From 673ef5fa7a8748bc2553834f2b1ed3c1bc41c3b2 Mon Sep 17 00:00:00 2001
From: Xenofon Foukas <x.foukas@sms.ed.ac.uk>
Date: Thu, 14 Apr 2016 15:13:15 +0100
Subject: [PATCH] Modified active harq reporting mechanism to support long
 schedule ahead of time values

---
 openair1/SCHED/defs.h                     |   5 +
 openair1/SCHED/phy_procedures_lte_eNb.c   | 107 +++++++++++++++-------
 openair2/ENB_APP/enb_agent_common.c       |   3 +-
 openair2/LAYER2/MAC/eNB_scheduler_RA.c    |   2 +-
 openair2/LAYER2/MAC/eNB_scheduler_ulsch.c |   2 +-
 openair2/LAYER2/MAC/pre_processor.c       |   4 +-
 6 files changed, 83 insertions(+), 40 deletions(-)

diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h
index 8692a31f12..72830f35cb 100644
--- a/openair1/SCHED/defs.h
+++ b/openair1/SCHED/defs.h
@@ -81,6 +81,11 @@ enum openair_SYNCH_STATUS {
   openair_SCHED_EXIT
 };
 
+enum openair_HARQ_TYPE {
+  openair_harq_DL = 0,
+  openair_harq_UL,
+  openair_harq_RA
+};
 
 #define DAQ_AGC_ON 1
 #define DAQ_AGC_OFF 0
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 15cd98881d..ba180e781f 100755
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -29,11 +29,11 @@
 
 /*! \file phy_procedures_lte_eNB.c
  * \brief Implementation of eNB procedures from 36.213 LTE specifications
- * \author R. Knopp, F. Kaltenberger, N. Nikaein
+ * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas
  * \date 2011
  * \version 0.1
  * \company Eurecom
- * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr
+ * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk
  * \note
  * \warning
  */
@@ -141,26 +141,23 @@ uint8_t is_SR_subframe(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id,uint8_t sched_su
 
 void put_harq_pid_in_freelist(LTE_eNB_DLSCH_t *DLSCH_ptr, int harq_pid)
 {
-  DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->tail_freelist] = harq_pid;
-  DLSCH_ptr->tail_freelist = (DLSCH_ptr->tail_freelist + 1) % 10;
+  if (harq_pid >=0 && harq_pid < 8) {
+    DLSCH_ptr->harq_pid_freelist[harq_pid] = 1;
+  } else {
+    LOG_E(PHY, "%s:%d: critical error, get in touch with the authors\n", __FILE__, __LINE__);
+    abort();
+  }
 }
 
 void remove_harq_pid_from_freelist(LTE_eNB_DLSCH_t *DLSCH_ptr, int harq_pid)
 {
-  if (DLSCH_ptr->head_freelist == DLSCH_ptr->tail_freelist) {
-    LOG_E(PHY, "%s:%d: you cannot read this!\n", __FILE__, __LINE__);
-    abort();
-  }
-  /* basic check, in case several threads deal with the free list at the same time
-   * in normal situations it should not happen, that's also why we don't use any
-   * locking mechanism to protect the free list
-   * to be refined in case things don't work properly
-   */
-  if (harq_pid != DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]) {
+
+  if (harq_pid >=0 && harq_pid < 8) {
+    DLSCH_ptr->harq_pid_freelist[harq_pid] = 0;
+  } else {
     LOG_E(PHY, "%s:%d: critical error, get in touch with the authors\n", __FILE__, __LINE__);
     abort();
   }
-  DLSCH_ptr->head_freelist = (DLSCH_ptr->head_freelist + 1) % 10;
 }
 
 int32_t add_ue(int16_t rnti, PHY_VARS_eNB *phy_vars_eNB)
@@ -257,12 +254,17 @@ int8_t find_next_ue_index(PHY_VARS_eNB *phy_vars_eNB)
   return(-1);
 }
 
