diff --git a/src/gprs_ms.c b/src/gprs_ms.c index 57d8a19a..10d761d0 100644 --- a/src/gprs_ms.c +++ b/src/gprs_ms.c @@ -24,6 +24,7 @@ #include "pcu_utils.h" #include "nacc_fsm.h" #include "tbf_ul_ack_fsm.h" +#include "gprs_ms_storage.h" #include @@ -402,6 +403,32 @@ void ms_reset(struct GprsMs *ms) ms->imsi[0] = '\0'; } +/* This function should be called on the MS object of a TBF each time an RLCMAC + * block is received for it with TLLI information. + * Besides updating the TLLI field on the MS object, it also seeks for other MS + * objects in the store and merges them into the current MS object. The MS + * duplication happened because we don't learn the TLLI of the created TBF until + * a later point. */ +void ms_update_announced_tlli(struct GprsMs *ms, uint32_t tlli) +{ + struct GprsMs *old_ms = NULL; + + if (tlli == GSM_RESERVED_TMSI) + return; + + /* 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. */ + if (!ms_check_tlli(ms, tlli)) + old_ms = ms_store_get_ms(bts_ms_store(ms->bts), tlli, GSM_RESERVED_TMSI, NULL); + + ms_set_tlli(ms, tlli); + + if (old_ms) + ms_merge_and_clear_ms(ms, old_ms); + /* old_ms may no longer be available here */ +} + /* Merge 'old_ms' object into 'ms' object. * 'old_ms' may be freed during the call to this function, don't use the pointer to it afterwards */ void ms_merge_and_clear_ms(struct GprsMs *ms, struct GprsMs *old_ms) diff --git a/src/gprs_ms.h b/src/gprs_ms.h index 53b0cd60..41ef2ad7 100644 --- a/src/gprs_ms.h +++ b/src/gprs_ms.h @@ -119,6 +119,7 @@ void ms_set_current_cs_dl(struct GprsMs *ms, enum CodingScheme scheme); void ms_update_error_rate(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf, int error_rate); uint8_t ms_current_pacch_slots(const struct GprsMs *ms); +void ms_update_announced_tlli(struct GprsMs *ms, uint32_t tlli); void ms_merge_and_clear_ms(struct GprsMs *ms, struct GprsMs *old_ms); void ms_attach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf); diff --git a/src/gprs_ms_storage.cpp b/src/gprs_ms_storage.cpp index c9a41c9a..e49474f2 100644 --- a/src/gprs_ms_storage.cpp +++ b/src/gprs_ms_storage.cpp @@ -109,3 +109,8 @@ GprsMs *GprsMsStorage::create_ms() return ms; } + +struct GprsMs *ms_store_get_ms(struct GprsMsStorage *ms_store, uint32_t tlli, uint32_t old_tlli, const char *imsi) +{ + return ms_store->get_ms(tlli, old_tlli, imsi); +} diff --git a/src/gprs_ms_storage.h b/src/gprs_ms_storage.h index ef808d0c..45238cfe 100644 --- a/src/gprs_ms_storage.h +++ b/src/gprs_ms_storage.h @@ -23,6 +23,17 @@ struct gprs_rlcmac_bts; +#ifdef __cplusplus +extern "C" { +#endif +struct GprsMsStorage; +struct GprsMs *ms_store_get_ms(struct GprsMsStorage *ms_store, uint32_t tlli, uint32_t old_tlli, const char *imsi); +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + struct GprsMsStorage { public: GprsMsStorage(struct gprs_rlcmac_bts *bts); @@ -38,3 +49,5 @@ private: struct gprs_rlcmac_bts *m_bts; struct llist_head m_list; /* list of struct GprsMs */ }; + +#endif diff --git a/src/pdch.cpp b/src/pdch.cpp index 8dd7597e..e979cf05 100644 --- a/src/pdch.cpp +++ b/src/pdch.cpp @@ -367,8 +367,8 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, /* Reset N3101 counter: */ tbf->n_reset(N3101); - tbf->update_ms(tlli, GPRS_RLCMAC_UL_TBF); - /* Gather MS from TBF, since it may be NULL or may have been merged during update_ms */ + ms_update_announced_tlli(tbf->ms(), tlli); + /* Gather MS from TBF again, since it may be NULL or may have been merged during ms_update_announced_tlli */ ms = tbf->ms(); LOGPTBF(tbf, LOGL_DEBUG, "FN=%" PRIu32 " Rx Packet Control Ack (reason=%s)\n", diff --git a/src/tbf.cpp b/src/tbf.cpp index dfed320d..0ba04383 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -213,30 +213,6 @@ void gprs_rlcmac_tbf::set_ms(GprsMs *ms) ms_attach_tbf(m_ms, this); } -void gprs_rlcmac_tbf::update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction dir) -{ - GprsMs *old_ms = NULL; - - if (tlli == GSM_RESERVED_TMSI) - 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 - * IMSI in dl_tbf_handle() so there should be a unified solution */ - if (!ms_check_tlli(ms(), tlli)) - old_ms = bts_ms_store(bts)->get_ms(tlli, GSM_RESERVED_TMSI, NULL); - - if (dir == GPRS_RLCMAC_UL_TBF) - ms_set_tlli(ms(), tlli); - else - ms_confirm_tlli(ms(), tlli); - - if (old_ms) - ms_merge_and_clear_ms(ms(), old_ms); - /* old_ms may no longer be available here */ -} - static void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf) { int ts; diff --git a/src/tbf.h b/src/tbf.h index 616c3e0b..3146ee09 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -200,9 +200,6 @@ struct gprs_rlcmac_tbf { uint32_t tlli() const; bool is_tlli_valid() const; - /** MS updating */ - void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction); - uint8_t tfi() const; bool is_tfi_assigned() const; diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp index 07f562af..910bfb4d 100644 --- a/src/tbf_ul.cpp +++ b/src/tbf_ul.cpp @@ -397,7 +397,7 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged( LOGPTBFUL(this, LOGL_INFO, "Decoded premier TLLI=0x%08x of UL DATA TFI=%d.\n", new_tlli, rlc->tfi); - update_ms(new_tlli, GPRS_RLCMAC_UL_TBF); + ms_update_announced_tlli(ms(), new_tlli); bts_pch_timer_stop(bts, ms()); } else if (new_tlli != GSM_RESERVED_TMSI && new_tlli != tlli()) { LOGPTBFUL(this, LOGL_NOTICE, diff --git a/tests/alloc/AllocTest.cpp b/tests/alloc/AllocTest.cpp index e124b645..379e69a9 100644 --- a/tests/alloc/AllocTest.cpp +++ b/tests/alloc/AllocTest.cpp @@ -269,7 +269,7 @@ static inline bool test_alloc_b_dl_ul(bool ts0, bool ts1, bool ts2, bool ts3, bo if (!dl_tbf) return false; - dl_tbf->update_ms(0x23, GPRS_RLCMAC_DL_TBF); + ms_confirm_tlli(ms, 0x23); OSMO_ASSERT(dl_tbf->ms() == ms); OSMO_ASSERT(ms_current_trx(dl_tbf->ms())); @@ -279,7 +279,7 @@ static inline bool test_alloc_b_dl_ul(bool ts0, bool ts1, bool ts2, bool ts3, bo if (!ul_tbf) return false; - ul_tbf->update_ms(0x23, GPRS_RLCMAC_UL_TBF); + ms_update_announced_tlli(ms, 0x23); ul_tbf->m_contention_resolution_done = true; dump_assignment(ul_tbf, "UL", verbose); diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp index 96fede77..60e242ca 100644 --- a/tests/tbf/TbfTest.cpp +++ b/tests/tbf/TbfTest.cpp @@ -126,7 +126,7 @@ static void test_tbf_tlli_update() gprs_rlcmac_tbf *dl_tbf = dl_tbf_alloc(bts, ms, 0, false); OSMO_ASSERT(dl_tbf != NULL); - dl_tbf->update_ms(0x2342, GPRS_RLCMAC_DL_TBF); + ms_confirm_tlli(ms, 0x2342); dl_tbf->set_ta(4); OSMO_ASSERT(ms_dl_tbf(ms) == dl_tbf); OSMO_ASSERT(dl_tbf->ms() == ms); @@ -134,7 +134,7 @@ static void test_tbf_tlli_update() gprs_rlcmac_tbf *ul_tbf = ul_tbf_alloc(bts, ms, 0, false); OSMO_ASSERT(ul_tbf != NULL); - ul_tbf->update_ms(0x2342, GPRS_RLCMAC_UL_TBF); + ms_update_announced_tlli(ms, 0x2342); OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); OSMO_ASSERT(ul_tbf->ms() == ms); @@ -144,7 +144,7 @@ static void test_tbf_tlli_update() * Now check.. that DL changes and that the timing advance * has changed. */ - dl_tbf->update_ms(0x4232, GPRS_RLCMAC_DL_TBF); + ms_confirm_tlli(dl_tbf->ms(), 0x4232); /* It is still there, since the new TLLI has not been used for UL yet */ ms_new = bts_ms_by_tlli(bts, 0x2342, GSM_RESERVED_TMSI); @@ -156,7 +156,7 @@ static void test_tbf_tlli_update() OSMO_ASSERT(ms_ul_tbf(ms) == ul_tbf); /* Now use the new TLLI for UL */ - ul_tbf->update_ms(0x4232, GPRS_RLCMAC_UL_TBF); + ms_update_announced_tlli(ms, 0x4232); ms_new = bts_ms_by_tlli(bts, 0x2342, GSM_RESERVED_TMSI); OSMO_ASSERT(ms_new == NULL); @@ -305,7 +305,7 @@ static void test_tbf_final_ack(enum test_tbf_final_ack_mode test_mode) setup_bts(bts, ts_no); dl_tbf = create_dl_tbf(bts, ms_class, 0, &trx_no); - dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms_confirm_tlli(dl_tbf->ms(), tlli); ms = dl_tbf->ms(); for (i = 0; i < sizeof(llc_data); i++) @@ -381,7 +381,7 @@ static void test_tbf_delayed_release() OSMO_ASSERT(osmo_tdef_set(the_pcu->T_defs, -2031, 200, OSMO_TDEF_MS) == 0); dl_tbf = create_dl_tbf(bts, ms_class, 0, &trx_no); - dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms_confirm_tlli(dl_tbf->ms(), tlli); for (i = 0; i < sizeof(llc_data); i++) llc_data[i] = i%256; @@ -446,8 +446,8 @@ static void test_tbf_imsi() dl_tbf[0] = create_dl_tbf(bts, ms_class, 0, &trx_no); dl_tbf[1] = create_dl_tbf(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); + ms_confirm_tlli(dl_tbf[0]->ms(), 0xf1000001); + ms_confirm_tlli(dl_tbf[1]->ms(), 0xf1000002); ms_set_imsi(dl_tbf[0]->ms(), "001001000000001"); ms1 = bts_ms_store(bts)->get_ms(GSM_RESERVED_TMSI, GSM_RESERVED_TMSI, "001001000000001"); @@ -2634,7 +2634,7 @@ static void test_tbf_epdan_out_of_rx_window(void) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; dl_tbf = create_dl_tbf(bts, ms_class, egprs_ms_class, &trx_no); - dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms_confirm_tlli(dl_tbf->ms(), tlli); prlcdlwindow = static_cast(dl_tbf->window()); prlcmvb = &prlcdlwindow->m_v_b; prlcdlwindow->m_v_s = 1288; @@ -2767,7 +2767,7 @@ static void establish_and_use_egprs_dl_tbf(struct gprs_rlcmac_bts *bts, int mcs) bts->initial_mcs_dl = mcs; dl_tbf = create_dl_tbf(bts, ms_class, egprs_ms_class, &trx_no); - dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms_confirm_tlli(dl_tbf->ms(), tlli); for (i = 0; i < sizeof(llc_data); i++) llc_data[i] = i%256; @@ -2824,7 +2824,7 @@ static gprs_rlcmac_dl_tbf *tbf_init(struct gprs_rlcmac_bts *bts, bts->initial_mcs_dl = mcs; dl_tbf = create_dl_tbf(bts, ms_class, egprs_ms_class, &trx_no); - dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms_confirm_tlli(dl_tbf->ms(), tlli); for (i = 0; i < sizeof(test_data); i++) test_data[i] = i%256; @@ -3344,7 +3344,7 @@ void test_packet_access_rej_epdan() setup_bts(bts, 4); static gprs_rlcmac_dl_tbf *dl_tbf = tbf_init(bts, 1); - dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + ms_confirm_tlli(dl_tbf->ms(), tlli); osmo_fsm_inst_dispatch(dl_tbf->ul_ass_fsm.fi, TBF_UL_ASS_EV_SCHED_ASS_REJ, NULL); struct msgb *msg = tbf_ul_ass_create_rlcmac_msg((const struct gprs_rlcmac_tbf*)dl_tbf, 0, 0);