tbf: Always call set_tlli/confirm_tlli in update_ms

Currently the m_tlli member in GprsMs is set by the constructor,
circumventing the TLLI confirmation mechanism.

This commit replaces the get_or_create_ms() method by a create_ms()
method which takes the TLLI and the direction (UL or DL) as
parameters to select either set_tlli() or confirm_tlli(). The MS
object is instantiated with TLLI = 0, and therefore GprsMs::tlli() is
extended to return the DL TLLI if both of the other TLLI are not set.

Note that create_ms() will not check whether an MS object with a
matching TLLI is already stored in the list, so it should only be
called after a corresponding get_ms() in general.

Sponsored-by: On-Waves ehf
diff --git a/src/gprs_ms.h b/src/gprs_ms.h
index ac1928e..e84ff9e 100644
--- a/src/gprs_ms.h
+++ b/src/gprs_ms.h
@@ -89,7 +89,9 @@
 
 inline uint32_t GprsMs::tlli() const
 {
-	return m_new_ul_tlli ? m_new_ul_tlli : m_tlli;
+	return m_new_ul_tlli ? m_new_ul_tlli :
+	       m_tlli        ? m_tlli :
+			       m_new_dl_tlli;
 }
 
 inline bool GprsMs::check_tlli(uint32_t tlli)
diff --git a/src/gprs_ms_storage.cpp b/src/gprs_ms_storage.cpp
index 4f72c86..1cdb753 100644
--- a/src/gprs_ms_storage.cpp
+++ b/src/gprs_ms_storage.cpp
@@ -71,14 +71,20 @@
 	return ms;
 }
 
-GprsMs *GprsMsStorage::get_or_create_ms(uint32_t tlli, uint32_t old_tlli, const char *imsi)
+GprsMs *GprsMsStorage::create_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction dir)
 {
-	GprsMs *ms = get_ms(tlli, old_tlli, imsi);
+	GprsMs *ms = get_ms(tlli);
 
 	if (ms)
 		return ms;
 
-	ms = new GprsMs(tlli);
+	ms = new GprsMs(0);
+
+	if (dir == GPRS_RLCMAC_UL_TBF)
+		ms->set_tlli(tlli);
+	else
+		ms->confirm_tlli(tlli);
+
 	ms->set_callback(this);
 	llist_add(&ms->list(), &m_list);
 
diff --git a/src/gprs_ms_storage.h b/src/gprs_ms_storage.h
index 1eef28f..fff9638 100644
--- a/src/gprs_ms_storage.h
+++ b/src/gprs_ms_storage.h
@@ -22,6 +22,7 @@
 
 #include "gprs_ms.h"
 #include "cxx_linuxlist.h"
+#include "tbf.h"
 #include <stdint.h>
 #include <stddef.h>
 
@@ -34,7 +35,7 @@
 	virtual void ms_active(class GprsMs *);
 
 	GprsMs *get_ms(uint32_t tlli, uint32_t old_tlli = 0, const char *imsi = 0) const;
-	GprsMs *get_or_create_ms(uint32_t tlli, uint32_t old_tlli = 0, const char *imsi = 0);
+	GprsMs *create_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction dir);
 
 private:
 	LListHead<GprsMs> m_list;
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 8f8e538..51b2aa5 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -98,9 +98,16 @@
 
 void gprs_rlcmac_tbf::update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction dir)
 {
-	if (!ms())
-		set_ms(bts->ms_store().get_or_create_ms(tlli));
-	else if (dir == GPRS_RLCMAC_UL_TBF)
+	if (!ms()) {
+		GprsMs *new_ms = bts->ms_store().get_ms(tlli);
+		if (!new_ms)
+			new_ms = bts->ms_store().create_ms(tlli, dir);
+
+		set_ms(new_ms);
+		return;
+	}
+
+	if (dir == GPRS_RLCMAC_UL_TBF)
 		ms()->set_tlli(tlli);
 	else
 		ms()->confirm_tlli(tlli);