From d48c336934d3845ca49d69c3b77b0a4a4b71bb5c Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Mon, 11 Jul 2016 12:47:31 +0200
Subject: [PATCH] hotfix: better management of s-tmsi reconnect

The code was changing the rnti in the red-black tree without
removing/reinserting the context. This is wrong because the
rnti is a key of the red-black tree and you cannot change the
key in a stored item at will.

There are also modifications of the function mac_eNB_rrc_ul_failure
which has to remove the UE in any case.

And rrc_mac_remove_ue has been changed for the case where
the UE is not found.
---
 .../LAYER2/MAC/eNB_scheduler_primitives.c     |  6 ++++++
 openair2/RRC/LITE/L2_interface.c              | 13 ++++++------
 openair2/RRC/LITE/rrc_eNB.c                   | 21 ++++++++++++++++---
 3 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
index 80a1dbc76a..bb9e7b3d30 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
@@ -298,6 +298,12 @@ int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP)
   int UE_id = find_UE_id(mod_idP,rntiP);
   int pCC_id = UE_PCCID(mod_idP,UE_id);
 
+  if (UE_id == -1) {
+    LOG_W(MAC,"rrc_mac_remove_ue: UE %x not found\n", rntiP);
+    mac_phy_remove_ue(mod_idP,rntiP);
+    return 0;
+  }
+
   LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",UE_id,pCC_id, rntiP);
   dump_ue_list(UE_list,0);
 
diff --git a/openair2/RRC/LITE/L2_interface.c b/openair2/RRC/LITE/L2_interface.c
index a28f2b1894..d4ddd0e7ab 100644
--- a/openair2/RRC/LITE/L2_interface.c
+++ b/openair2/RRC/LITE/L2_interface.c
@@ -719,12 +719,12 @@ mac_eNB_get_rrc_status(
   }
 }
 
-void mac_eNB_rrc_ul_failure(const module_id_t Mod_instP, 
-			    const int CC_idP, 
+void mac_eNB_rrc_ul_failure(const module_id_t Mod_instP,
+			    const int CC_idP,
 			    const frame_t frameP,
 			    const sub_frame_t subframeP,
-			    const rnti_t rntiP) {
-
+			    const rnti_t rntiP)
+{
   struct rrc_eNB_ue_context_s* ue_context_p = NULL;
   ue_context_p = rrc_eNB_get_ue_context(
                    &eNB_rrc_inst[Mod_instP],
@@ -735,10 +735,9 @@ void mac_eNB_rrc_ul_failure(const module_id_t Mod_instP,
     ue_context_p->ue_context.ul_failure_timer=1;
   }
   else {
-    LOG_W(RRC,"Frame %d, Subframe %d: UE %x unknown \n",frameP,subframeP,rntiP);
-    rrc_mac_remove_ue(Mod_instP,rntiP);
+    LOG_W(RRC,"Frame %d, Subframe %d: UL failure: UE %x unknown \n",frameP,subframeP,rntiP);
   }
-  
+  rrc_mac_remove_ue(Mod_instP,rntiP);
 }
 
 void mac_eNB_rrc_ul_in_sync(const module_id_t Mod_instP, 
diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c
index c85e61a0a4..2828209d62 100644
--- a/openair2/RRC/LITE/rrc_eNB.c
+++ b/openair2/RRC/LITE/rrc_eNB.c
@@ -3790,14 +3790,29 @@ rrc_eNB_decode_ccch(
 		//#warning "TODO: stmsi_exist: remove UE from MAC/PHY (how?)"
 	      LOG_I(RRC," S-TMSI exists, ue_context_p %p\n",ue_context_p);
 	      stmsi_received=1;
+              /* replace rnti in the context */
+              /* for that, remove the context from the RB tree */
+              RB_REMOVE(rrc_ue_tree_s, &eNB_rrc_inst[ctxt_pP->module_id].rrc_ue_head, ue_context_p);
+              /* and insert again, after changing rnti everywhere it has to be changed */
+              ue_context_p->ue_id_rnti = ctxt_pP->rnti;
 	      ue_context_p->ue_context.rnti = ctxt_pP->rnti;
+              RB_INSERT(rrc_ue_tree_s, &eNB_rrc_inst[ctxt_pP->module_id].rrc_ue_head, ue_context_p);
+              /* reset timers */
+              ue_context_p->ue_context.ul_failure_timer = 0;
+              ue_context_p->ue_context.ue_release_timer = 0;
 	      //   AssertFatal(0 == 1, "TODO: remove UE from MAC/PHY (how?)");
 	      //              ue_context_p = NULL;
             } else {
               ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, NOT_A_RANDOM_UE_IDENTITY);
-	      ue_context_p->ue_context.Initialue_identity_s_TMSI.presence = TRUE;
-	      ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code = mme_code;
-	      ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi = m_tmsi;
+              if (ue_context_p == NULL)
+                LOG_E(RRC, "%s:%d:%s: rrc_eNB_get_next_free_ue_context returned NULL\n", __FILE__, __LINE__, __FUNCTION__);
+              if (ue_context_p != NULL) {
+	        ue_context_p->ue_context.Initialue_identity_s_TMSI.presence = TRUE;
+	        ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code = mme_code;
+	        ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi = m_tmsi;
+              } else {
+                break;
+              }
             }
 
             MSC_LOG_RX_MESSAGE(
-- 
2.26.2