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
diff --git a/tests/ms/MsTest.cpp b/tests/ms/MsTest.cpp
index 0895e4d..01f2642 100644
--- a/tests/ms/MsTest.cpp
+++ b/tests/ms/MsTest.cpp
@@ -232,6 +232,99 @@
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 @@
test_ms_state();
test_ms_callback();
test_ms_replace_tbf();
+ test_ms_change_tlli();
test_ms_storage();
if (getenv("TALLOC_REPORT_FULL"))