-int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t ul_flag)
+int prev_frame = -1;
+int prev_subframe = -1;
+int prev_harq_pid = 0;
+int prev_harq_round = 0;
+
+int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t harq_flag)
 {
   LTE_eNB_DLSCH_t *DLSCH_ptr;
   LTE_eNB_ULSCH_t *ULSCH_ptr;
   uint8_t ulsch_subframe,ulsch_frame;
-  uint8_t i;
+  uint8_t i, j;
   int8_t UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][CC_id]);
   int sf1=(10*frame)+subframe,sf2,sfdiff,sfdiff_max=7;
 
@@ -272,39 +274,74 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16
     return(-1);
   }
 
-  if (ul_flag == 0)  {// this is a DL request
+  if ((harq_flag == openair_harq_DL) || (harq_flag == openair_harq_RA))  {// this is a DL request
+
     DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch_eNB[(uint32_t)UE_id][0];
 
+    if (harq_flag == openair_harq_RA) {
+      if (DLSCH_ptr->harq_processes[0] != NULL) {
+	*harq_pid = 0;
+	*round = DLSCH_ptr->harq_processes[0]->round;
+	return 0;
+      } else {
+	return -1;
+      }
+    }
+
+    if (prev_frame == frame && prev_subframe == subframe) {
+      *harq_pid = prev_harq_pid;
+      *round = prev_harq_round;
+      return (0);
+    }
+
     // set to no available process first
     *harq_pid = -1;
 
-    for (i=0; i<DLSCH_ptr->Mdlharq; i++) {
-      if (DLSCH_ptr->harq_processes[i]!=NULL) {
-	if (DLSCH_ptr->harq_processes[i]->status == ACTIVE) {
-	  sf2 = (DLSCH_ptr->harq_processes[i]->frame*10) + DLSCH_ptr->harq_processes[i]->subframe;
-	  if (sf2<=sf1)
+    j = prev_harq_pid;
+
+    for (i = 0; i < 8; i++) {
+      j = (j + 1) % 8;
+      if (DLSCH_ptr->harq_processes[j] != NULL) {
+	if (DLSCH_ptr->harq_processes[j]->status == ACTIVE) {
+	  sf2 = (DLSCH_ptr->harq_processes[j]->frame*10) + DLSCH_ptr->harq_processes[j]->subframe;
+	  if (sf2<=sf1) {
 	    sfdiff = sf1-sf2;
-	  else // this happens when wrapping around 1024 frame barrier
+	  } else { // this happens when wrapping around 1024 frame barrier
 	    sfdiff = 10240 + sf1-sf2;
-	  LOG_D(PHY,"process %d is active, round %d (waiting %d)\n",i,DLSCH_ptr->harq_processes[i]->round,sfdiff);
-
-	  if (sfdiff>sfdiff_max) { // this is an active process that is waiting longer than the others (and longer than 7 ms)
-	    sfdiff_max = sfdiff; 
-	    *harq_pid = i;
-	    *round = DLSCH_ptr->harq_processes[i]->round;
+	  }
+	  LOG_D(PHY,"process %d is active, round %d (waiting %d)\n",i,DLSCH_ptr->harq_processes[j]->round,sfdiff);
+	  if (sfdiff > sfdiff_max) {
+	    prev_harq_pid = j;
+	    prev_harq_round = DLSCH_ptr->harq_processes[j]->round;
+	    prev_frame = frame;
+	    prev_subframe = subframe;
+	    *harq_pid = j;
+	    *round = DLSCH_ptr->harq_processes[j]->round;
+	    LOG_D(PHY,"process %d, %d is the allocated process\n", *harq_pid, *round);
+	    return 0;
+	  }
+	} else { // Send from the freelist
+	  if (DLSCH_ptr->harq_pid_freelist[j] == 1) {
+	    *harq_pid = j;
+	    *round = 0;
+	    prev_harq_pid = *harq_pid;
+	    prev_harq_round = *round;
+	    prev_frame = frame;
+	    prev_subframe = subframe;
+	    LOG_D(PHY,"process %d is first free process\n", *harq_pid);
+	    return 0;
 	  }
 	}
-      } else { // a process is not defined
+      } else {
 	LOG_E(PHY,"[eNB %d] DLSCH process %d for rnti %x (UE_id %d) not allocated\n",Mod_id,i,rnti,UE_id);
 	return(-1);
       }
     }
 
-    /* if no active harq pid, get the oldest in the freelist, if any */
-    if (*harq_pid == 255 && DLSCH_ptr->head_freelist != DLSCH_ptr->tail_freelist) {
-      *harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist];
+    if (*harq_pid == 255) {
       *round = 0;
-      LOG_D(PHY,"process %d is first free process\n", *harq_pid);
+      LOG_I(PHY, "TEST, no process found\n");
+      return -1;
     }
 
     LOG_D(PHY,"get_ue_active_harq_pid DL => Frame %d, Subframe %d : harq_pid %d\n",
diff --git a/openair2/ENB_APP/enb_agent_common.c b/openair2/ENB_APP/enb_agent_common.c
index e21c180cec..e3c2bcfcb5 100644
--- a/openair2/ENB_APP/enb_agent_common.c
+++ b/openair2/ENB_APP/enb_agent_common.c
@@ -43,6 +43,7 @@
 #include "PHY/extern.h"
 #include "log.h"
 
+#include "SCHED/defs.h"
 #include "RRC/LITE/extern.h"
 #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
 #include "rrc_eNB_UE_context.h"
@@ -671,7 +672,7 @@ int get_harq(const mid_t mod_id, const uint8_t CC_id, const mid_t ue_id, const i
 
   uint16_t rnti = get_ue_crnti(mod_id,ue_id);
 
-  mac_xface->get_ue_active_harq_pid(mod_id,CC_id,rnti,frame,subframe,&harq_pid,&round,0);
+  mac_xface->get_ue_active_harq_pid(mod_id,CC_id,rnti,frame,subframe,&harq_pid,&round,openair_harq_DL);
 
   *id = harq_pid;
   if (round > 0) {
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
index 8cb6b91301..a4b7339677 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
@@ -661,7 +661,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un
 	LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \n",
 	      module_idP,CC_id,frameP,subframeP);
 	// Get candidate harq_pid from PHY
-	mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,0);
+	mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,openair_harq_RA);
 	
 	if (round>0) {
 	  //RA_template->wait_ack_Msg4++;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
index e6033d5057..17a8cec5db 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
@@ -753,7 +753,7 @@ void schedule_ulsch_rnti(module_id_t   module_idP,
         DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu;
         UE_template = &UE_list->UE_template[CC_id][UE_id];
 
-        if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,1) == -1 ) {
+        if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL) == -1 ) {
           LOG_W(MAC,"[eNB %d] Scheduler Frame %d, subframeP %d: candidate harq_pid from PHY for UE %d CC %d RNTI %x\n",
                 module_idP,frameP,subframeP, UE_id, CC_id, rnti);
           //  NN --> RK: Don't schedule UE if we cannot get harq pid
diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c
index c744d1d90a..64ae2d9453 100644
--- a/openair2/LAYER2/MAC/pre_processor.c
+++ b/openair2/LAYER2/MAC/pre_processor.c
@@ -760,7 +760,7 @@ void dlsch_scheduler_pre_processor_reset (int module_idP,
 				    frameP,subframeP,
 				    &ue_sched_ctl->harq_pid[CC_id],
 				    &ue_sched_ctl->round[CC_id],
-				    0);
+				    openair_harq_DL);
   if (ue_sched_ctl->ta_timer == 0) {
 
     // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...
@@ -1020,7 +1020,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP,
       // This is the actual CC_id in the list
       CC_id = UE_list->ordered_ULCCids[n][UE_id];
 
-      mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,1);
+      mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL);
 
       if(round>0) {
         nb_allocated_rbs[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid];
-- 
2.26.2