aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2015-08-16 18:19:32 +0200
committerJacob Erlbeck <jerlbeck@sysmocom.de>2015-08-17 16:23:01 +0200
commit28c40b17574a2dc792278baffb6f4f87e3559bb6 (patch)
treea3fd8c7bc9ffc04279e19979ce6d63e951ecaf2c /src
parent3449a61032cbf91f1a042e02264142b4df3d61a7 (diff)
tbf: Clean old MS objects if they have the same TLLI
Currently if an MS retries to access the PCU by using RACH and if there is already an entry for that MS, a duplicated MS object referring to the same TLLI is created. This is caused by blindly setting the TLLI without querying the MS storage to avoid inconsitencies. This leads to several entries in the MS storage that are assigned to the same TLLI. If that happens, 'show ms all' can display multiple entries with the same TLLI (note that an MS object can belong to several TLLIs, so there might be an intersection that is not visible in the list) or 'show tbf all' can show entries with MS_CLASS == 0 in some cases. This commit changes update_ms() to merge and clean up old entries that belong to the given TLLI if they exist. Some data (like the MS class) is copied to the new MS object. Note that TBF belonging to the old MS object are deleted immediately if they have not registered a timer. Sponsored-by: On-Waves ehf
Diffstat (limited to 'src')
-rw-r--r--src/tbf.cpp58
-rw-r--r--src/tbf.h1
2 files changed, 58 insertions, 1 deletions
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];