Rework tbf::update_ms()

That function was pretty confusing since it used a "enum
gprs_rlcmac_tbf_direction dir" param (whose type is expected to describe
the data direction of a TBF) to describe the direction of the the packet
which triggered its call.
The parameter was actually always called with "GPRS_RLCMAC_UL_TBF" which
in this case meant "uplink direction" which meant "TLLI was updated from
the MS, not the SGSN".
The DL direction was only used in unit tests, which can hence be simply
replaced by ms_confirm_tlli(), which this commit does.
So this update_ms() function was actually used in practice in osmo-pcu
to trigger update of TLLI and find duplicates only when an RLCMAC block
(control or data) was received from the MS. Therefore, this function is
renamed in this patch and moved to the gprs_ms class, since it really
does nothing with the TBF.

Related: OS#5700
Change-Id: I1b7c0fde15b9bb8a973068994dbe972285ad0aff
diff --git a/src/gprs_ms.c b/src/gprs_ms.c
index 57d8a19..10d761d 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 <time.h>
 
@@ -402,6 +403,32 @@
 	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)