From b7e2a90ef44961570e8e116639c99b5f4e640db7 Mon Sep 17 00:00:00 2001
From: Xu Bo <xubo1@cn.fujitsu.com>
Date: Sat, 27 Jan 2018 02:06:08 +0000
Subject: [PATCH] fix release timer by starting timer after SCD
 DCCH(RRCConnectionRelease)

---
 openair2/COMMON/mac_rlc_primitives.h      |  1 +
 openair2/LAYER2/MAC/defs.h                | 11 +++-
 openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 24 +++++++-
 openair2/LAYER2/MAC/pre_processor.c       | 15 +++--
 openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c    |  2 +-
 openair2/LAYER2/RLC/rlc.h                 |  1 +
 openair2/LAYER2/RLC/rlc_mac.c             |  1 +
 openair2/RRC/LITE/proto.h                 |  3 +-
 openair2/RRC/LITE/rrc_common.c            | 71 ++++++++++++++++++++++-
 openair2/RRC/LITE/rrc_eNB.c               | 23 ++++++--
 openair2/RRC/LITE/rrc_eNB_S1AP.c          |  3 +-
 11 files changed, 139 insertions(+), 16 deletions(-)

diff --git a/openair2/COMMON/mac_rlc_primitives.h b/openair2/COMMON/mac_rlc_primitives.h
index 4e3e22781c..b96a7b7b82 100644
--- a/openair2/COMMON/mac_rlc_primitives.h
+++ b/openair2/COMMON/mac_rlc_primitives.h
@@ -191,6 +191,7 @@ struct mac_status_resp {
   uint32_t             head_sdu_remaining_size_to_send;
   unsigned char     head_sdu_is_segmented;
   struct rlc_entity_info rlc_info;             /*!< xxx*/
+  mui_t              rrc_mui;
 };
 
 struct mac_tb_ind {
diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h
index 0282baa3cb..ab2f4ce06e 100644
--- a/openair2/LAYER2/MAC/defs.h
+++ b/openair2/LAYER2/MAC/defs.h
@@ -1362,7 +1362,16 @@ typedef struct {
     uint16_t cell_ids[6];
     uint8_t n_adj_cells;
 } neigh_cell_id_t;
-
+typedef struct {
+  volatile uint8_t flag;
+  rnti_t rnti;
+  mui_t  rrc_eNB_mui;
+}RRC_release_ctrl;
+ 
+typedef struct {
+    uint16_t num_UEs;
+    RRC_release_ctrl RRC_release_ctrl[NUMBER_OF_UE_MAX];
+} RRC_release_list_t;
 #include "proto.h"
 /*@}*/
 #endif /*__LAYER2_MAC_DEFS_H__ */
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
index 85f5e300e8..c6313b3dd9 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
@@ -919,7 +919,29 @@ schedule_ue_spec(module_id_t module_idP,
 							  (char *)
 							  &dlsch_buffer
 							  [0]);
-
+            pthread_mutex_lock(&rrc_release_freelist);
+            if(rrc_release_info.num_UEs > 0){
+              uint16_t release_total = 0;
+              for(uint16_t release_num = 0;release_num < NUMBER_OF_UE_MAX;release_num++){
+                if(rrc_release_info.RRC_release_ctrl[release_num].flag == 1){
+                 release_total++;
+                  if( (rrc_release_info.RRC_release_ctrl[release_num].rnti == rnti) &&
+                      (rrc_release_info.RRC_release_ctrl[release_num].rrc_eNB_mui == rlc_status.rrc_mui)){
+                      rrc_release_info.RRC_release_ctrl[release_num].flag = 3;
+                  }
+                }
+                if(rrc_release_info.RRC_release_ctrl[release_num].flag == 2){
+                    release_total++;
+                    if( (rrc_release_info.RRC_release_ctrl[release_num].rnti == rnti) &&
+                        (rrc_release_info.RRC_release_ctrl[release_num].rrc_eNB_mui == rlc_status.rrc_mui)){
+                        rrc_release_info.RRC_release_ctrl[release_num].flag = 4;
+                    }
+                }
+                if(release_total >= rrc_release_info.num_UEs)
+                  break;
+              }
+            }
+            pthread_mutex_unlock(&rrc_release_freelist);
 			T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP),
 			  T_INT(CC_id), T_INT(rnti), T_INT(frameP),
 			  T_INT(subframeP), T_INT(harq_pid), T_INT(DCCH),
diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c
index 23d3f3bd60..666cdb474c 100644
--- a/openair2/LAYER2/MAC/pre_processor.c
+++ b/openair2/LAYER2/MAC/pre_processor.c
@@ -459,9 +459,10 @@ void sort_UEs(module_id_t Mod_idP, int frameP, sub_frame_t subframeP)
 	    continue;
 	if ((rnti = UE_RNTI(Mod_idP, i)) == NOT_A_RNTI)
 	    continue;
+#if 0
 	if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
 	    continue;
-
+#endif
 	list[list_size] = i;
 	list_size++;
     }
@@ -650,8 +651,10 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
 
 	if (rnti == NOT_A_RNTI)
 	    continue;
+#if 0
 	if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
 	    continue;
+#endif
 	UE_id = i;
 
 	for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) {
@@ -707,9 +710,10 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
 
 	if (rnti == NOT_A_RNTI)
 	    continue;
+#if 0
 	if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
 	    continue;
-
+#endif
 	for (ii = 0; ii < UE_num_active_CC(UE_list, i); ii++) {
 	    CC_id = UE_list->ordered_CCids[ii][i];
 	    ue_sched_ctl = &UE_list->UE_sched_ctrl[i];
@@ -779,9 +783,10 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
 		    // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti );
 		    if (rnti == NOT_A_RNTI)
 			continue;
+#if 0
 		    if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
 			continue;
-
+#endif
 		    transmission_mode = get_tmode(Mod_id, CC_id, UE_id);
 		    //          mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0);
 		    //rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti);
@@ -837,11 +842,11 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
 				    round2 = ue_sched_ctl2->round[CC_id];
 				    if (rnti2 == NOT_A_RNTI)
 					continue;
-				    if (UE_list->
+#if 0				    if (UE_list->
 					UE_sched_ctrl
 					[UE_id2].ul_out_of_sync == 1)
 					continue;
-
+#endif
 				    eNB_UE_stats2 =
 					UE_list->
 					eNB_UE_stats[CC_id][UE_id2];
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
index 0e21d5cfac..881c7b14cc 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
@@ -585,7 +585,7 @@ rlc_am_mac_status_indication (
 
     sdu_size            = ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_size;
     sdu_remaining_size  = ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_remaining_size;
-
+    status_resp.rrc_mui = rlc->input_sdus[rlc->current_sdu_index].mui;
     status_resp.head_sdu_remaining_size_to_send = sdu_remaining_size;
 
     if (sdu_size == sdu_remaining_size)  {
diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h
index fca786b4d3..7c1ebab2be 100644
--- a/openair2/LAYER2/RLC/rlc.h
+++ b/openair2/LAYER2/RLC/rlc.h
@@ -151,6 +151,7 @@ typedef  struct {
   frame_t                      head_sdu_creation_time;           /*!< \brief Head SDU creation time. */
   sdu_size_t                   head_sdu_remaining_size_to_send;  /*!< \brief remaining size of sdu: could be the total size or the remaining size of already segmented sdu */
   boolean_t                    head_sdu_is_segmented;     /*!< \brief 0 if head SDU has not been segmented, 1 if already segmented */
+  mui_t                        rrc_mui;
 } mac_rlc_status_resp_t;
 
 
diff --git a/openair2/LAYER2/RLC/rlc_mac.c b/openair2/LAYER2/RLC/rlc_mac.c
index 6793e71c54..b309dab0bc 100644
--- a/openair2/LAYER2/RLC/rlc_mac.c
+++ b/openair2/LAYER2/RLC/rlc_mac.c
@@ -406,6 +406,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
     mac_rlc_status_resp.head_sdu_creation_time          = status_resp.head_sdu_creation_time;
     mac_rlc_status_resp.head_sdu_remaining_size_to_send = status_resp.head_sdu_remaining_size_to_send;
     mac_rlc_status_resp.head_sdu_is_segmented           = status_resp.head_sdu_is_segmented;
+    mac_rlc_status_resp.rrc_mui                         = status_resp.rrc_mui;
     //return mac_rlc_status_resp;
     break;
 
diff --git a/openair2/RRC/LITE/proto.h b/openair2/RRC/LITE/proto.h
index d14ec46d78..063ab67e11 100644
--- a/openair2/RRC/LITE/proto.h
+++ b/openair2/RRC/LITE/proto.h
@@ -489,7 +489,8 @@ void openair_rrc_top_init_ue(
                         uint8_t cba_group_active,
                         uint8_t HO_active
 );
-
+pthread_mutex_t      rrc_release_freelist;
+RRC_release_list_t rrc_release_info;
 pthread_mutex_t      lock_ue_freelist;
 void remove_UE_from_freelist(module_id_t mod_id, rnti_t rnti);
 void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, boolean_t removeFlag);
diff --git a/openair2/RRC/LITE/rrc_common.c b/openair2/RRC/LITE/rrc_common.c
index 105e28f9a9..0c8ef99460 100644
--- a/openair2/RRC/LITE/rrc_common.c
+++ b/openair2/RRC/LITE/rrc_common.c
@@ -359,10 +359,11 @@ rrc_rx_tx(
             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_context_p->ue_context.ue_release_timer_s1 = 0;
+//          ue_context_p->ue_context.ue_release_timer_s1 = 0;
 #if defined(ENABLE_USE_MME)
 #if defined(ENABLE_ITTI)
           rrc_eNB_generate_RRCConnectionRelease(ctxt_pP, ue_context_p);
+#if 0
           {
             int      e_rab;
             MessageDef *msg_delete_tunnels_p = NULL;
@@ -400,9 +401,11 @@ rrc_rx_tx(
             }
           }
 #endif
+#endif
 #else
           ue_to_be_removed = ue_context_p;
 #endif
+          ue_context_p->ue_context.ue_release_timer_s1 = 0;
           break;
         }
       }
@@ -412,10 +415,74 @@ rrc_rx_tx(
         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_context_p->ue_context.ue_release_timer_rrc = 0;
           ue_to_be_removed = ue_context_p;
           break;
         }
-      }
+       }
+       pthread_mutex_lock(&rrc_release_freelist);
+      if(rrc_release_info.num_UEs > 0){
+        uint16_t release_total = 0;
+        for(uint16_t release_num = 0;release_num < NUMBER_OF_UE_MAX;release_num++){
+          if(rrc_release_info.RRC_release_ctrl[release_num].flag > 0){
+            release_total++;
+          }
+          if( (rrc_release_info.RRC_release_ctrl[release_num].flag > 2) &&
+            (rrc_release_info.RRC_release_ctrl[release_num].rnti == ue_context_p->ue_context.rnti)){
+           ue_context_p->ue_context.ue_release_timer_rrc = 1;
+           ue_context_p->ue_context.ue_release_timer_thres_rrc = 100;
+#if defined(ENABLE_USE_MME)
+#if defined(ENABLE_ITTI)
+           int      e_rab;
+           MessageDef *msg_complete_p = NULL;
+           MessageDef *msg_delete_tunnels_p = NULL;
+           uint32_t eNB_ue_s1ap_id = ue_context_p->ue_context.eNB_ue_s1ap_id;
+           if(rrc_release_info.RRC_release_ctrl[release_num].flag == 4){
+             MSC_LOG_TX_MESSAGE(
+                    MSC_RRC_ENB,
+                    MSC_S1AP_ENB,
+                     NULL,0,
+                    "0 S1AP_UE_CONTEXT_RELEASE_COMPLETE eNB_ue_s1ap_id 0x%06"PRIX32" ",
+                     eNB_ue_s1ap_id);
+             msg_complete_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_COMPLETE);
+             S1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_complete_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
+             itti_send_msg_to_task(TASK_S1AP, ctxt_pP->module_id, msg_complete_p);
+           }
+           MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_GTPU_ENB, NULL,0, "0 GTPV1U_ENB_DELETE_TUNNEL_REQ rnti %x ", eNB_ue_s1ap_id);
+           msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
+           memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
+           // do not wait response
+           GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
+           for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
+             GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
+               ue_context_p->ue_context.enb_gtp_ebi[e_rab];
+             // erase data
+             ue_context_p->ue_context.enb_gtp_teid[e_rab] = 0;
+             memset(&ue_context_p->ue_context.enb_gtp_addrs[e_rab], 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[e_rab]));
+             ue_context_p->ue_context.enb_gtp_ebi[e_rab]  = 0;
+           }
+           itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->module_id, msg_delete_tunnels_p);
+           struct rrc_ue_s1ap_ids_s    *rrc_ue_s1ap_ids = NULL;
+           rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(
+                  RC.rrc[ctxt_pP->module_id],
+                  0,
+                  eNB_ue_s1ap_id);
+           if (NULL != rrc_ue_s1ap_ids) {
+             rrc_eNB_S1AP_remove_ue_ids(
+                        RC.rrc[ctxt_pP->module_id],
+                        rrc_ue_s1ap_ids);
+           }
+#endif
+#endif
+           rrc_release_info.RRC_release_ctrl[release_num].flag = 0;
+           rrc_release_info.num_UEs--;
+           break;
+         }
+         if(release_total >= rrc_release_info.num_UEs)
+           break;
+         }
+       }
+       pthread_mutex_unlock(&rrc_release_freelist);
 
       if (ue_context_p->ue_context.ue_reestablishment_timer>0) {
         ue_context_p->ue_context.ue_reestablishment_timer++;
diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c
index 7afd9d2a0f..60b0030446 100644
--- a/openair2/RRC/LITE/rrc_eNB.c
+++ b/openair2/RRC/LITE/rrc_eNB.c
@@ -2005,9 +2005,9 @@ rrc_eNB_generate_RRCConnectionRelease(
   // remove UE after 10 frames after RRCConnectionRelease is triggered
   //ue_context_pP->ue_context.ue_release_timer_thres=100;
     // set release timer
-  ue_context_pP->ue_context.ue_release_timer_rrc = 1;
+//  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_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;
@@ -2033,7 +2033,21 @@ rrc_eNB_generate_RRCConnectionRelease(
     ue_context_pP->ue_context.rnti,
     rrc_eNB_mui,
     size);
-
+  pthread_mutex_lock(&rrc_release_freelist);
+  for(uint16_t release_num = 0;release_num < NUMBER_OF_UE_MAX;release_num++){
+    if(rrc_release_info.RRC_release_ctrl[release_num].flag == 0){
+      if(ue_context_pP->ue_context.ue_release_timer_s1 > 0){
+        rrc_release_info.RRC_release_ctrl[release_num].flag = 1;
+      }else{
+        rrc_release_info.RRC_release_ctrl[release_num].flag = 2;
+      }
+      rrc_release_info.RRC_release_ctrl[release_num].rnti = ctxt_pP->rnti;
+      rrc_release_info.RRC_release_ctrl[release_num].rrc_eNB_mui = rrc_eNB_mui;
+      rrc_release_info.num_UEs++;
+      break;
+    }
+  }
+  pthread_mutex_unlock(&rrc_release_freelist);
   rrc_data_req(
 	       ctxt_pP,
 	       DCCH,
@@ -6695,7 +6709,8 @@ rrc_enb_task(
   protocol_ctxt_t                     ctxt;
 
   pthread_mutex_init(&lock_ue_freelist, NULL);
-
+  pthread_mutex_init(&rrc_release_freelist, NULL);
+  memset(&rrc_release_info,0,sizeof(RRC_release_list_t));
   itti_mark_task_ready(TASK_RRC_ENB);
   LOG_I(RRC,"Entering main loop of RRC message task\n");
   while (1) {
diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.c b/openair2/RRC/LITE/rrc_eNB_S1AP.c
index d2c0d0acbe..0ecf8f569a 100644
--- a/openair2/RRC/LITE/rrc_eNB_S1AP.c
+++ b/openair2/RRC/LITE/rrc_eNB_S1AP.c
@@ -1206,6 +1206,7 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const ch
                   instance,
                   eNB_ue_s1ap_id);
     */
+#if 0
     {
       int      e_rab;
       //int      mod_id = 0;
@@ -1261,7 +1262,7 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const ch
       		  rrc_ue_s1ap_ids);
       }
     }
-
+#endif
     return (0);
   }
 }
-- 
2.26.2