From 76b91cfefb3d755ab6d294f4ecb58d6bae0dda09 Mon Sep 17 00:00:00 2001
From: Navid Nikaein <navid.nikaein@eurecom.fr>
Date: Thu, 18 Jul 2013 11:53:58 +0000
Subject: [PATCH]   * add additional RLC buffer information for fine grain DL
 scheduling   * protect ENABLE_DB flag with explicit user-defined flag

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4036 818b1a75-f10b-46b9-bf7c-635c3b92a50f
---
 openair2/COMMON/mac_rlc_primitives.h   |  3 ++
 openair2/LAYER2/MAC/defs.h             | 14 ++++++++
 openair2/LAYER2/MAC/pre_processor.c    | 38 ++++++++++++++++++---
 openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c | 36 ++++++++++++++++++--
 openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c | 46 ++++++++++++++++++++------
 openair2/LAYER2/RLC/mac_primitives.h   |  2 +-
 openair2/LAYER2/RLC/rlc.h              |  3 ++
 openair2/LAYER2/RLC/rlc_mac.c          |  9 +++--
 targets/SIMU/USER/Makefile             |  2 ++
 9 files changed, 133 insertions(+), 20 deletions(-)

diff --git a/openair2/COMMON/mac_rlc_primitives.h b/openair2/COMMON/mac_rlc_primitives.h
index cf375d4ea20..8c48af0d75e 100644
--- a/openair2/COMMON/mac_rlc_primitives.h
+++ b/openair2/COMMON/mac_rlc_primitives.h
@@ -165,6 +165,9 @@ in a suspended state or to indicate the current buffer occupancy to MAC.
 struct mac_status_resp {
   unsigned int             buffer_occupancy_in_bytes;   /*!< \brief the parameter Buffer Occupancy (BO) indicates for each logical channel the amount of data in number of bytes that is available for transmission and retransmission in RLC layer. */
   unsigned short             buffer_occupancy_in_pdus;    /*!< xxx*/
+  u32_t             head_sdu_creation_time;          
+  u32_t             head_sdu_remaining_size_to_send;
+  unsigned char     head_sdu_is_segmented;
   struct rlc_entity_info rlc_info;             /*!< xxx*/
 };
 
diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h
index bdf5f6ed296..2ed4f7de46d 100644
--- a/openair2/LAYER2/MAC/defs.h
+++ b/openair2/LAYER2/MAC/defs.h
@@ -511,6 +511,17 @@ typedef struct{
   u32_t dl_buffer_info[MAX_NUM_LCID];
 
   u32_t dl_buffer_total;
+
+  u32_t dl_pdus_total;
+
+  u32_t dl_pdus_in_buffer[MAX_NUM_LCID];
+  
+  u32_t dl_buffer_head_sdu_creation_time[MAX_NUM_LCID];
+
+  u8    dl_buffer_head_sdu_is_segmented[MAX_NUM_LCID];
+
+  u32_t dl_buffer_head_sdu_remaining_size_to_send[MAX_NUM_LCID];
+
 } UE_TEMPLATE;
 
 typedef struct {
@@ -1079,6 +1090,9 @@ u8 is_UE_active(unsigned char Mod_id, unsigned char UE_id );
 u16 find_ulgranted_UEs(u8 Mod_id);
 u16 find_dlgranted_UEs(u8 Mod_id);
 u8 process_ue_cqi (u8 Mod_id, u8 UE_id);
+
+s8 find_active_UEs_with_traffic(unsigned char Mod_id);
+
 u8 find_num_active_UEs_in_cbagroup(unsigned char Mod_id, unsigned char group_id);
 u8 UE_is_to_be_scheduled(u8 Mod_id,u8 UE_id);
 /** \brief Round-robin scheduler for ULSCH traffic.
diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c
index bef4ad56dee..82678a0a588 100644
--- a/openair2/LAYER2/MAC/pre_processor.c
+++ b/openair2/LAYER2/MAC/pre_processor.c
@@ -88,9 +88,14 @@ void store_dlsch_buffer (unsigned char Mod_id,
   granted_UEs = find_dlgranted_UEs(Mod_id);
 
   for (UE_id=0;UE_id<granted_UEs;UE_id++){
-    eNB_mac_inst[Mod_id].UE_template[UE_id].dl_buffer_total = 0;
-    for(i=0;i< MAX_NUM_LCID; i++)
+    eNB_mac_inst[Mod_id].UE_template[UE_id].dl_buffer_total = 0; 
+    eNB_mac_inst[Mod_id].UE_template[UE_id].dl_pdus_total = 0;
+    for(i=0;i< MAX_NUM_LCID; i++) {
       eNB_mac_inst[Mod_id].UE_template[UE_id].dl_buffer_info[i]=0;
+      eNB_mac_inst[Mod_id].UE_template[UE_id].dl_pdus_in_buffer[i]=0;
+      eNB_mac_inst[Mod_id].UE_template[UE_id].dl_buffer_head_sdu_creation_time[i]=0;
+      eNB_mac_inst[Mod_id].UE_template[UE_id].dl_buffer_head_sdu_remaining_size_to_send[i]=0;
+    }
   }
 
 
@@ -106,11 +111,36 @@ void store_dlsch_buffer (unsigned char Mod_id,
       
       rlc_status = mac_rlc_status_ind(Mod_id,frame,1,RLC_MBMS_NO,i+(NB_RB_MAX*next_ue),0 );
       eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel
-      
+      eNB_mac_inst[Mod_id].UE_template[next_ue].dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer; 
+      eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ;
+      eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_head_sdu_remaining_size_to_send[i] = rlc_status.head_sdu_remaining_size_to_send;
+      eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_head_sdu_is_segmented[i] = rlc_status.head_sdu_is_segmented;
       eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_total = eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_total + eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_info[i];//storing the total dlsch buffer
-      
+      eNB_mac_inst[Mod_id].UE_template[next_ue].dl_pdus_total += eNB_mac_inst[Mod_id].UE_template[next_ue].dl_pdus_in_buffer[i];
+
+#ifdef DEBUG_eNB_SCHEDULER     
+      /* note for dl_buffer_head_sdu_remaining_size_to_send[i] :
+       * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent
+       */
+      if (eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_info[i]>0)
+	LOG_D(MAC,"[eNB %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and %d size, head sdu queuing time %d, remaining size %d, is segmeneted %d \n",
+	    Mod_id, frame, subframe, next_ue, 
+	    i, eNB_mac_inst[Mod_id].UE_template[next_ue].dl_pdus_in_buffer[i],eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_info[i],
+	    eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_head_sdu_creation_time[i],
+	      eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_head_sdu_remaining_size_to_send[i],
+	      eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_head_sdu_is_segmented[i]
+	    );
+#endif   
       
     }
+#ifdef DEBUG_eNB_SCHEDULER        
+    if ( eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_total>0)
+      LOG_D(MAC,"[eNB %d] Frame %d Subframe %d : RLC status for UE %d : total DL buffer size %d and total number of pdu %d \n",
+	    Mod_id, frame, subframe, next_ue, 
+	    eNB_mac_inst[Mod_id].UE_template[next_ue].dl_buffer_total,
+	    eNB_mac_inst[Mod_id].UE_template[next_ue].dl_pdus_total
+	    );
+#endif   
   }
 }
 
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 282fab08dae..e550eeaf990 100755
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
@@ -45,7 +45,7 @@ Address      : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis
 //#define TRACE_RLC_AM_DATA_REQUEST
 //#define TRACE_RLC_AM_TX_STATUS
 //#define TRACE_RLC_AM_TX
-#//define TRACE_RLC_AM_RX
+//#define TRACE_RLC_AM_RX
 //#define TRACE_RLC_AM_BO
 //-----------------------------------------------------------------------------
 u32_t
