From 27c3074ff96f2632b332b719ccd7adce6c889917 Mon Sep 17 00:00:00 2001
From: Xu Bo <xubo1@cn.fujtisu.com>
Date: Mon, 8 Jan 2018 15:27:54 +0900
Subject: [PATCH] fix RRCConnectionReestablishment issue when multiple
 RRCConnectionReestablishment happen

---
 cmake_targets/CMakeLists.txt                  |   1 +
 openair1/PHY/LTE_TRANSPORT/dci_tools.c        |   2 +-
 openair1/SCHED/phy_procedures_lte_eNb.c       |   4 +-
 openair2/LAYER2/MAC/defs.h                    |   2 +
 openair2/LAYER2/MAC/eNB_scheduler.c           |  39 ++++-
 .../LAYER2/MAC/eNB_scheduler_primitives.c     |   1 +
 openair2/LAYER2/MAC/extern.h                  |   2 -
 openair2/RRC/LITE/MESSAGES/asn1_msg.c         |   2 +-
 openair2/RRC/LITE/defs.h                      |   6 +
 openair2/RRC/LITE/rrc_common.c                |  46 +++++-
 openair2/RRC/LITE/rrc_eNB.c                   | 143 ++++++++++++++++--
 openair2/RRC/LITE/rrc_eNB_S1AP.c              |   1 +
 openair2/RRC/LITE/rrc_eNB_UE_context.c        |  14 ++
 openair3/GTPV1-U/gtpv1u_eNB.c                 |  65 ++++++--
 14 files changed, 294 insertions(+), 34 deletions(-)

diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index b24db90edb..89d17cb279 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1936,6 +1936,7 @@ add_executable(oaisim_nos1
   ${OPENAIR_BIN_DIR}/messages_xml.h
   ${OPENAIR_TARGETS}/RT/USER/lte-ue.c
   ${OPENAIR_TARGETS}/RT/USER/lte-ru.c
+  ${OPENAIR_TARGETS}/RT/USER/lte-enb.c
   ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
   ${OPENAIR_TARGETS}/SIMU/USER/channel_sim.c
   ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c
diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
index 97a9709df5..ea6d850196 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
@@ -6492,7 +6492,7 @@ uint8_t pdcch_alloc2ul_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t n)
   else
     ul_subframe = ((n+4)%10);
 
-  if (subframe_select(frame_parms,ul_subframe) != SF_UL) return(255);
+  if ((subframe_select(frame_parms,ul_subframe) != SF_UL) && (frame_parms->frame_type == TDD)) return(255);
 
   LOG_D(PHY, "subframe %d: PUSCH subframe = %d\n", n, ul_subframe);
   return ul_subframe;
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index c99776e7e5..d2d38a88be 100644
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -834,10 +834,10 @@ void uci_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
 	if (uci->type == SR) {
 	  if (SR_payload == 1) {
 	    fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);
-	    return;
+        continue;
 	  }
 	  else {
-	    return;
+        continue;
 	  }
 	}
       case HARQ:
diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h
index e4c931ea51..78a74f00d3 100644
--- a/openair2/LAYER2/MAC/defs.h
+++ b/openair2/LAYER2/MAC/defs.h
@@ -835,6 +835,8 @@ typedef struct {
     int32_t cqi_req_timer;
     int32_t ul_inactivity_timer;
     int32_t ul_failure_timer;
+    uint32_t ue_reestablishment_reject_timer;
+    uint32_t ue_reestablishment_reject_timer_thres;
     int32_t ul_scheduled;
     int32_t ra_pdcch_order_sent;
     int32_t ul_out_of_sync;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c
index de4213f6eb..38a34d5eec 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler.c
@@ -163,7 +163,7 @@ schedule_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
 						   (nfapi_ul_config_srs_pdu));
 				ul_config_pdu->srs_pdu.srs_pdu_rel8.size =
 				    (uint8_t)
-				    sizeof(nfapi_ul_config_srs_pdu);;
+				    sizeof(nfapi_ul_config_srs_pdu);
 				ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti =
 				    UE_list->UE_template[CC_id][UE_id].
 				    rnti;
@@ -549,7 +549,7 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id,
 
 	UE_list->UE_sched_ctrl[UE_id].ul_failure_timer++;
 	// check threshold
-	if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 200) {
+	if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 20000) {
 	    // inform RRC of failure and clear timer
 	    LOG_I(MAC,
 		  "UE %d rnti %x: UL Failure after repeated PDCCH orders: Triggering RRC \n",
@@ -707,6 +707,41 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP,
 	      ul_inactivity_timer,
 	      RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].cqi_req_timer);
 	check_ul_failure(module_idP, CC_id, i, frameP, subframeP);