@@ -439,10 +439,16 @@ rlc_am_mac_status_indication (void *rlcP, u32 frame, u16 tb_sizeP, struct mac_st
 {
 //-----------------------------------------------------------------------------
   struct mac_status_resp  status_resp;
+  u16_t  sdu_size = 0;
+  u16_t  sdu_remaining_size = 0;
+  s32_t diff_time=0;
   rlc_am_entity_t *rlc = (rlc_am_entity_t *) rlcP;
 
-  status_resp.buffer_occupancy_in_bytes = 0;
-  status_resp.buffer_occupancy_in_pdus  = 0;
+  status_resp.buffer_occupancy_in_bytes        = 0;
+  status_resp.buffer_occupancy_in_pdus         = 0;
+  status_resp.head_sdu_remaining_size_to_send  = 0;
+  status_resp.head_sdu_creation_time           = 0;
+  status_resp.head_sdu_is_segmented            = 0;
   status_resp.rlc_info.rlc_protocol_state = rlc->protocol_state;
 
   if (rlc->last_frame_status_indication != frame) {
@@ -455,6 +461,30 @@ rlc_am_mac_status_indication (void *rlcP, u32 frame, u16 tb_sizeP, struct mac_st
   rlc->nb_bytes_requested_by_mac = tb_sizeP;
 
   status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(rlc,frame);
+  
+  if ((rlc->input_sdus[rlc->current_sdu_index].mem_block != NULL) && (status_resp.buffer_occupancy_in_bytes)) {
+          
+	  //status_resp.buffer_occupancy_in_bytes += ((rlc_am_entity_t *) rlc)->tx_header_min_length_in_bytes;
+	  status_resp.buffer_occupancy_in_pdus = rlc->nb_sdu;
+	  diff_time =   frame - ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_creation_time;
+	  
+	  status_resp.head_sdu_creation_time = (diff_time > 0 ) ? (u32_t) diff_time :  (u32_t)(0xffffffff - diff_time + frame) ;
+	  
+	  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.head_sdu_remaining_size_to_send = sdu_remaining_size;
+	  if (sdu_size == sdu_remaining_size)  {
+           status_resp.head_sdu_is_segmented = 0; 
+	  }
+	  else {
+	   status_resp.head_sdu_is_segmented = 1; 
+	  }
+	
+  } else {
+  }
+  
+  
 #ifdef TRACE_RLC_AM_TX_STATUS
   if (tb_sizeP > 0) {
       LOG_D(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] MAC_STATUS_INDICATION (DATA) %d bytes -> %d bytes\n", frame, rlc->module_id, rlc->rb_id, tb_sizeP, status_resp.buffer_occupancy_in_bytes);
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
index a62306b0eb8..ccd64dd5d53 100755
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
@@ -334,19 +334,46 @@ rlc_um_mac_status_indication (void *rlcP, u32_t frame, u8_t eNB_flag, u16_t tbs_
 {
 //-----------------------------------------------------------------------------
   struct mac_status_resp status_resp;
-
-  status_resp.buffer_occupancy_in_pdus    = 0;
-  status_resp.buffer_occupancy_in_bytes   = 0;
-  status_resp.rlc_info.rlc_protocol_state = ((rlc_um_entity_t *) rlcP)->protocol_state;
+  u16_t  sdu_size = 0;
+  u16_t  sdu_remaining_size = 0;
+  s32_t diff_time=0;
+  rlc_um_entity_t   *rlc = NULL;
+  
+  status_resp.buffer_occupancy_in_pdus         = 0;
+  status_resp.buffer_occupancy_in_bytes        = 0;
+  status_resp.head_sdu_remaining_size_to_send  = 0;
+  status_resp.head_sdu_creation_time           = 0;
+  status_resp.head_sdu_is_segmented            = 0;
+  status_resp.rlc_info.rlc_protocol_state      = ((rlc_um_entity_t *) rlcP)->protocol_state;
 
   if (rlcP) {
-      rlc_um_check_timer_dar_time_out((rlc_um_entity_t *) rlcP,frame,eNB_flag);
+      rlc = (rlc_um_entity_t *) rlcP;
+      rlc_um_check_timer_dar_time_out(rlc,frame,eNB_flag);
 
-      ((rlc_um_entity_t *) rlcP)->nb_bytes_requested_by_mac = tbs_sizeP;
+      rlc->nb_bytes_requested_by_mac = tbs_sizeP;
 
-      status_resp.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy ((rlc_um_entity_t *) rlcP);
+      status_resp.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (rlc);
       if (status_resp.buffer_occupancy_in_bytes > 0) {
-          status_resp.buffer_occupancy_in_bytes += ((rlc_um_entity_t *) rlcP)->tx_header_min_length_in_bytes;
+          
+	  status_resp.buffer_occupancy_in_bytes += rlc->tx_header_min_length_in_bytes;
+	  status_resp.buffer_occupancy_in_pdus = rlc->nb_sdu;
+	 
+	  diff_time =   frame - ((struct rlc_um_tx_sdu_management *) (rlc->input_sdus[rlc->current_sdu_index])->data)->sdu_creation_time;
+	  status_resp.head_sdu_creation_time = (diff_time > 0 ) ? (u32_t) diff_time :  (u32_t)(0xffffffff - diff_time + frame) ;
+	  //msg("rlc status for frame %d diff time %d resp %d\n", frame, diff_time,status_resp.head_sdu_creation_time) ;
+	  
+	  sdu_size            = ((struct rlc_um_tx_sdu_management *) (rlc->input_sdus[rlc->current_sdu_index])->data)->sdu_size;
+	  sdu_remaining_size  = ((struct rlc_um_tx_sdu_management *) (rlc->input_sdus[rlc->current_sdu_index])->data)->sdu_remaining_size;
+	  
+	  status_resp.head_sdu_remaining_size_to_send = sdu_remaining_size;	
+	  if (sdu_size == sdu_remaining_size)  {
+           status_resp.head_sdu_is_segmented = 0;
+	  }
+	  else {
+	   status_resp.head_sdu_is_segmented = 1;
+	  }
+	
+      } else {
       }
       //msg("[RLC_UM][MOD %d][RB %d][FRAME %05d] MAC_STATUS_INDICATION BO = %d\n", ((rlc_um_entity_t *) rlcP)->module_id, ((rlc_um_entity_t *) rlcP)->rb_id, status_resp.buffer_occupancy_in_bytes);
 
@@ -465,8 +492,7 @@ rlc_um_data_req (void *rlcP, u32_t frame, mem_block_t *sduP)
     ((struct rlc_um_tx_sdu_management *) (sduP->data))->sdu_remaining_size = ((struct rlc_um_tx_sdu_management *)
                                                                               (sduP->data))->sdu_size;
     ((struct rlc_um_tx_sdu_management *) (sduP->data))->sdu_segmented_size = 0;
-    // LG ((struct rlc_um_tx_sdu_management *) (sduP->data))->sdu_creation_time = *rlc->frame_tick_milliseconds;
-    // LG ??? WHO WROTE THAT LINE ?((struct rlc_um_tx_sdu_management *) (sduP->data))->sdu_creation_time = 0;
+    ((struct rlc_um_tx_sdu_management *) (sduP->data))->sdu_creation_time = frame;
     rlc->next_sdu_index = (rlc->next_sdu_index + 1) % rlc->size_input_sdus_buffer;
 
     rlc->stat_tx_pdcp_sdu   += 1;
diff --git a/openair2/LAYER2/RLC/mac_primitives.h b/openair2/LAYER2/RLC/mac_primitives.h
index 0cedf7440e0..4b54f8be968 100644
--- a/openair2/LAYER2/RLC/mac_primitives.h
+++ b/openair2/LAYER2/RLC/mac_primitives.h
@@ -172,7 +172,7 @@ struct mac_data_ind {
 //---------------------
 struct mac_status_resp {
   u32_t             buffer_occupancy_in_bytes;
-  u16_t             buffer_occupancy_in_pdus;
+  u32_t             buffer_occupancy_in_pdus;
   struct rlc_entity_info rlc_info;
 };
 //---------------------
diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h
index 85865e24392..aa35be6d794 100755
--- a/openair2/LAYER2/RLC/rlc.h
+++ b/openair2/LAYER2/RLC/rlc.h
@@ -132,6 +132,9 @@ typedef volatile struct {
 typedef  struct {
     u32_t                        bytes_in_buffer; /*!< \brief Bytes buffered in RLC protocol instance. */
     u32_t                        pdus_in_buffer;  /*!< \brief Number of PDUs buffered in RLC protocol instance (OBSOLETE). */
+    u32_t                        head_sdu_creation_time;           /*!< \brief Head SDU creation time. */
+    u32_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 */
+    u32_t  			  head_sdu_is_segmented;	    /*!< \brief 0 if head SDU has not been segmented, 1 if already segmeneted */	
 } mac_rlc_status_resp_t;
 
 
diff --git a/openair2/LAYER2/RLC/rlc_mac.c b/openair2/LAYER2/RLC/rlc_mac.c
index 099a95c1d46..ba96a306a8d 100644
--- a/openair2/LAYER2/RLC/rlc_mac.c
+++ b/openair2/LAYER2/RLC/rlc_mac.c
@@ -215,7 +215,9 @@ mac_rlc_status_resp_t mac_rlc_status_ind     (module_id_t module_idP, u32_t fram
                     case RLC_AM:
                         status_resp = rlc_am_mac_status_indication(&rlc[module_idP].m_rlc_am_array[rlc[module_idP].m_rlc_pointer[channel_idP].rlc_index], frame, tb_sizeP, tx_status);
                         mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes;
-                        mac_rlc_status_resp.pdus_in_buffer = status_resp.buffer_occupancy_in_pdus;
+                        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;	
                         return mac_rlc_status_resp;
                         break;
 
@@ -223,7 +225,10 @@ mac_rlc_status_resp_t mac_rlc_status_ind     (module_id_t module_idP, u32_t fram
                         //msg("[RLC_UM][MOD %d] mac_rlc_status_ind  tb_size %d\n", module_idP,  tb_sizeP);
                         status_resp = rlc_um_mac_status_indication(&rlc[module_idP].m_rlc_um_array[rlc[module_idP].m_rlc_pointer[channel_idP].rlc_index], frame, eNB_flag, tb_sizeP, tx_status);
                         mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes;
-                        //mac_rlc_status_resp.pdus_in_buffer = status_resp.buffer_occupancy_in_pdus;
+                        mac_rlc_status_resp.pdus_in_buffer = status_resp.buffer_occupancy_in_pdus;
+			 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;	
                         return mac_rlc_status_resp;
                         break;
 
diff --git a/targets/SIMU/USER/Makefile b/targets/SIMU/USER/Makefile
index 35a7e9ffe8c..80532dbc61b 100644
--- a/targets/SIMU/USER/Makefile
+++ b/targets/SIMU/USER/Makefile
@@ -65,12 +65,14 @@ ifdef XFORMS
 CFLAGS += -DXFORMS
 endif
 
+ifdef DB
 # Check if libmysqlclient is installed and use it if found to store simulation data for postprocessing
 ENABLE_DB = $(shell if [ `dpkg -l | grep libmysqlclient -c` = "0" ]; then  echo "0" ; else  echo "1" ; fi )
 ifeq ($(ENABLE_DB), 1)
 CFLAGS +=-I/usr/include/mysql -L/usr/lib/mysql -DENABLE_DB_STATS
 DB_LDFLAGS = -lmysqlclient
 endif 
+endif 
 
 ifdef PRINT_STATS
 CFLAGS += -DPRINT_STATS
-- 
GitLab