+ 
+      if (RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer > 0) {
+         RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer++;
+         if(RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer >=
+            RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer_thres) {
+             RC.mac[module_idP]->UE_list.UE_sched_ctrl[i].ue_reestablishment_reject_timer = 0;
+             for (int ii=0; ii<NUMBER_OF_UE_MAX; ii++) {
+                 LTE_eNB_ULSCH_t *ulsch = NULL;
+                 ulsch = RC.eNB[module_idP][CC_id]->ulsch[ii];
+                 if((ulsch != NULL) && (ulsch->rnti == rnti)){
+                     LOG_I(MAC, "clean_eNb_ulsch UE %x \n", rnti);
+                     clean_eNb_ulsch(ulsch);
+                     break;
+                 }
+             }
+
+             for(int j = 0; j < 10; j++){
+                 nfapi_ul_config_request_body_t *ul_req_tmp = NULL;
+                 ul_req_tmp = &RC.mac[module_idP]->UL_req_tmp[CC_id][j].ul_config_request_body;
+                 if(ul_req_tmp){
+                     int pdu_number = ul_req_tmp->number_of_pdus;
+                     for(int pdu_index = pdu_number-1; pdu_index >= 0; pdu_index--){
+                         if(ul_req_tmp->ul_config_pdu_list[pdu_index].ulsch_pdu.ulsch_pdu_rel8.rnti == rnti){
+                             LOG_I(MAC, "remove UE %x from ul_config_pdu_list %d/%d\n", rnti, pdu_index, pdu_number);
+                             if(pdu_index < pdu_number -1){
+                                 memcpy(&ul_req_tmp->ul_config_pdu_list[pdu_index], &ul_req_tmp->ul_config_pdu_list[pdu_index+1], (pdu_number-1-pdu_index) * sizeof(nfapi_ul_config_request_pdu_t));
+                             }
+                             ul_req_tmp->number_of_pdus--;
+                         }
+                     }
+                 }
+             }
+             rrc_mac_remove_ue(module_idP,rnti);
+         }
+      }
 
     }
 
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
index 05d8e8dc2d..b1d66b0946 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
@@ -2075,6 +2075,7 @@ int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP, int harq_pidP
 	       sizeof(UE_sched_ctrl));
 	memset((void *) &UE_list->eNB_UE_stats[cc_idP][UE_id], 0,
 	       sizeof(eNB_UE_STATS));
+    UE_list->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0;
 
 	UE_list->UE_sched_ctrl[UE_id].ta_update = 31;
 
diff --git a/openair2/LAYER2/MAC/extern.h b/openair2/LAYER2/MAC/extern.h
index db0aac7768..d0c8706ad6 100644
--- a/openair2/LAYER2/MAC/extern.h
+++ b/openair2/LAYER2/MAC/extern.h
@@ -101,6 +101,4 @@ extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu1;
 extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2;
 extern DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu1E;
 
-extern uint16_t reestablish_rnti_map[NUMBER_OF_UE_MAX][2];
-
 #endif //DEF_H
diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.c b/openair2/RRC/LITE/MESSAGES/asn1_msg.c
index 163950950e..db5ce5db95 100644
--- a/openair2/RRC/LITE/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.c
@@ -233,7 +233,7 @@ uint8_t do_MIB(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_t phich
 
   AssertFatal(phich_Resource <= PHICH_Config__phich_Resource_two,"Illegal phich_Resource\n");
   mib->message.phich_Config.phich_Resource = phich_Resource;
-  AssertFatal(phich_Resource <= PHICH_Config__phich_Duration_extended,"Illegal phich_Duration\n");
+  AssertFatal(phich_duration <= PHICH_Config__phich_Duration_extended,"Illegal phich_Duration\n");
   mib->message.phich_Config.phich_Duration = phich_duration;
   LOG_I(RRC,"[MIB] systemBandwidth %x, phich_duration %x, phich_resource %x,sfn %x\n",
          (uint32_t)mib->message.dl_Bandwidth,
diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h
index fa9a2161fc..0a66184998 100644
--- a/openair2/RRC/LITE/defs.h
+++ b/openair2/RRC/LITE/defs.h
@@ -451,6 +451,12 @@ typedef struct eNB_RRC_UE_s {
   uint32_t                           ul_failure_timer;
   uint32_t                           ue_release_timer;
   uint32_t                           ue_release_timer_thres;
+  uint32_t                           ue_release_timer_s1;
+  uint32_t                           ue_release_timer_thres_s1;
+  uint32_t                           ue_release_timer_rrc;
+  uint32_t                           ue_release_timer_thres_rrc;
+  uint32_t                           ue_reestablishment_timer;
+  uint32_t                           ue_reestablishment_timer_thres;
   uint8_t                            e_rab_release_command_flag;
 } eNB_RRC_UE_t;
 
diff --git a/openair2/RRC/LITE/rrc_common.c b/openair2/RRC/LITE/rrc_common.c
index 718c8c63f3..f8cfbdc12a 100644
--- a/openair2/RRC/LITE/rrc_common.c
+++ b/openair2/RRC/LITE/rrc_common.c
@@ -333,26 +333,58 @@ rrc_rx_tx(
     RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) {
       if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe==0)) {
 	if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) {
-	  LOG_I(RRC,"UE rnti %x:S-TMSI %x failure timer %d/20000\n",
+	  LOG_I(RRC,"UE rnti %x:S-TMSI %x failure timer %d/8\n",
 		ue_context_p->ue_context.rnti,
 		ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi,
 		ue_context_p->ue_context.ul_failure_timer);
 	}
 	else {
-	  LOG_I(RRC,"UE rnti %x failure timer %d/20000\n",
+	  LOG_I(RRC,"UE rnti %x failure timer %d/8\n",
 		ue_context_p->ue_context.rnti,
 		ue_context_p->ue_context.ul_failure_timer);
 	}
       }
       if (ue_context_p->ue_context.ul_failure_timer>0) {
 	ue_context_p->ue_context.ul_failure_timer++;
-	if (ue_context_p->ue_context.ul_failure_timer >= 20000) {
+	if (ue_context_p->ue_context.ul_failure_timer >= 8) {
 	  // remove UE after 20 seconds after MAC has indicated UL failure
 	  LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti);
 	  ue_to_be_removed = ue_context_p;
 	  break;
 	}
       }
+      if (ue_context_p->ue_context.ue_release_timer_s1>0) {
+        ue_context_p->ue_context.ue_release_timer_s1++;
+        if (ue_context_p->ue_context.ue_release_timer_s1 >=
+            ue_context_p->ue_context.ue_release_timer_thres_s1) {
+          LOG_I(RRC,"Removing UE %x instance Because of UE_CONTEXT_RELEASE_COMMAND not received after %d ms from sending request\n",
+        		  ue_context_p->ue_context.rnti, ue_context_p->ue_context.ue_release_timer_thres_s1);
+          ue_to_be_removed = ue_context_p;
+          break;
+        }
+      }
+
+      if (ue_context_p->ue_context.ue_release_timer_rrc>0) {
+        ue_context_p->ue_context.ue_release_timer_rrc++;
+        if (ue_context_p->ue_context.ue_release_timer_rrc >=
+          ue_context_p->ue_context.ue_release_timer_thres_rrc) {
+          LOG_I(RRC,"Removing UE %x instance After UE_CONTEXT_RELEASE_Complete\n", ue_context_p->ue_context.rnti);
+          ue_to_be_removed = ue_context_p;
+          break;
+        }
+      }
+
+      if (ue_context_p->ue_context.ue_reestablishment_timer>0) {
+        ue_context_p->ue_context.ue_reestablishment_timer++;
+        if (ue_context_p->ue_context.ue_reestablishment_timer >=
+            ue_context_p->ue_context.ue_reestablishment_timer_thres) {
+          LOG_I(RRC,"UE %d reestablishment_timer max\n",ue_context_p->ue_context.rnti);
+          ue_context_p->ue_context.ul_failure_timer = 20000;
+          ue_to_be_removed = ue_context_p;
+          ue_context_p->ue_context.ue_reestablishment_timer = 0;
+          break;
+        }
+      }
       if (ue_context_p->ue_context.ue_release_timer>0) {
 	ue_context_p->ue_context.ue_release_timer++;
 	if (ue_context_p->ue_context.ue_release_timer >= 
@@ -364,8 +396,14 @@ rrc_rx_tx(
       }
     }
     if (ue_to_be_removed) {
+      if(ue_to_be_removed->ue_context.ul_failure_timer >= 8) {
+          ue_to_be_removed->ue_context.ue_release_timer_s1 = 1;
+          ue_to_be_removed->ue_context.ue_release_timer_thres_s1 = 100;
+          ue_to_be_removed->ue_context.ue_release_timer = 0;
+          ue_to_be_removed->ue_context.ue_reestablishment_timer = 0;
+      }
       rrc_eNB_free_UE(ctxt_pP->module_id,ue_to_be_removed);
-      if(ue_to_be_removed->ue_context.ul_failure_timer >= 20000){
+      if(ue_to_be_removed->ue_context.ul_failure_timer >= 8){
         ue_to_be_removed->ue_context.ul_failure_timer = 0;
       }
     }
diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c
index 5817319198..24571ad4f7 100644
--- a/openair2/RRC/LITE/rrc_eNB.c
+++ b/openair2/RRC/LITE/rrc_eNB.c
@@ -572,6 +572,7 @@ rrc_eNB_get_next_free_ue_context(
 					ctxt_pP->rnti);
 
   if (ue_context_p == NULL) {
+#if 0
     RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) {
       if (ue_context_p->ue_context.random_ue_identity == ue_identityP) {
         LOG_D(RRC,
@@ -582,6 +583,7 @@ rrc_eNB_get_next_free_ue_context(
         return NULL;
       }
     }
+#endif
     ue_context_p = rrc_eNB_allocate_new_UE_context(RC.rrc[ctxt_pP->module_id]);
 
     if (ue_context_p == NULL) {
@@ -801,7 +803,11 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s*
   (void)ue_module_id;
 #endif
   rnti_t rnti = ue_context_pP->ue_context.rnti;
-
+  int i, j , CC_id, pdu_number;
+  LTE_eNB_ULSCH_t *ulsch = NULL;
+  nfapi_ul_config_request_body_t *ul_req_tmp = NULL;
+  PHY_VARS_eNB *eNB_PHY = NULL;
+  eNB_MAC_INST *eNB_MAC = RC.mac[enb_mod_idP];
 
   AssertFatal(enb_mod_idP < NB_eNB_INST, "eNB inst invalid (%d/%d) for UE %x!", enb_mod_idP, NB_eNB_INST, rnti);
   /*  ue_context_p = rrc_eNB_get_ue_context(
@@ -814,7 +820,8 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s*
     LOG_W(RRC, "[eNB %d] Removing UE RNTI %x\n", enb_mod_idP, rnti);
 
 #if defined(ENABLE_USE_MME)
-   if( ue_context_pP->ue_context.ul_failure_timer >= 20000 ) {
+   if( ue_context_pP->ue_context.ul_failure_timer >= 8 ) {
+	LOG_I(RRC, "[eNB %d] S1AP_UE_CONTEXT_RELEASE_REQ RNTI %x\n", enb_mod_idP, rnti);
     rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 21); // send cause 21: connection with ue lost
     /* From 3GPP 36300v10 p129 : 19.2.2.2.2 S1 UE Context Release Request (eNB triggered)
      * If the E-UTRAN internal reason is a radio link failure detected in the eNB, the eNB shall wait a sufficient time before
@@ -833,7 +840,33 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s*
     oai_emulation.info.eNB_ue_module_id_to_rnti[enb_mod_idP][ue_module_id] = NOT_A_RNTI;
 #endif
 #endif
+    for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
+      eNB_PHY = RC.eNB[enb_mod_idP][CC_id];
+      for (i=0; i<NUMBER_OF_UE_MAX; i++) {
+        ulsch = eNB_PHY->ulsch[i];
+        if((ulsch != NULL) && (ulsch->rnti == rnti)){
+          LOG_I(RRC, "clean_eNb_ulsch UE %x \n", rnti);
+          clean_eNb_ulsch(ulsch);
+          break;
+        }
+      }
 
+      for(j = 0; j < 10; j++){
+        ul_req_tmp = &eNB_MAC->UL_req_tmp[CC_id][j].ul_config_request_body;
+        if(ul_req_tmp){
+          pdu_number = ul_req_tmp->number_of_pdus;
+          for(int pdu_index = pdu_number-1; pdu_index >= 0; pdu_index--){
+            if(ul_req_tmp->ul_config_pdu_list[pdu_index].ulsch_pdu.ulsch_pdu_rel8.rnti == rnti){
+              LOG_I(RRC, "remove UE %x from ul_config_pdu_list %d/%d\n", rnti, pdu_index, pdu_number);
+              if(pdu_index < pdu_number -1){
+                memcpy(&ul_req_tmp->ul_config_pdu_list[pdu_index], &ul_req_tmp->ul_config_pdu_list[pdu_index+1], (pdu_number-1-pdu_index) * sizeof(nfapi_ul_config_request_pdu_t));
+              }
+              ul_req_tmp->number_of_pdus--;
+            }
+          }
+        }
+      }
+    }
     rrc_mac_remove_ue(enb_mod_idP,rnti);
     rrc_rlc_remove_ue(&ctxt);
     pdcp_remove_UE(&ctxt);
@@ -1158,9 +1191,13 @@ rrc_eNB_generate_RRCConnectionReestablishment(
         RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size);
 
   // activate release timer, if RRCComplete not received after 10 frames, remove UE
-  ue_context_pP->ue_context.ue_release_timer = 1;
+  //ue_context_pP->ue_context.ue_release_timer = 1;
   // remove UE after 10 frames after RRCConnectionReestablishmentRelease is triggered
-  ue_context_pP->ue_context.ue_release_timer_thres = 100;
+  //ue_context_pP->ue_context.ue_release_timer_thres = 100;
+    // activate release timer, if RRCComplete not received after 100 frames, remove UE
+  ue_context_pP->ue_context.ue_reestablishment_timer = 1;
+  // remove UE after 100 frames after RRCConnectionReestablishmentRelease is triggered
+  ue_context_pP->ue_context.ue_reestablishment_timer_thres = 1000;
 }
 
 //-----------------------------------------------------------------------------
@@ -1742,6 +1779,38 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete(
   // delete UE data of prior RNTI.  UE use current RNTI.
   protocol_ctxt_t ctxt_prior = *ctxt_pP;
   ctxt_prior.rnti = reestablish_rnti;
+
+  LTE_eNB_ULSCH_t *ulsch = NULL;
+  nfapi_ul_config_request_body_t *ul_req_tmp = NULL;
+  PHY_VARS_eNB *eNB_PHY = NULL;
+  eNB_MAC_INST *eNB_MAC = RC.mac[ctxt_prior.module_id];
+  for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
+    eNB_PHY = RC.eNB[ctxt_prior.module_id][CC_id];
+    for (int i=0; i<NUMBER_OF_UE_MAX; i++) {
+      ulsch = eNB_PHY->ulsch[i];
+      if((ulsch != NULL) && (ulsch->rnti == ctxt_prior.rnti)){
+        LOG_I(RRC, "clean_eNb_ulsch UE %x \n", ctxt_prior.rnti);
+        clean_eNb_ulsch(ulsch);
+        break;
+      }
+    }
+
+    for(int j = 0; j < 10; j++){
+      ul_req_tmp = &eNB_MAC->UL_req_tmp[CC_id][j].ul_config_request_body;
+      if(ul_req_tmp){
+        int pdu_number = ul_req_tmp->number_of_pdus;
+        for(int pdu_index = pdu_number-1; pdu_index >= 0; pdu_index--){
+          if(ul_req_tmp->ul_config_pdu_list[pdu_index].ulsch_pdu.ulsch_pdu_rel8.rnti == ctxt_prior.rnti){
+            LOG_I(RRC, "remove UE %x from ul_config_pdu_list %d/%d\n", ctxt_prior.rnti, pdu_index, pdu_number);
+            if(pdu_index < pdu_number -1){
+               memcpy(&ul_req_tmp->ul_config_pdu_list[pdu_index], &ul_req_tmp->ul_config_pdu_list[pdu_index+1], (pdu_number-1-pdu_index) * sizeof(nfapi_ul_config_request_pdu_t));
+            }
+            ul_req_tmp->number_of_pdus--;
+          }
+        }
+      }
+    }
+  }
   rrc_mac_remove_ue(ctxt_prior.module_id, ctxt_prior.rnti);
   rrc_rlc_remove_ue(&ctxt_prior);
   pdcp_remove_UE(&ctxt_prior);
@@ -1759,6 +1828,9 @@ rrc_eNB_generate_RRCConnectionReestablishmentReject(
 #ifdef RRC_MSG_PRINT
   int                                 cnt;
 #endif
+  int UE_id = find_UE_id(ctxt_pP->module_id, ctxt_pP->rnti);
+  RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1;
+  RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres = 20;
 
   T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_REJECT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
     T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
@@ -1812,9 +1884,16 @@ rrc_eNB_generate_RRCConnectionRelease(
 
   size = do_RRCConnectionRelease(ctxt_pP->module_id, buffer,rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id));
   // set release timer
-  ue_context_pP->ue_context.ue_release_timer=1;
+  //ue_context_pP->ue_context.ue_release_timer=1;
   // remove UE after 10 frames after RRCConnectionRelease is triggered
-  ue_context_pP->ue_context.ue_release_timer_thres=100;
+  //ue_context_pP->ue_context.ue_release_timer_thres=100;
+    // set release timer
+  ue_context_pP->ue_context.ue_release_timer_rrc = 1;
+  // remove UE after 10 frames after RRCConnectionRelease is triggered
+  ue_context_pP->ue_context.ue_release_timer_thres_rrc = 100;
+  ue_context_pP->ue_context.ue_reestablishment_timer = 0;
+  ue_context_pP->ue_context.ue_release_timer = 0;
+  ue_context_pP->ue_context.ue_release_timer_s1 = 0;
   LOG_I(RRC,
         PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate RRCConnectionRelease (bytes %d)\n",
         PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
@@ -4656,6 +4735,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
   uint8_t                            *kRRCenc = NULL;
   uint8_t                            *kRRCint = NULL;
   uint8_t                            *kUPenc = NULL;
+  ue_context_pP->ue_context.ue_reestablishment_timer = 0;
 
   DRB_ToAddModList_t*                 DRB_configList = ue_context_pP->ue_context.DRB_configList2[xid];
   SRB_ToAddModList_t*                 SRB_configList = ue_context_pP->ue_context.SRB_configList2[xid];
@@ -5052,9 +5132,13 @@ rrc_eNB_generate_RRCConnectionSetup(
         RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size);
 
   // activate release timer, if RRCSetupComplete not received after 10 frames, remove UE
-  ue_context_pP->ue_context.ue_release_timer=1;
+  //ue_context_pP->ue_context.ue_release_timer=1;
   // remove UE after 10 frames after RRCConnectionRelease is triggered
-  ue_context_pP->ue_context.ue_release_timer_thres=100;
+  //ue_context_pP->ue_context.ue_release_timer_thres=100;
+     // activate release timer, if RRCSetupComplete not received after 100 frames, remove UE
+   ue_context_pP->ue_context.ue_release_timer=1;
+   // remove UE after 10 frames after RRCConnectionRelease is triggered
+   ue_context_pP->ue_context.ue_release_timer_thres=1000;
 }
 
 
@@ -5398,11 +5482,27 @@ rrc_eNB_decode_ccch(
         rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id);
         break;
       }
-
+      if(ue_context_p->ue_context.ue_reestablishment_timer > 0){
+          LOG_I(RRC,
+                PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReestablishment(Previous) don't complete, let's reject the UE\n",
+                PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
+          rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id);
+          ue_context_p->ue_context.ue_reestablishment_timer_thres = 1000;
+          break;
+      }
       LOG_D(RRC,
             PROTOCOL_RRC_CTXT_UE_FMT" UE context: %p\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
             ue_context_p);
+      ue_context_p->ue_context.ul_failure_timer = 0;
+      ue_context_p->ue_context.ue_release_timer = 0;
+      ue_context_p->ue_context.ue_reestablishment_timer = 0;
+      ue_context_p->ue_context.ue_release_timer_s1 = 0;
+      ue_context_p->ue_context.ue_release_timer_rrc = 0;
+
+      /* reset timers */
+      ue_context_p->ue_context.ul_failure_timer = 0;
+      ue_context_p->ue_context.ue_release_timer = 0;
 
       // insert C-RNTI to map
       for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
@@ -5538,6 +5638,7 @@ rrc_eNB_decode_ccch(
             /* if there is already a registered UE (with another RNTI) with this random_value,
              * the current one must be removed from MAC/PHY (zombie UE)
              */
+#if 0
             if ((ue_context_p = rrc_eNB_ue_context_random_exist(ctxt_pP, random_value))) {
               LOG_W(RRC, "new UE rnti %x (coming with random value) is already there as UE %x, removing %x from MAC/PHY\n",
                     ctxt_pP->rnti, ue_context_p->ue_context.rnti, ctxt_pP->rnti);
@@ -5547,6 +5648,13 @@ rrc_eNB_decode_ccch(
             } else {
               ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, random_value);
             }
+#endif
+            if ((ue_context_p = rrc_eNB_ue_context_random_exist(ctxt_pP, random_value))) {
+              LOG_W(RRC, "new UE rnti %x (coming with random value) is already there as UE %x, removing %x from MAC/PHY\n",
+                    ctxt_pP->rnti, ue_context_p->ue_context.rnti, ue_context_p->ue_context.rnti);
+              ue_context_p->ue_context.ul_failure_timer = 20000;
+            }
+            ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, random_value);
           } else if (InitialUE_Identity_PR_s_TMSI == rrcConnectionRequest->ue_Identity.present) {
             /* Save s-TMSI */
             S_TMSI_t   s_TMSI = rrcConnectionRequest->ue_Identity.choice.s_TMSI;
@@ -5567,6 +5675,9 @@ rrc_eNB_decode_ccch(
               /* reset timers */
               ue_context_p->ue_context.ul_failure_timer = 0;
               ue_context_p->ue_context.ue_release_timer = 0;
+              ue_context_p->ue_context.ue_reestablishment_timer = 0;
+              ue_context_p->ue_context.ue_release_timer_s1 = 0;
+              ue_context_p->ue_context.ue_release_timer_rrc = 0;
             } else {
 	      LOG_I(RRC," S-TMSI doesn't exist, setting Initialue_identity_s_TMSI.m_tmsi to %p => %x\n",ue_context_p,m_tmsi);
 //              ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, NOT_A_RANDOM_UE_IDENTITY);
@@ -5961,6 +6072,13 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
 						       ue_context_p);
           } else {
             ue_context_p->ue_context.reestablishment_cause = ReestablishmentCause_spare1;
+            for (uint8_t e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
+              if (ue_context_p->ue_context.e_rab[e_rab].status == E_RAB_STATUS_DONE) {
+                ue_context_p->ue_context.e_rab[e_rab].status = E_RAB_STATUS_ESTABLISHED;
+              } else {
+                ue_context_p->ue_context.e_rab[e_rab].status = E_RAB_STATUS_FAILED;
+              }
+            }
           }
 	}
       }    
@@ -6044,7 +6162,8 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
           }
 #endif
         }
-        ue_context_p->ue_context.ue_release_timer = 0;
+        //ue_context_p->ue_context.ue_release_timer = 0;
+		ue_context_p->ue_context.ue_reestablishment_timer = 1;
       }
       break;
 
@@ -6526,6 +6645,10 @@ rrc_enb_task(
       /* Nothing to do. Apparently everything is done in S1AP processing */
       //LOG_I(RRC, "[eNB %d] Received message %s, not processed because procedure not synched\n",
       //instance, msg_name_p);
+    	if (rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)) {
+    	  rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc =
+    	  rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_thres_rrc;
+    	}
       break;
 
 #   endif
diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.c b/openair2/RRC/LITE/rrc_eNB_S1AP.c
index ae8fa0a450..d2c0d0acbe 100644
--- a/openair2/RRC/LITE/rrc_eNB_S1AP.c
+++ b/openair2/RRC/LITE/rrc_eNB_S1AP.c
@@ -1197,6 +1197,7 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const ch
     }
     return (-1);
   } else {
+    ue_context_p->ue_context.ue_release_timer_s1 = 0;
     PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
     rrc_eNB_generate_RRCConnectionRelease(&ctxt, ue_context_p);
     /*
diff --git a/openair2/RRC/LITE/rrc_eNB_UE_context.c b/openair2/RRC/LITE/rrc_eNB_UE_context.c
index 28eace8f5a..0ae3d7ca15 100644
--- a/openair2/RRC/LITE/rrc_eNB_UE_context.c
+++ b/openair2/RRC/LITE/rrc_eNB_UE_context.c
@@ -155,7 +155,21 @@ rrc_eNB_get_ue_context(
   memset(&temp, 0, sizeof(struct rrc_eNB_ue_context_s));
   /* eNB ue rrc id = 24 bits wide */
   temp.ue_id_rnti = rntiP;
+#if 0
   return RB_FIND(rrc_ue_tree_s, &rrc_instance_pP->rrc_ue_head, &temp);
+#endif
+  struct rrc_eNB_ue_context_s   *ue_context_p = NULL;
+  ue_context_p = RB_FIND(rrc_ue_tree_s, &rrc_instance_pP->rrc_ue_head, &temp);
+  if ( ue_context_p != NULL) {
+    return ue_context_p;
+  } else {
+    RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(rrc_instance_pP->rrc_ue_head)) {
+      if (ue_context_p->ue_context.rnti == rntiP) {
+        return ue_context_p;
+      }
+    }
+    return NULL;
+  }
 }
 
 
diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c
index d152840dd4..7c87cbc073 100644
--- a/openair3/GTPV1-U/gtpv1u_eNB.c
+++ b/openair3/GTPV1-U/gtpv1u_eNB.c
@@ -814,40 +814,81 @@ int gtpv1u_update_s1u_tunnel(
     const rnti_t                                  prior_rnti
     )
 {
+
   /* Local tunnel end-point identifier */
   teid_t                   s1u_teid             = 0;
   gtpv1u_teid_data_t      *gtpv1u_teid_data_p   = NULL;
   gtpv1u_ue_data_t        *gtpv1u_ue_data_p     = NULL;
+  gtpv1u_ue_data_t        *gtpv1u_ue_data_new_p     = NULL;
   //MessageDef              *message_p            = NULL;
   hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
-  int                      i;
-  ebi_t                    eps_bearer_id        = 0;
+  int                      i,j;
+  uint8_t                  bearers_num = 0,bearers_total = 0;
 
   //-----------------------
   // PDCP->GTPV1U mapping
   //-----------------------
   hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, prior_rnti, (void **)&gtpv1u_ue_data_p);
-  AssertFatal(hash_rc == HASH_TABLE_OK, "Error get ue_mapping(rnti=%x) from GTPV1U hashtable error\n", prior_rnti);
+  if(hash_rc != HASH_TABLE_OK){
+    LOG_E(GTPU,"Error get ue_mapping(rnti=%x) from GTPV1U hashtable error\n", prior_rnti);
+    return -1;
+  }
 
-  gtpv1u_ue_data_p->ue_id       = create_tunnel_req_pP->rnti;
-  hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_p);
+  gtpv1u_ue_data_new_p = calloc (1, sizeof(gtpv1u_ue_data_t));
+  memcpy(gtpv1u_ue_data_new_p,gtpv1u_ue_data_p,sizeof(gtpv1u_ue_data_t));
+  gtpv1u_ue_data_new_p->ue_id       = create_tunnel_req_pP->rnti;
+
+  hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_new_p);
   AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
   LOG_I(GTPU, "inserting ue_mapping(rnti=%x) in GTPV1U hashtable\n",
       create_tunnel_req_pP->rnti);
 
+  hash_rc = hashtable_remove(RC.gtpv1u_data_g->ue_mapping, prior_rnti);
+  LOG_I(GTPU, "hashtable_remove ue_mapping(rnti=%x) in GTPV1U hashtable\n",
+		  prior_rnti);
   //-----------------------
   // GTPV1U->PDCP mapping
   //-----------------------
-  for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
-    eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i];
-    s1u_teid = gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_eNB;
-    hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, s1u_teid, (void**)&gtpv1u_teid_data_p);
-    AssertFatal(hash_rc == HASH_TABLE_OK, "Error get teid mapping(s1u_teid=%u) from GTPV1U hashtable", s1u_teid);
+  bearers_total =gtpv1u_ue_data_new_p->num_bearers;
+  for(j = 0;j<GTPV1U_MAX_BEARERS_ID;j++){
 
-    gtpv1u_teid_data_p->ue_id         = create_tunnel_req_pP->rnti;
-    gtpv1u_teid_data_p->eps_bearer_id = eps_bearer_id;
+    if(gtpv1u_ue_data_new_p->bearers[j].state != BEARER_IN_CONFIG)
+      continue;
+
+    bearers_num++;
+    for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
+      if(j == (create_tunnel_req_pP->eps_bearer_id[i]-GTPV1U_BEARER_OFFSET))
+        break;
+    }
+    if(i < create_tunnel_req_pP->num_tunnels){
+      s1u_teid = gtpv1u_ue_data_new_p->bearers[j].teid_eNB;
+      hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, s1u_teid, (void**)&gtpv1u_teid_data_p);
+      if (hash_rc == HASH_TABLE_OK) {
+        gtpv1u_teid_data_p->ue_id         = create_tunnel_req_pP->rnti;
+        gtpv1u_teid_data_p->eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i];
+
+        LOG_I(GTPU, "updata teid_mapping te_id %u (prior_rnti %x rnti %x) in GTPV1U hashtable\n",
+              s1u_teid,prior_rnti,create_tunnel_req_pP->rnti);
+      }else{
+        LOG_W(GTPU, "Error get teid mapping(s1u_teid=%u) from GTPV1U hashtable", s1u_teid);
+      }
+    }else{
+      s1u_teid = gtpv1u_ue_data_new_p->bearers[j].teid_eNB;
+      hash_rc = hashtable_remove(RC.gtpv1u_data_g->teid_mapping, s1u_teid);
+
+      if (hash_rc != HASH_TABLE_OK) {
+        LOG_D(GTPU, "Removed user rnti %x , enb S1U teid %u not found\n", prior_rnti, s1u_teid);
+      }
+      gtpv1u_ue_data_new_p->bearers[j].state = BEARER_DOWN;
+      gtpv1u_ue_data_new_p->num_bearers--;
+      LOG_I(GTPU, "delete teid_mapping te_id %u (rnti%x) bearer_id %d in GTPV1U hashtable\n",
+            s1u_teid,prior_rnti,j+GTPV1U_BEARER_OFFSET);;
+    }
+    if(bearers_num > bearers_total)
+      break;
   }
   return 0;
+
 }
 
 //-----------------------------------------------------------------------------
-- 
GitLab