diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 4312b33beb7e6a48526eb5b6addfc6ae96076b37..734bfccf2d060a8791367f58e6ede0adbf9600a5 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1148,6 +1148,7 @@ if (FLEXRAN_AGENT_SB_IF)
 
 set (MAC_SRC ${MAC_SRC}
   ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue.c
+  ${MAC_DIR}/flexran_agent_scheduler_ulsch_ue.c
   ${MAC_DIR}/flexran_agent_scheduler_dataplane.c
   ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue_remote.c
 )
@@ -1171,6 +1172,9 @@ if (FLEXRAN_AGENT_SB_IF)
 add_library(default_sched SHARED ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue.c)
 add_library(remote_sched SHARED ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue_remote.c)
 
+add_library(default_ul_sched SHARED ${MAC_DIR}/flexran_agent_scheduler_ulsch_ue.c)
+
+
 endif()
 
 # L3 Libs
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c
index 73ae74a32f775641545c1e150c4686e7a4ca50dd..512be68669800472fb565e0d186015f3af5ccfd0 100644
--- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c
@@ -1044,6 +1044,78 @@ int flexran_agent_mac_destroy_dl_config(Protocol__FlexranMessage *msg) {
   return -1;
 }
 
+int flexran_agent_mac_create_empty_ul_config(mid_t mod_id, Protocol__FlexranMessage **msg) {
+
+  int xid = 0;
+  Protocol__FlexHeader *header;
+  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_UL_MAC_CONFIG, &header) != 0)
+    goto error;
+
+  Protocol__FlexUlMacConfig *ul_mac_config_msg;
+  ul_mac_config_msg = malloc(sizeof(Protocol__FlexUlMacConfig));
+  if (ul_mac_config_msg == NULL) {
+    goto error;
+  }
+  protocol__flex_ul_mac_config__init(ul_mac_config_msg);
+
+  ul_mac_config_msg->header = header;
+  ul_mac_config_msg->has_sfn_sf = 1;
+  ul_mac_config_msg->sfn_sf = flexran_get_sfn_sf(mod_id);
+
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if(*msg == NULL)
+    goto error;
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_MAC_CONFIG_MSG;
+  (*msg)->msg_dir =  PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+  (*msg)->ul_mac_config_msg = ul_mac_config_msg;
+
+  return 0;
+
+ error:
+  return -1;
+}
+
+
+int flexran_agent_mac_destroy_ul_config(Protocol__FlexranMessage *msg) {
+  int i,j, k;
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_MAC_CONFIG_MSG)
+    goto error;
+
+  Protocol__FlexUlDci *ul_dci;
+
+  free(msg->ul_mac_config_msg->header);
+  for (i = 0; i < msg->ul_mac_config_msg->n_ul_ue_data; i++) {
+    // TODO  uplink rlc ...
+    // free(msg->ul_mac_config_msg->dl_ue_data[i]->ce_bitmap); 
+  //   for (j = 0; j < msg->ul_mac_config_msg->ul_ue_data[i]->n_rlc_pdu; j++) {
+  //     for (k = 0; k <  msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu[j]->n_rlc_pdu_tb; k++) {
+  // free(msg->ul_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb[k]);
+  //     }
+  //     free(msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb);
+  //     free(msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu[j]);
+  //   }
+    // free(msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu);
+    ul_dci = msg->ul_mac_config_msg->ul_ue_data[i]->ul_dci;
+    // free(dl_dci->tbs_size);
+    // free(ul_dci->mcs);
+    // free(ul_dci->ndi);
+    // free(ul_dci->rv);
+    // free(ul_dci);
+    free(msg->ul_mac_config_msg->ul_ue_data[i]);
+  }
+  free(msg->ul_mac_config_msg->ul_ue_data);
+  
+  free(msg->ul_mac_config_msg);
+  free(msg);
+
+  return 0;
+
+ error:
+  return -1;
+}
+
+
 void flexran_agent_get_pending_dl_mac_config(mid_t mod_id, Protocol__FlexranMessage **msg) {
 
   struct lfds700_misc_prng_state ls;
@@ -1176,12 +1248,13 @@ int flexran_agent_register_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) {
   xface->flexran_agent_send_sr_info = flexran_agent_send_sr_info;
   xface->flexran_agent_send_sf_trigger = flexran_agent_send_sf_trigger;
   //xface->flexran_agent_send_update_mac_stats = flexran_agent_send_update_mac_stats;
-  xface->flexran_agent_schedule_ue_spec = flexran_schedule_ue_spec_default;
+  xface->flexran_agent_schedule_ue_spec = flexran_schedule_ue_dl_spec_default;
+  xface->flexran_agent_schedule_ul_spec = flexran_schedule_ue_ul_spec_default;
   //xface->flexran_agent_schedule_ue_spec = flexran_schedule_ue_spec_remote;
   xface->flexran_agent_get_pending_dl_mac_config = flexran_agent_get_pending_dl_mac_config;
   
   xface->dl_scheduler_loaded_lib = NULL;
-
+  xface->ul_scheduler_loaded_lib = NULL;
   mac_agent_registered[mod_id] = 1;
   agent_mac_xface[mod_id] = xface;
 
@@ -1199,7 +1272,7 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) {
   
 
   xface->dl_scheduler_loaded_lib = NULL;
-
+  xface->ul_scheduler_loaded_lib = NULL;
   mac_agent_registered[mod_id] = 0;
   agent_mac_xface[mod_id] = NULL;
 
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h
index d2db860ce45d65908d8a3091531019b9da04acb9..0dcee577f592729b94bfdcd75e0f0ab34e27c44d 100644
--- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h
@@ -57,6 +57,10 @@ int flexran_agent_mac_destroy_stats_reply(Protocol__FlexranMessage *msg);
 int flexran_agent_mac_create_empty_dl_config(mid_t mod_id, Protocol__FlexranMessage **msg);
 int flexran_agent_mac_destroy_dl_config(Protocol__FlexranMessage *msg);
 
+/* UL MAC scheduling decision protocol message constructor (empty command) and destructor */ 
+int flexran_agent_mac_create_empty_ul_config(mid_t mod_id, Protocol__FlexranMessage **msg);
+int flexran_agent_mac_destroy_ul_config(Protocol__FlexranMessage *msg);
+
 int flexran_agent_mac_handle_dl_mac_config(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
 
 
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_defs.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_defs.h
index 83542231231ebeb2768ae12b3bcef12d40b16202..362c50f13cee3c2c61e06f80531d5b8cfb0a5d3c 100644
--- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_defs.h
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_defs.h
@@ -61,6 +61,9 @@ typedef struct {
 					 int *mbsfn_flag, Protocol__FlexranMessage **dl_info);
   
 
+ void (*flexran_agent_schedule_ul_spec)(mid_t module_idP,  uint32_t frameP, unsigned char cooperation_flag,
+        uint32_t subframeP, unsigned char sched_subframe, Protocol__FlexranMessage **ul_info);
+
   /// Notify the controller for a state change of a particular UE, by sending the proper
   /// UE state change message (ACTIVATION, DEACTIVATION, HANDOVER)
   // int (*flexran_agent_notify_ue_state_change)(mid_t mod_id, uint32_t rnti,
@@ -68,6 +71,7 @@ typedef struct {
   
   
   void *dl_scheduler_loaded_lib;
+  void *ul_scheduler_loaded_lib;
   /*TODO: Fill in with the rest of the MAC layer technology specific callbacks (UL/DL scheduling, RACH info etc)*/
 
 } AGENT_MAC_xface;
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
index 66efafae555aa1c792ebb57fcc677da993569643..68b82713e6ae80abb4b6c798bfe869bc858e1828 100644
--- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
@@ -607,7 +607,10 @@ int parse_mac_config(mid_t mod_id, yaml_parser_t *parser) {
       } else if (strcmp((char *) event.data.scalar.value, "ul_scheduler") == 0) {
 	// Call the proper handler
 	LOG_D(ENB_APP, "This is for the ul_scheduler subsystem\n");
-	goto error;
+	if (parse_ul_scheduler_config(mod_id, parser) == -1) {
+    LOG_D(ENB_APP, "An error occured\n");
+    goto error;
+  }
 	// TODO
       } else if (strcmp((char *) event.data.scalar.value, "ra_scheduler") == 0) {
 	// Call the proper handler
@@ -700,6 +703,56 @@ int parse_dl_scheduler_config(mid_t mod_id, yaml_parser_t *parser) {
   return -1;
 }
 
+int parse_ul_scheduler_config(mid_t mod_id, yaml_parser_t *parser) {
+  
+  yaml_event_t event;
+
+  int done = 0;
+  int mapping_started = 0;
+
+  while (!done) {
+    
+    if (!yaml_parser_parse(parser, &event))
+      goto error;
+
+    switch (event.type) {
+      // We are expecting a mapping (behavior and parameters)
+    case YAML_MAPPING_START_EVENT:
+      LOG_D(ENB_APP, "The mapping of the subsystem started\n");
+      mapping_started = 1;
+      break;
+    case YAML_MAPPING_END_EVENT:
+      LOG_D(ENB_APP, "The mapping of the subsystem ended\n");
+      mapping_started = 0;
+      break;
+    case YAML_SCALAR_EVENT:
+      if (!mapping_started) {
+  goto error;
+      }
+      // Check what key needs to be set
+      if (strcmp((char *) event.data.scalar.value, "parameters") == 0) {
+  LOG_D(ENB_APP, "Now it is time to set the parameters for this subsystem\n");
+  if (parse_ul_scheduler_parameters(mod_id, parser) == -1) {
+    goto error;
+  }
+      }
+      break;
+    default:
+      goto error;
+    }
+
+    done = (event.type == YAML_MAPPING_END_EVENT);
+    yaml_event_delete(&event);
+  }
+
+  return 0;
+
+ error:
+  yaml_event_delete(&event);
+  return -1;
+}
+
+
 int parse_dl_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser) {
   yaml_event_t event;
   
@@ -755,6 +808,61 @@ int parse_dl_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser) {
   return -1;
 }
 
+int parse_ul_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser) {
+  yaml_event_t event;
+  
+  void *param;
+  
+  int done = 0;
+  int mapping_started = 0;
+
+  while (!done) {
+    
+    if (!yaml_parser_parse(parser, &event))
+      goto error;
+
+    switch (event.type) {
+      // We are expecting a mapping of parameters
+    case YAML_MAPPING_START_EVENT:
+      LOG_D(ENB_APP, "The mapping of the parameters started\n");
+      mapping_started = 1;
+      break;
+    case YAML_MAPPING_END_EVENT:
+      LOG_D(ENB_APP, "The mapping of the parameters ended\n");
+      mapping_started = 0;
+      break;
+    case YAML_SCALAR_EVENT:
+      if (!mapping_started) {
+  goto error;
+      }
+      // Check what key needs to be set
+      if (mac_agent_registered[mod_id]) {
+  LOG_D(ENB_APP, "Setting parameter %s\n", event.data.scalar.value);
+  param = dlsym(agent_mac_xface[mod_id]->ul_scheduler_loaded_lib,
+          (char *) event.data.scalar.value);
+  if (param == NULL) {
+    goto error;
+  }
+  apply_parameter_modification(param, parser);
+      } else {
+  goto error;
+      }
+      break;
+    default:
+      goto error;
+    }
+
+    done = (event.type == YAML_MAPPING_END_EVENT);
+    yaml_event_delete(&event);
+  }
+
+  return 0;
+  
+ error:
+  yaml_event_delete(&event);
+  return -1;
+}
+
 int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
   void *lib;
 
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h
index 9a7d4a8555b070fde7f389e30b46d256f84bc278..95f6934e56d4a4bc01b7806ac985ff5e29ce5b18 100644
--- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h
@@ -101,6 +101,10 @@ int parse_dl_scheduler_config(mid_t mod_id, yaml_parser_t *parser);
 
 int parse_dl_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser);
 
+int parse_ul_scheduler_config(mid_t mod_id, yaml_parser_t *parser);
+
+int parse_ul_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser);
+
 int load_dl_scheduler_function(mid_t mod_id, const char *function_name);
 
 #endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/
diff --git a/openair2/ENB_APP/MESSAGES/V2/controller_commands.proto b/openair2/ENB_APP/MESSAGES/V2/controller_commands.proto
index cbec332b304085d4389d7b3498556fc29a9803dd..252efc6aefb3fff24e0e61389272cc3af9f5ba99 100644
--- a/openair2/ENB_APP/MESSAGES/V2/controller_commands.proto
+++ b/openair2/ENB_APP/MESSAGES/V2/controller_commands.proto
@@ -3,7 +3,7 @@ package protocol;
 import "mac_primitives.proto";
 
 //
-// Body of UE DL MAC scheduling configuration info
+// Body of UE DL/UL MAC scheduling configuration info
 //
 
 message flex_dl_data {
@@ -15,6 +15,12 @@ message flex_dl_data {
 	optional uint32 act_deact_ce = 6; //Hex content of MAC CE for Activation/Deactivation in CA
 }
 
+
+message flex_ul_data {
+	optional uint32 rnti = 1;
+  	optional flex_ul_dci ul_dci = 2;
+}
+
 //
 // Body of the RAR scheduler configuration
 //
@@ -55,4 +61,4 @@ message flex_pdcch_ofdm_sym_count {
 enum flex_broadcast_type {
      FLBT_BCCH = 0;
      FLBT_PCCH = 1;
-}
\ No newline at end of file
+}
diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto
index 7fb3a22df8e103103c12162573cf5175ee14f636..8ebfc7df8b55595119b0a6883ef9d40d0c92c918 100644
--- a/openair2/ENB_APP/MESSAGES/V2/flexran.proto
+++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto
@@ -24,11 +24,12 @@ message flexran_message {
 	      flex_ue_config_reply ue_config_reply_msg = 11;
 	      flex_lc_config_request lc_config_request_msg = 12;
 	      flex_lc_config_reply lc_config_reply_msg = 13;
-	      flex_dl_mac_config dl_mac_config_msg = 14;
+	      flex_dl_mac_config dl_mac_config_msg = 14;	      
 	      flex_ue_state_change ue_state_change_msg = 15;
 	      flex_control_delegation control_delegation_msg = 16;
 	      flex_agent_reconfiguration agent_reconfiguration_msg = 17;
 	      flex_rrc_triggering rrc_triggering = 18;
+	      flex_ul_mac_config ul_mac_config_msg = 19;
 	}
 }
 
@@ -164,6 +165,14 @@ message flex_dl_mac_config {
 	repeated flex_pdcch_ofdm_sym_count ofdm_sym = 6; // OFDM symbol count for each CC
 }
 
+
+message flex_ul_mac_config {
+	optional flex_header header = 1;
+    optional uint32 sfn_sf = 2;
+    repeated flex_ul_data ul_ue_data = 3;
+}
+
+
 message flex_rrc_triggering {
 
   optional flex_header header = 1;
@@ -171,6 +180,7 @@ message flex_rrc_triggering {
 }
 
 
+
 //
 // UE state change message
 //
diff --git a/openair2/ENB_APP/MESSAGES/V2/header.proto b/openair2/ENB_APP/MESSAGES/V2/header.proto
index 468dcd201e5ae05fda69ed789448450622bdbb70..79d541200cc0ee548160ef0bdac085be991192a3 100644
--- a/openair2/ENB_APP/MESSAGES/V2/header.proto
+++ b/openair2/ENB_APP/MESSAGES/V2/header.proto
@@ -32,7 +32,7 @@ enum flex_type {
 
      //Controller command messages
      FLPT_DL_MAC_CONFIG = 13;
-
+     
      // UE state change messages
      FLPT_UE_STATE_CHANGE = 14;
 
@@ -40,6 +40,6 @@ enum flex_type {
      FLPT_DELEGATE_CONTROL = 15;
      FLPT_RECONFIGURE_AGENT = 16;
      FLPT_RRC_TRIGGERING = 17;
-
+     FLPT_UL_MAC_CONFIG = 18;
 }
 
diff --git a/openair2/ENB_APP/MESSAGES/V2/mac_primitives.proto b/openair2/ENB_APP/MESSAGES/V2/mac_primitives.proto
index be7c72ab7b07a4dd69bc99d5f7c4b9765d79c1c9..01f8799a17f8ced6a8ae739e6090adbd4b3f74ef 100644
--- a/openair2/ENB_APP/MESSAGES/V2/mac_primitives.proto
+++ b/openair2/ENB_APP/MESSAGES/V2/mac_primitives.proto
@@ -33,6 +33,38 @@ message flex_dl_dci {
 	optional uint32 pdcch_power_offset = 25; // DL PDCCH power boosting in dB
 	optional uint32 cif_present = 26;    	// Boolean. Indication of CIF field
 	optional uint32 cif = 27;     		// CIF for cross-carrier scheduling
+}
+
+message flex_ul_dci {
+	optional uint32 rnti = 1;
+	optional uint32 rb_start = 2;		// The start RB allocated to the UE 
+	optional uint32 rb_len = 3;		// The number of RBs allocated to the UE
+	optional uint32 mcs = 4;		// Modulation and coding scheme
+	optional uint32 cyclic_shift2 = 5;	//  match DCI format 0/4 PDU 
+	optional uint32 freq_hop_flag = 6;   	// 0 no hopping, 1 hoppping
+	optional uint32 freq_hop_map = 7;	// Frequency hopping bits (0..4) 
+	optional uint32 ndi = 8;		// New data indicator
+  	optional uint32 rv = 9;			// Redundancy version
+  	optional uint32 harq_pid = 10; 		//  The harq process id
+	optional uint32 ultx_mode = 11; 	//  A FLULM_* value
+  	optional uint32 tbs_size = 12;		// The size of each TBS
+	optional uint32 n_srs = 13;    		// Overlap indication with srs
+  	optional uint32 res_alloc = 14;		// Type of resource allocation
+  	optional uint32 size = 15;    // Size of the ULSCH PDU in bytes for UL Grant.
+
+	optional uint32 dai = 16;      		// TDD only
+
+//	optional uint32 tb_swap = 17;	 	// Boolean. TB to codeword swap flag
+
+//	optional uint32 pdcch_order = 19;
+//	optional uint32 preamble_index = 20;	// Only valid if pdcch_order = 1
+//	optional uint32 prach_mask_index = 21;	// Only valid if pdcch_order = 1
+	
+//	optional uint32 tbs_idx = 23;		// The TBS index for Format 1A
+	
+
+
+
 }
 
 //
@@ -73,4 +105,10 @@ enum flex_vrb_format {
 enum flex_ngap_val {
      FLNGV_1 = 0;
      FLNGV_2 = 1;
-}
\ No newline at end of file
+}
+
+enum flex_mod_type {
+    FLMOD_QPSK = 2; 
+    FLMOD_16QAM = 4;
+    FLMOD_64QAM = 6;
+}
diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c
index 9602b041c3ccf6ccc21a409c8c182f00bf9af8ac..ae304d1e262e1419d5c14859bfc9eaa2aaeb7ce0 100644
--- a/openair2/ENB_APP/flexran_agent_ran_api.c
+++ b/openair2/ENB_APP/flexran_agent_ran_api.c
@@ -299,8 +299,9 @@ int flexran_get_harq(const mid_t mod_id,
 		     const mid_t ue_id, 
 		     const int frame, 
 		     const uint8_t subframe, 
-		     uint8_t *id, 
-		     uint8_t *round)	{ //flag_id_status = 0 then id, else status
+		     uint8_t *pid, 
+		     uint8_t *round,
+         const uint8_t harq_flag)	{ //flag_id_status = 0 then id, else status
 	/*TODO: Add int TB in function parameters to get the status of the second TB. This can be done to by editing in
 	 * get_ue_active_harq_pid function in line 272 file: phy_procedures_lte_eNB.c to add
 	 * DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch_eNB[(uint32_t)UE_id][1];*/
@@ -310,10 +311,21 @@ int flexran_get_harq(const mid_t mod_id,
   
 
   uint16_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+  if (harq_flag == openair_harq_DL){
 
-  mac_xface->get_ue_active_harq_pid(mod_id,CC_id,rnti,frame,subframe,&harq_pid,&harq_round,openair_harq_DL);
+      mac_xface->get_ue_active_harq_pid(mod_id,CC_id,rnti,frame,subframe,&harq_pid,&harq_round,openair_harq_DL);
 
-  *id = harq_pid;
+   } else if (harq_flag == openair_harq_UL){
+
+     mac_xface->get_ue_active_harq_pid(mod_id,CC_id,rnti,frame,subframe,&harq_pid,&round,openair_harq_UL);    
+   }
+   else {
+
+      LOG_W(FLEXRAN_AGENT,"harq_flag is not recongnized");
+   }
+
+
+  *pid = harq_pid;
   *round = harq_round;
   /* if (round > 0) { */
   /*   *status = 1; */
@@ -643,6 +655,21 @@ int flexran_get_meas_gap_config_offset(mid_t mod_id, mid_t ue_id) {
   return -1;
 }
 
+
+int flexran_get_rrc_status(const mid_t mod_id,  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_id],rntiP);
+
+  if (ue_context_p != NULL) {
+    return(ue_context_p->ue_context.Status);
+  } else {
+    return RRC_INACTIVE;
+  }
+
+}
+
 int flexran_get_ue_aggregated_max_bitrate_dl (mid_t mod_id, mid_t ue_id) {
 	return ((UE_list_t *)enb_ue[mod_id])->UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL;
 }
diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h
index 8a7d6dbaf742d7ba5ff5285b395596d7487399e2..e80ed44ce958052b61b3506eb84b8f3a63325f6f 100644
--- a/openair2/ENB_APP/flexran_agent_ran_api.h
+++ b/openair2/ENB_APP/flexran_agent_ran_api.h
@@ -187,7 +187,7 @@ int flexran_get_ue_pmi(mid_t mod_id);
    a designated frame and subframe. Returns 0 for success. The id and the 
    status of the HARQ process are stored in id and status respectively */
 int flexran_get_harq(const mid_t mod_id, const uint8_t CC_id, const mid_t ue_id,
-		     const int frame, const uint8_t subframe, unsigned char *id, unsigned char *round);
+		     const int frame, const uint8_t subframe, unsigned char *id, unsigned char *round,const uint8_t harq_flag);
 
 /* Uplink power control management*/
 int flexran_get_p0_pucch_dbm(mid_t mod_id, mid_t ue_id, int CC_id);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c
index acd76e6c0ed4131d74ffca99ca87a0f46604084a..8575b0b00a324542c392c5306e1e953b9b912bd3 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler.c
@@ -386,11 +386,30 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 
 
     if (mac_xface->frame_parms->frame_type == FDD) {  //FDD
+#ifndef FLEXRAN_AGENT_SB_IF
       schedule_ulsch(module_idP,frameP,cooperation_flag,0,4);//,calibration_flag);
+#else
+      if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,0,4, &msg);   
+      }
+
+      flexran_agent_mac_destroy_ul_config(msg);
+     
+#endif
+
     } else if  ((mac_xface->frame_parms->tdd_config == 0) || //TDD
                 (mac_xface->frame_parms->tdd_config == 3) ||
                 (mac_xface->frame_parms->tdd_config == 6)) {
+#ifndef FLEXRAN_AGENT_SB_IF      
       schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);//,calibration_flag);
+#else
+      if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,subframeP,4, &msg);   
+      }
+
+      flexran_agent_mac_destroy_ul_config(msg);
+     
+#endif      
     }
 #ifndef FLEXRAN_AGENT_SB_IF
     schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
@@ -404,7 +423,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -422,14 +441,36 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       switch (mac_xface->frame_parms->tdd_config) {
       case 0:
       case 1:
-        schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7);
+#ifndef FLEXRAN_AGENT_SB_IF
+      schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7);//,calibration_flag);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,subframeP,7, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif
 #ifndef FLEXRAN_AGENT_SB_IF
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
 #endif
         break;
 
       case 6:
+#ifndef FLEXRAN_AGENT_SB_IF      
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8);
+#else
+
+  if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,subframeP,8, &msg);   
+      }
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif  
+
 #ifndef FLEXRAN_AGENT_SB_IF
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
 #endif
@@ -439,7 +480,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
         break;
       }
     } else { //FDD
+#ifndef FLEXRAN_AGENT_SB_IF            
       schedule_ulsch(module_idP,frameP,cooperation_flag,1,5);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,1,5, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif        
+
 #ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -452,7 +505,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -469,7 +522,20 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
     // TDD, nothing
     // FDD, normal UL/DLSCH
     if (mac_xface->frame_parms->frame_type == FDD) {  //FDD
+#ifndef FLEXRAN_AGENT_SB_IF            
       schedule_ulsch(module_idP,frameP,cooperation_flag,2,6);
+#else
+
+   if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,2,6, &msg);   
+      }
+
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif        
+
 #ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -482,7 +548,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -502,7 +568,18 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
     if (mac_xface->frame_parms->frame_type == TDD) {
       switch (mac_xface->frame_parms->tdd_config) {
       case 2:
+#ifndef FLEXRAN_AGENT_SB_IF                  
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,subframeP,7, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif        
 
         // no break here!
       case 5:
@@ -518,7 +595,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -532,8 +609,20 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
         break;
       }
     } else { //FDD
-
+#ifndef FLEXRAN_AGENT_SB_IF                  
       schedule_ulsch(module_idP,frameP,cooperation_flag,3,7);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,3,7, &msg);   
+      }
+
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif        
+
 #ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -546,7 +635,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -567,7 +656,18 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       switch (mac_xface->frame_parms->tdd_config) {
       case 1:
         //        schedule_RA(module_idP,frameP,subframeP);
+#ifndef FLEXRAN_AGENT_SB_IF                        
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,subframeP,8, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif        
 
         // no break here!
       case 2:
@@ -589,7 +689,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 					       frameP,
 					       subframeP,
 					       mbsfn_status,
@@ -604,8 +704,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       }
     } else {
       if (mac_xface->frame_parms->frame_type == FDD) {  //FDD
-
+#ifndef FLEXRAN_AGENT_SB_IF                        
 	schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,4,8, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif        
+
 #ifndef FLEXRAN_AGENT_SB_IF
 	schedule_ue_spec(module_idP, frameP, subframeP,  mbsfn_status);
         fill_DLSCH_dci(module_idP, frameP, subframeP,   mbsfn_status);
@@ -618,7 +729,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -641,7 +752,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
     //schedule_RA(module_idP,frameP,subframeP,5);
     if (mac_xface->frame_parms->frame_type == FDD) {
       schedule_RA(module_idP,frameP,subframeP,1);
+#ifndef FLEXRAN_AGENT_SB_IF                              
       schedule_ulsch(module_idP,frameP,cooperation_flag,5,9);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,5,9, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif        
+
 #ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP, frameP, subframeP,  mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -654,7 +777,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 					  frameP,
 					  subframeP,
 					  mbsfn_status,
@@ -681,7 +804,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -704,7 +827,18 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
         break;
 
       case 1:
+#ifndef FLEXRAN_AGENT_SB_IF                                    
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,subframeP,2, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif         
         //  schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
 #ifndef FLEXRAN_AGENT_SB_IF
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -712,7 +846,18 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
         break;
 
       case 6:
+#ifndef FLEXRAN_AGENT_SB_IF                                          
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,subframeP,3, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif                 
         //  schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
 #ifndef FLEXRAN_AGENT_SB_IF
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -733,7 +878,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -757,7 +902,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -771,7 +916,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
         break;
       }
     } else { //FDD
+#ifndef FLEXRAN_AGENT_SB_IF                                                
       schedule_ulsch(module_idP,frameP,cooperation_flag,6,0);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,6,0, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif
+
 #ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -784,7 +941,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -817,7 +974,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -840,7 +997,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -854,7 +1011,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
         break;
       }
     } else { //FDD
+#ifndef FLEXRAN_AGENT_SB_IF                                                
       schedule_ulsch(module_idP,frameP,cooperation_flag,7,1);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,7,1, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif
+
 #ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -867,7 +1036,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -892,7 +1061,18 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       case 5:
 
         //  schedule_RA(module_idP,subframeP);
+#ifndef FLEXRAN_AGENT_SB_IF                                                      
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,subframeP,2, &msg);   
+      }
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif
+
 #ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -905,7 +1085,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -919,7 +1099,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
         break;
       }
     } else { //FDD
+#ifndef FLEXRAN_AGENT_SB_IF                                                            
       schedule_ulsch(module_idP,frameP,cooperation_flag,8,2);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,8,2, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif
+
 #ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -932,7 +1124,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -950,7 +1142,18 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
     if (mac_xface->frame_parms->frame_type == TDD) {
       switch (mac_xface->frame_parms->tdd_config) {
       case 1:
+#ifndef FLEXRAN_AGENT_SB_IF                                                                  
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,subframeP,3, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif        
         schedule_RA(module_idP,frameP,subframeP,7);  // 7 = Msg3 subframeP, not
 #ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
@@ -964,7 +1167,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -976,7 +1179,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 
       case 3:
       case 4:
+#ifndef FLEXRAN_AGENT_SB_IF                                                                        
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,subframeP,3, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif 
+
 #ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -989,7 +1204,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -1000,7 +1215,18 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
         break;
 
       case 6:
+#ifndef FLEXRAN_AGENT_SB_IF                                                                              
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,subframeP,4, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif         
         //schedule_RA(module_idP,frameP,subframeP);
 #ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
@@ -1014,7 +1240,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -1039,7 +1265,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
@@ -1053,7 +1279,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
         break;
       }
     } else { //FDD
+#ifndef FLEXRAN_AGENT_SB_IF                                                                                    
       schedule_ulsch(module_idP,frameP,cooperation_flag,9,3);
+#else
+
+if (mac_agent_registered[module_idP]){
+       agent_mac_xface[module_idP]->flexran_agent_schedule_ul_spec(module_idP,frameP,cooperation_flag,9,3, &msg);   
+      }
+
+
+      flexran_agent_mac_destroy_ul_config(msg);
+
+#endif   
+
 #ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
@@ -1066,7 +1304,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 								      mbsfn_status,
 								      &msg);
 	  
-	  flexran_apply_dl_scheduling_decisions(module_idP,
+	  flexran_apply_scheduling_decisions(module_idP,
 						frameP,
 						subframeP,
 						mbsfn_status,
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
index 6d0044b346a2484aeccedb1a4932572eb8e1b7cd..585d9c2c1c7c7ac9443b60fb895553233d2d062d 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
@@ -885,7 +885,7 @@ abort();
               rb_table_index=UE_template->pre_allocated_rb_table_index_ul;
             } else {
 	      mcs=10;//cmin (10, openair_daq_vars.target_ue_ul_mcs);
-              rb_table_index=5; // for PHR
+              rb_table_index=13; // for PHR
 	    }
 
             UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=mcs;
diff --git a/openair2/LAYER2/MAC/flexran_agent_mac_proto.h b/openair2/LAYER2/MAC/flexran_agent_mac_proto.h
index a3ff3b6a4aa9ee88b176b795d3246312e0ddfcc0..5fc53fece6a7e2d215237309505097ffd8791e4e 100644
--- a/openair2/LAYER2/MAC/flexran_agent_mac_proto.h
+++ b/openair2/LAYER2/MAC/flexran_agent_mac_proto.h
@@ -39,19 +39,25 @@
 /*
  * slice specific scheduler 
  */
-typedef void (*slice_scheduler)(module_id_t mod_id, 
+typedef void (*slice_scheduler_dl)(module_id_t mod_id, 
 				int slice_id, 
 				uint32_t frame, 
 				uint32_t subframe,
 				int *mbsfn_flag,
 				Protocol__FlexranMessage **dl_info);
 
+typedef void (*slice_scheduler_ul)(module_id_t mod_id, 
+				frame_t frame, 
+				unsigned char cooperation_flag,
+				uint32_t      subframe,
+				unsigned char sched_subframe,
+				Protocol__FlexranMessage **ul_info);
 
 
 /*
  * top level flexran scheduler used by the eNB scheduler
  */
-void flexran_schedule_ue_spec_default(mid_t mod_id, 
+void flexran_schedule_ue_dl_spec_default(mid_t mod_id, 
 				      uint32_t frame, 
 				      uint32_t subframe,
 				      int *mbsfn_flag, 
@@ -102,13 +108,22 @@ flexran_schedule_ue_spec_be(mid_t   mod_id,
  * common flexran scheduler function
  */
 void
-flexran_schedule_ue_spec_common(mid_t   mod_id,
+flexran_schedule_ue_dl_spec_common(mid_t   mod_id,
 				int       slice_id, 
 				uint32_t      frame,
 				uint32_t      subframe,
 				int           *mbsfn_flag,
 				Protocol__FlexranMessage **dl_info);
 
+void
+flexran_schedule_ue_ul_spec_default(mid_t   mod_id,
+				 uint32_t      frame,
+				 uint32_t      cooperation_flag,
+				 int           subframe,
+				 unsigned char sched_subframe,
+				 Protocol__FlexranMessage **ul_info);
+
+
 uint16_t flexran_nb_rbs_allowed_slice(float rb_percentage, 
 				      int total_rbs);
 
@@ -117,6 +132,8 @@ int flexran_slice_member(int UE_id,
 
 int flexran_slice_maxmcs(int slice_id) ;
 
+/* Downlink Primitivies */
+
 void _store_dlsch_buffer (module_id_t Mod_id,
 			  int         slice_id,
 			  frame_t     frameP,
@@ -131,6 +148,21 @@ void _assign_rbs_required (module_id_t Mod_id,
 			   uint16_t    nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES], 
 			   int         min_rb_unit[MAX_NUM_CCs]);
 
+
+/* Uplink Primitivies */
+
+// void _sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP);
+
+void _assign_max_mcs_min_rb(module_id_t module_idP, int slice_id, int frameP, sub_frame_t subframeP, uint16_t *first_rb);
+
+
+void _ulsch_scheduler_pre_processor(module_id_t module_idP,
+                                   int slice_id,                                   
+                                   int frameP,
+                                   sub_frame_t subframeP,
+                                   uint16_t *first_rb);
+
+
 void _dlsch_scheduler_pre_processor (module_id_t   Mod_id,
 				     int           slice_id,
 				     frame_t       frameP,
@@ -165,13 +197,21 @@ void _dlsch_scheduler_pre_processor_allocate (module_id_t   Mod_id,
 /*
  * Default scheduler used by the eNB agent
  */
-void flexran_schedule_ue_spec_default(mid_t mod_id, uint32_t frame, uint32_t subframe,
+void flexran_schedule_ue_dl_spec_default(mid_t mod_id, uint32_t frame, uint32_t subframe,
 				      int *mbsfn_flag, Protocol__FlexranMessage **dl_info);
 
+/*
+  Uplink scheduler used by MAC agent
+*/
+
+void flexran_agent_schedule_ulsch_ue_spec(module_id_t module_idP,  frame_t frameP,  unsigned char cooperation_flag,
+		    sub_frame_t subframeP, 
+		    unsigned char sched_subframe, Protocol__FlexranMessage **ul_info);
+
 /*
  * Data plane function for applying the DL decisions of the scheduler
  */
-void flexran_apply_dl_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag,
+void flexran_apply_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag,
 					   Protocol__FlexranMessage *dl_scheduling_info);
 
 /*
diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c
index 38f39e50e10e613a2f979ae8e32a6eaf0cf1901a..ba5aadcb5b03ca1fc2a7be8651758c5597bffc2d 100644
--- a/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c
+++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c
@@ -59,28 +59,28 @@
 
 #include "SIMULATION/TOOLS/defs.h" // for taus
 
-void flexran_apply_dl_scheduling_decisions(mid_t mod_id,
+void flexran_apply_scheduling_decisions(mid_t mod_id,
 					   uint32_t frame,
 					   uint32_t subframe,
 					   int *mbsfn_flag,
 					   Protocol__FlexranMessage *dl_scheduling_info) {
 
-  Protocol__FlexDlMacConfig *mac_config = dl_scheduling_info->dl_mac_config_msg;
+  Protocol__FlexDlMacConfig *mac_dl_config = dl_scheduling_info->dl_mac_config_msg;
 
   // Check if there is anything to schedule for random access
-  if (mac_config->n_dl_rar > 0) {
+  if (mac_dl_config->n_dl_rar > 0) {
     /*TODO: call the random access data plane function*/
   }
 
   // Check if there is anything to schedule for paging/broadcast
-  if (mac_config->n_dl_broadcast > 0) {
+  if (mac_dl_config->n_dl_broadcast > 0) {
     /*TODO: call the broadcast/paging data plane function*/
   }
 
   // Check if there is anything to schedule for the UEs
-  if (mac_config->n_dl_ue_data > 0) {
+  if (mac_dl_config->n_dl_ue_data > 0) {
     flexran_apply_ue_spec_scheduling_decisions(mod_id, frame, subframe, mbsfn_flag,
-					       mac_config->n_dl_ue_data, mac_config->dl_ue_data);
+					       mac_dl_config->n_dl_ue_data, mac_dl_config->dl_ue_data);
   }
   
 }
diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c
index 0bde8c965b40e69bccf7d90ad31f6f073f4555cd..e47adc4fdbd3232783d6e71067fd0693a5b68bc8 100644
--- a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c
+++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c
@@ -88,16 +88,16 @@ typedef enum {
 
 
 // number of active slices for  past and current time
-int n_active_slices = 1;
-int n_active_slices_current = 1;
+int n_active_slices = 2;
+int n_active_slices_current = 2;
 
 // ue to slice mapping
 int slicing_strategy = UEID_TO_SLICEID;
 int slicing_strategy_current = UEID_TO_SLICEID;
 
 // RB share for each slice for past and current time
-float slice_percentage[MAX_NUM_SLICES] = {1.0, 0.0, 0.0, 0.0};
-float slice_percentage_current[MAX_NUM_SLICES] = {1.0, 0.0, 0.0, 0.0};
+float slice_percentage[MAX_NUM_SLICES] = {0.5, 0.5, 0.0, 0.0};
+float slice_percentage_current[MAX_NUM_SLICES] = {0.5, 0.5, 0.0, 0.0};
 float total_slice_percentage = 0;
 
 // MAX MCS for each slice for past and current time
@@ -115,7 +115,7 @@ char *dl_scheduler_type[MAX_NUM_SLICES] = {"flexran_schedule_ue_spec_embb",
 };
 
 // pointer to the slice specific scheduler 
-slice_scheduler slice_sched[MAX_NUM_SLICES] = {0};
+slice_scheduler_dl slice_sched_dl[MAX_NUM_SLICES] = {0};
 
 
 /**
@@ -495,7 +495,7 @@ void _dlsch_scheduler_pre_processor (module_id_t   Mod_id,
     }
   }
   
-  // Store the DLSCH buffer for each logical channel
+  /* Store the DLSCH buffer for each logical channel for each UE */
   _store_dlsch_buffer (Mod_id,slice_id,frameP,subframeP);
 
   // Calculate the number of RBs required by each UE on the basis of logical channel's buffer
@@ -526,7 +526,7 @@ void _dlsch_scheduler_pre_processor (module_id_t   Mod_id,
       CC_id = UE_list->ordered_CCids[ii][UE_id];
       ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
       ue_sched_ctl->max_allowed_rbs[CC_id]=nb_rbs_allowed_slice[CC_id][slice_id];
-      flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round);
+      flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round, openair_harq_DL);
 
       // if there is no available harq_process, skip the UE
       if (UE_list->UE_sched_ctrl[UE_id].harq_pid[CC_id]<0)
@@ -640,7 +640,7 @@ void _dlsch_scheduler_pre_processor (module_id_t   Mod_id,
 	for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
           CC_id = UE_list->ordered_CCids[ii][UE_id];
 	  ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
-	  flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round);	  
+	  flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round, openair_harq_DL);	  
           rnti = UE_RNTI(Mod_id,UE_id);
 
           // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti );
@@ -709,12 +709,12 @@ void _dlsch_scheduler_pre_processor (module_id_t   Mod_id,
 #define SF05_LIMIT 1
 
 /*
- * Main scheduling functions to support slicing
+ * Main Downlink Slicing
  *
  */
 
 void
-flexran_schedule_ue_spec_default(mid_t   mod_id,
+flexran_schedule_ue_dl_spec_default(mid_t   mod_id,
 				 uint32_t      frame,
 				 uint32_t      subframe,
 				 int           *mbsfn_flag,
@@ -729,7 +729,7 @@ flexran_schedule_ue_spec_default(mid_t   mod_id,
     
     // Load any updated functions
     if (update_dl_scheduler[i] > 0 ) {
-      slice_sched[i] = dlsym(NULL, dl_scheduler_type[i]); 
+      slice_sched_dl[i] = dlsym(NULL, dl_scheduler_type[i]); 
       update_dl_scheduler[i] = 0;
       update_dl_scheduler_current[i] = 0;
       slice_percentage_current[i]= slice_percentage[i];
@@ -742,7 +742,9 @@ flexran_schedule_ue_spec_default(mid_t   mod_id,
       if ((n_active_slices > 0) && (n_active_slices <= MAX_NUM_SLICES)) {
 	LOG_N(MAC,"[eNB %d]frame %d subframe %d: number of active slices has changed: %d-->%d\n",
 	      mod_id, frame, subframe, n_active_slices_current, n_active_slices);
+
 	n_active_slices_current = n_active_slices;
+
       } else {
 	LOG_W(MAC,"invalid number of slices %d, revert to the previous value %d\n",n_active_slices, n_active_slices_current);
 	n_active_slices = n_active_slices_current;
@@ -751,26 +753,30 @@ flexran_schedule_ue_spec_default(mid_t   mod_id,
     
     // check if the slice rb share has changed, and log the console
     if (slice_percentage_current[i] != slice_percentage[i]){
-      if ((slice_percentage[i] >= 0.0) && (slice_percentage[i] <= 1.0)){
-	if ((total_slice_percentage - slice_percentage_current[i]  + slice_percentage[i]) <= 1.0) {
-	  total_slice_percentage=total_slice_percentage - slice_percentage_current[i]  + slice_percentage[i];
+ //      if ((slice_percentage[i] >= 0.0) && (slice_percentage[i] <= 1.0)){
+	// if ((total_slice_percentage - slice_percentage_current[i]  + slice_percentage[i]) <= 1.0) {
+	//   total_slice_percentage=total_slice_percentage - slice_percentage_current[i]  + slice_percentage[i];
 	  LOG_N(MAC,"[eNB %d][SLICE %d] frame %d subframe %d: total percentage %f, slice RB percentage has changed: %f-->%f\n",
 		mod_id, i, frame, subframe, total_slice_percentage, slice_percentage_current[i], slice_percentage[i]);
+
 	  slice_percentage_current[i] = slice_percentage[i];
-	} else {
-	  LOG_W(MAC,"[eNB %d][SLICE %d] invalid total RB share (%f->%f), revert the previous value (%f->%f)\n",
-		mod_id,i,  
-		total_slice_percentage,
-		total_slice_percentage - slice_percentage_current[i]  + slice_percentage[i],
-		slice_percentage[i],slice_percentage_current[i]);
-	  slice_percentage[i]= slice_percentage_current[i];
 
-	}
-      } else {
-	LOG_W(MAC,"[eNB %d][SLICE %d] invalid slice RB share, revert the previous value (%f->%f)\n",mod_id, i,  slice_percentage[i],slice_percentage_current[i]);
-	slice_percentage[i]= slice_percentage_current[i];
+	// } else {
+	//   LOG_W(MAC,"[eNB %d][SLICE %d] invalid total RB share (%f->%f), revert the previous value (%f->%f)\n",
+	// 	mod_id,i,  
+	// 	total_slice_percentage,
+	// 	total_slice_percentage - slice_percentage_current[i]  + slice_percentage[i],
+	// 	slice_percentage[i],slice_percentage_current[i]);
 
-      }
+	//   slice_percentage[i]= slice_percentage_current[i];
+
+	// }
+ //      } else {
+	// LOG_W(MAC,"[eNB %d][SLICE %d] invalid slice RB share, revert the previous value (%f->%f)\n",mod_id, i,  slice_percentage[i],slice_percentage_current[i]);
+
+	// slice_percentage[i]= slice_percentage_current[i];
+
+      // }
     }
   
     // check if the slice max MCS, and log the console
@@ -778,10 +784,14 @@ flexran_schedule_ue_spec_default(mid_t   mod_id,
       if ((slice_maxmcs[i] >= 0) && (slice_maxmcs[i] < 29)){
 	LOG_N(MAC,"[eNB %d][SLICE %d] frame %d subframe %d: slice MAX MCS has changed: %d-->%d\n",
 	      mod_id, i, frame, subframe, slice_maxmcs_current[i], slice_maxmcs[i]);
+
 	slice_maxmcs_current[i] = slice_maxmcs[i];
+
       } else {
 	LOG_W(MAC,"[eNB %d][SLICE %d] invalid slice max mcs %d, revert the previous value %d\n",mod_id, i,  slice_percentage[i],slice_percentage[i]);
+
 	slice_maxmcs[i]= slice_maxmcs_current[i];
+
       }
     }
     
@@ -789,12 +799,14 @@ flexran_schedule_ue_spec_default(mid_t   mod_id,
     if (update_dl_scheduler_current[i] != update_dl_scheduler[i]){
       LOG_N(MAC,"[eNB %d][SLICE %d] frame %d subframe %d: DL scheduler for this slice is updated: %s \n",
 	    mod_id, i, frame, subframe, dl_scheduler_type[i]);
+
       update_dl_scheduler_current[i] = update_dl_scheduler[i];
+      
     }
 
     // Run each enabled slice-specific schedulers one by one
     //LOG_N(MAC,"[eNB %d]frame %d subframe %d slice %d: calling the scheduler\n", mod_id, frame, subframe,i);
-    slice_sched[i](mod_id, i, frame, subframe, mbsfn_flag,dl_info);
+    slice_sched_dl[i](mod_id, i, frame, subframe, mbsfn_flag,dl_info);
 
   }
   
@@ -864,7 +876,7 @@ flexran_schedule_ue_spec_embb(mid_t         mod_id,
 			      Protocol__FlexranMessage **dl_info)
 
 {
-  flexran_schedule_ue_spec_common(mod_id,
+  flexran_schedule_ue_dl_spec_common(mod_id,
 				  slice_id,
 				  frame,
 				  subframe,
@@ -882,7 +894,7 @@ flexran_schedule_ue_spec_urllc(mid_t         mod_id,
 			       Protocol__FlexranMessage **dl_info)
 
 {
-  flexran_schedule_ue_spec_common(mod_id,
+  flexran_schedule_ue_dl_spec_common(mod_id,
 				  slice_id,
 				  frame,
 				  subframe,
@@ -901,7 +913,7 @@ flexran_schedule_ue_spec_mmtc(mid_t         mod_id,
   
 {
   
-  flexran_schedule_ue_spec_common(mod_id,
+  flexran_schedule_ue_dl_spec_common(mod_id,
 				  slice_id,
 				  frame,
 				  subframe,
@@ -920,7 +932,7 @@ flexran_schedule_ue_spec_be(mid_t         mod_id,
   
 {
   
-  flexran_schedule_ue_spec_common(mod_id,
+  flexran_schedule_ue_dl_spec_common(mod_id,
 				  slice_id,
 				  frame,
 				  subframe,
@@ -931,7 +943,7 @@ flexran_schedule_ue_spec_be(mid_t         mod_id,
 
 //------------------------------------------------------------------------------
 void
-flexran_schedule_ue_spec_common(mid_t   mod_id,
+flexran_schedule_ue_dl_spec_common(mid_t   mod_id,
 				int           slice_id, 
 				uint32_t      frame,
 				uint32_t      subframe,
@@ -1032,9 +1044,10 @@ flexran_schedule_ue_spec_common(mid_t   mod_id,
       ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
       
       if (eNB_UE_stats==NULL) {
-	LOG_D(MAC,"[eNB] Cannot find eNB_UE_stats\n");
-        //  mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n");
-	continue;
+
+        	LOG_D(MAC,"[eNB] Cannot find eNB_UE_stats\n");
+                //  mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n");
+        	continue;
       }
       
       if (flexran_slice_member(UE_id, slice_id) == 0)
@@ -1050,28 +1063,29 @@ flexran_schedule_ue_spec_common(mid_t   mod_id,
       case 1:
       case 2:
       case 7:
-	aggregation = get_aggregation(get_bw_index(mod_id,CC_id), 
+        	aggregation = get_aggregation(get_bw_index(mod_id,CC_id), 
 				      eNB_UE_stats->DL_cqi[0],
 				      format1);
-	break;
+      	break;
       case 3:
-	aggregation = get_aggregation(get_bw_index(mod_id,CC_id), 
+        	aggregation = get_aggregation(get_bw_index(mod_id,CC_id), 
 				      eNB_UE_stats->DL_cqi[0],
 				      format2A);
-	break;
+      	break;
       default:
-	LOG_W(MAC,"Unsupported transmission mode %d\n", mac_xface->get_transmission_mode(mod_id,CC_id,rnti));
-	aggregation = 2;
+        	LOG_W(MAC,"Unsupported transmission mode %d\n", mac_xface->get_transmission_mode(mod_id,CC_id,rnti));
+        	aggregation = 2;
       }
      
       if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) ||  // no RBs allocated 
 	  CCE_allocation_infeasible(mod_id, CC_id, 0, subframe, aggregation, rnti)) {
-        LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n",
-              mod_id, frame, UE_id, CC_id);
-        //if(mac_xface->get_transmission_mode(module_idP,rnti)==5)
-        continue; //to next user (there might be rbs availiable for other UEs in TM5
-        // else
-        //  break;
+
+            LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n",
+                  mod_id, frame, UE_id, CC_id);
+            //if(mac_xface->get_transmission_mode(module_idP,rnti)==5)
+            continue; //to next user (there might be rbs availiable for other UEs in TM5
+            // else
+            //  break;
       }
 
       if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD)  {
@@ -1094,26 +1108,28 @@ flexran_schedule_ue_spec_common(mid_t   mod_id,
       dl_data[num_ues_added]->n_rlc_pdu = 0;
       dl_data[num_ues_added]->has_serv_cell_index = 1;
       dl_data[num_ues_added]->serv_cell_index = CC_id;
-      
-      nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
-      flexran_get_harq(mod_id, CC_id, UE_id, frame, subframe, &harq_pid, &round);
+            
+      flexran_get_harq(mod_id, CC_id, UE_id, frame, subframe, &harq_pid, &round, openair_harq_DL);
       sdu_length_total=0;
       mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)];
       //      LOG_I(FLEXRAN_AGENT, "The MCS is %d\n", mcs);
       mcs = cmin(mcs,flexran_slice_maxmcs(slice_id));
-#ifdef EXMIMO
+// #ifdef EXMIMO
 
-       if (mac_xface->get_transmission_mode(mod_id, CC_id, rnti) == 5) {
-	  mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)];
-	  mcs =  cmin(mcs,16);
-       }
+//        if (mac_xface->get_transmission_mode(mod_id, CC_id, rnti) == 5) {
+// 	  mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)];
+// 	  mcs =  cmin(mcs,16);
+//        }
 
-#endif
+// #endif
 
+      /*Get pre available resource blocks based on buffers*/ 
+      nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
       // initializing the rb allocation indicator for each UE
        for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) {
-        UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
-	rballoc_sub[j] = 0;
+
+          UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
+        	rballoc_sub[j] = 0;
       }
 
       /* LOG_D(MAC,"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", */
@@ -1134,72 +1150,74 @@ flexran_schedule_ue_spec_common(mid_t   mod_id,
       /* process retransmission  */
       if (round > 0) {
 
-	LOG_D(FLEXRAN_AGENT, "There was a retransmission just now and the round was %d\n", round);
-
-	if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
-	  UE_list->UE_template[CC_id][UE_id].DAI++;
-	  update_ul_dci(mod_id, CC_id, rnti, UE_list->UE_template[CC_id][UE_id].DAI);
-	  LOG_D(MAC,"DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n",
-		CC_id, subframe,UE_id,UE_list->UE_template[CC_id][UE_id].DAI);
-	}
-
-	mcs = UE_list->UE_template[CC_id][UE_id].mcs[harq_pid];
-
-	  // get freq_allocation
-	nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
-	  
-	/*TODO: Must add this to FlexRAN agent API */
-	dci_tbs = mac_xface->get_TBS_DL(mcs, nb_rb);
-
-	if (nb_rb <= nb_available_rb) {
-	  
-	  if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
-	    for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { // for indicating the rballoc for each sub-band
-	      UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
-            }
-	  } else {
-	    nb_rb_temp = nb_rb;
-	    j = 0;
-
-	    while((nb_rb_temp > 0) && (j < flexran_get_N_RBG(mod_id, CC_id))) {
-	      if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
-		UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
-		
-		if((j == flexran_get_N_RBG(mod_id, CC_id) - 1) &&
-		   ((flexran_get_N_RB_DL(mod_id, CC_id) == 25)||
-		    (flexran_get_N_RB_DL(mod_id, CC_id) == 50))) {
-		  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
-		} else {
-		  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
-		}
-	      }
-	      j = j + 1;
-	    }
-	  }
-
-	  nb_available_rb -= nb_rb;
-	  PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
-	  PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];
-	  
-	  for(j=0; j < flexran_get_N_RBG(mod_id, CC_id); j++) {
-	    PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
-	    rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
-	  }
-
-	  // Keep the old NDI, do not toggle
-	  ndi = UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
-	  tpc = UE_list->UE_template[CC_id][UE_id].oldTPC[harq_pid];
-	  UE_list->UE_template[CC_id][UE_id].mcs[harq_pid] = mcs;
+      	LOG_D(FLEXRAN_AGENT, "There was a retransmission just now and the round was %d\n", round);
+
+      	if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+      	  UE_list->UE_template[CC_id][UE_id].DAI++;
+      	  update_ul_dci(mod_id, CC_id, rnti, UE_list->UE_template[CC_id][UE_id].DAI);
+      	  LOG_D(MAC,"DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n",
+      		CC_id, subframe,UE_id,UE_list->UE_template[CC_id][UE_id].DAI);
+      	}
+
+      	mcs = UE_list->UE_template[CC_id][UE_id].mcs[harq_pid];
+
+      	  // get freq_allocation
+      	nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
+      	  
+      	/*TODO: Must add this to FlexRAN agent API */
+      	dci_tbs = mac_xface->get_TBS_DL(mcs, nb_rb);
+
+      	if (nb_rb <= nb_available_rb) {
+      	  
+      	  if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
+      	    for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { // for indicating the rballoc for each sub-band
+      	      UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
+                  }
+      	  } else {
+      	    nb_rb_temp = nb_rb;
+      	    j = 0;
+
+      	    while((nb_rb_temp > 0) && (j < flexran_get_N_RBG(mod_id, CC_id))) {
+      	      if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
+      		UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
+      		
+      		if((j == flexran_get_N_RBG(mod_id, CC_id) - 1) &&
+      		   ((flexran_get_N_RB_DL(mod_id, CC_id) == 25)||
+      		    (flexran_get_N_RB_DL(mod_id, CC_id) == 50))) {
+      		  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
+      		} else {
+      		  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
+      		}
+      	      }
+      	      j = j + 1;
+      	    }
+      	  }
+
+      	  nb_available_rb -= nb_rb;
+      	  PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
+      	  PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];
+      	  
+      	  for(j=0; j < flexran_get_N_RBG(mod_id, CC_id); j++) {
+      	    PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
+      	    rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
+      	  }
+
+      	  // Keep the old NDI, do not toggle
+      	  ndi = UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
+      	  tpc = UE_list->UE_template[CC_id][UE_id].oldTPC[harq_pid];
+      	  UE_list->UE_template[CC_id][UE_id].mcs[harq_pid] = mcs;
+
+      	  ue_has_transmission = 1;
+      	  num_ues_added++;
+      	} else {
+      	  LOG_D(MAC,"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n",
+                      mod_id, frame, CC_id, UE_id);
+      	  ue_has_transmission = 0;
+      	}
+      	//End of retransmission
+      }
 
-	  ue_has_transmission = 1;
-	  num_ues_added++;
-	} else {
-	  LOG_D(MAC,"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n",
-                mod_id, frame, CC_id, UE_id);
-	  ue_has_transmission = 0;
-	}
-	//End of retransmission
-      } else { /* This is a potentially new SDU opportunity */
+       else { /* This is a potentially new SDU opportunity */
 	rlc_status.bytes_in_buffer = 0;
         // Now check RLC information to compute number of required RBs
         // get maximum TBS size for RLC request
@@ -1253,11 +1271,14 @@ flexran_schedule_ue_spec_common(mid_t   mod_id,
 	       //Fill in as much as possible
 	       data_to_request = cmin(dci_tbs - ta_len - header_len - sdu_length_total, rlc_status.bytes_in_buffer);
 	       LOG_D(FLEXRAN_AGENT, "Will request %d bytes from channel %d\n", data_to_request, j);
+
 	       if (data_to_request < 128) { //The header will be one byte less
-		 header_len--;
-		 header_len_last = 2;
-	       } else {
-		 header_len_last = 3;
+        		 header_len--;
+        		 header_len_last = 2;
+	       }
+          else {
+
+        		 header_len_last = 3;
 	       }
 	       /* if (j == 1 || j == 2) {
 		  data_to_request+=0; 
@@ -1352,7 +1373,8 @@ flexran_schedule_ue_spec_common(mid_t   mod_id,
             for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { // for indicating the rballoc for each sub-band
               UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
             }
-          } else {
+          }
+           else {
 	    nb_rb_temp = nb_rb;
             j = 0;
 	    LOG_D(MAC, "[TEST]Will only partially fill the bitmap\n");
@@ -1400,12 +1422,12 @@ flexran_schedule_ue_spec_common(mid_t   mod_id,
 	  
           UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb;
 
-	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
-            UE_list->UE_template[CC_id][UE_id].DAI++;
-            //  printf("DAI update: subframeP %d: UE %d, DAI %d\n",subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].DAI);
+	  // if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+   //          UE_list->UE_template[CC_id][UE_id].DAI++;
+   //          //  printf("DAI update: subframeP %d: UE %d, DAI %d\n",subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].DAI);
 	    //#warning only for 5MHz channel
-            update_ul_dci(mod_id, CC_id, rnti, UE_list->UE_template[CC_id][UE_id].DAI);
-          }
+          //   update_ul_dci(mod_id, CC_id, rnti, UE_list->UE_template[CC_id][UE_id].DAI);
+          // }
 
 	  // do PUCCH power control
           // this is the normalized RX power
@@ -1463,189 +1485,189 @@ flexran_schedule_ue_spec_common(mid_t   mod_id,
 	  ue_has_transmission = 0;
 	}
       } // End of new scheduling
-      
+        
       // If we has transmission or retransmission
       if (ue_has_transmission) {
-	switch (mac_xface->get_transmission_mode(mod_id, CC_id, rnti)) {
-	case 1:
-	case 2:
-	default:
-	  dl_dci->has_res_alloc = 1;
-	  dl_dci->res_alloc = 0;
-	  dl_dci->has_vrb_format = 1;
-	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
-	  dl_dci->has_format = 1;
-	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1;
-	  dl_dci->has_rb_bitmap = 1;
-	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
-	  dl_dci->has_rb_shift = 1;
-	  dl_dci->rb_shift = 0;
-	  dl_dci->n_ndi = 1;
-	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
-	  dl_dci->ndi[0] = ndi;
-	  dl_dci->n_rv = 1;
-	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
-	  dl_dci->rv[0] = round & 3;
-	  dl_dci->has_tpc = 1;
-	  dl_dci->tpc = tpc;
-	  dl_dci->n_mcs = 1;
-	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
-	  dl_dci->mcs[0] = mcs;
-	  dl_dci->n_tbs_size = 1;
-	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
-	  dl_dci->tbs_size[0] = dci_tbs;
-	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
-	    dl_dci->has_dai = 1;
-	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
-	  }
-	  break;
-	case 3:
-	  dl_dci->has_res_alloc = 1;
-	  dl_dci->res_alloc = 0;
-	  dl_dci->has_vrb_format = 1;
-	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
-	  dl_dci->has_format = 1;
-	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A;
-	  dl_dci->has_rb_bitmap = 1;
-	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
-	  dl_dci->has_rb_shift = 1;
-	  dl_dci->rb_shift = 0;
-	  dl_dci->n_ndi = 2;
-	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
-	  dl_dci->ndi[0] = ndi;
-	  dl_dci->ndi[1] = ndi;
-	  dl_dci->n_rv = 2;
-	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
-	  dl_dci->rv[0] = round & 3;
-	  dl_dci->rv[1] = round & 3;
-	  dl_dci->has_tpc = 1;
-	  dl_dci->tpc = tpc;
-	  dl_dci->n_mcs = 2;
-	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
-	  dl_dci->mcs[0] = mcs;
-	  dl_dci->mcs[1] = mcs;
-	  dl_dci->n_tbs_size = 2;
-	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
-	  dl_dci->tbs_size[0] = dci_tbs;
-	  dl_dci->tbs_size[1] = dci_tbs;
-	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
-	    dl_dci->has_dai = 1;
-	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
-	  }
-	  break;
-	case 4:
-	  dl_dci->has_res_alloc = 1;
-	  dl_dci->res_alloc = 0;
-	  dl_dci->has_vrb_format = 1;
-	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
-	  dl_dci->has_format = 1;
-	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A;
-	  dl_dci->has_rb_bitmap = 1;
-	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
-	  dl_dci->has_rb_shift = 1;
-	  dl_dci->rb_shift = 0;
-	  dl_dci->n_ndi = 2;
-	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
-	  dl_dci->ndi[0] = ndi;
-	  dl_dci->ndi[1] = ndi;
-	  dl_dci->n_rv = 2;
-	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
-	  dl_dci->rv[0] = round & 3;
-	  dl_dci->rv[1] = round & 3;
-	  dl_dci->has_tpc = 1;
-	  dl_dci->tpc = tpc;
-	  dl_dci->n_mcs = 2;
-	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
-	  dl_dci->mcs[0] = mcs;
-	  dl_dci->mcs[1] = mcs;
-	  dl_dci->n_tbs_size = 2;
-	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
-	  dl_dci->tbs_size[0] = dci_tbs;
-	  dl_dci->tbs_size[1] = dci_tbs;
-	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
-	    dl_dci->has_dai = 1;
-	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
-	  }
-	  break;
-	case 5:
-	  dl_dci->has_res_alloc = 1;
-	  dl_dci->res_alloc = 0;
-	  dl_dci->has_vrb_format = 1;
-	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
-	  dl_dci->has_format = 1;
-	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D;
-	  dl_dci->has_rb_bitmap = 1;
-	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
-	  dl_dci->has_rb_shift = 1;
-	  dl_dci->rb_shift = 0;
-	  dl_dci->n_ndi = 1;
-	  dl_dci->ndi[0] = ndi;
-	  dl_dci->n_rv = 1;
-	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
-	  dl_dci->rv[0] = round & 3;
-	  dl_dci->has_tpc = 1;
-	  dl_dci->tpc = tpc;
-	  dl_dci->n_mcs = 1;
-	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
-	  dl_dci->mcs[0] = mcs;
-	  dl_dci->n_tbs_size = 1;
-	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
-	  dl_dci->tbs_size[0] = dci_tbs;
-	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
-	    dl_dci->has_dai = 1;
-	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
-	  }
-	  
-	  if(ue_sched_ctl->dl_pow_off[CC_id] == 2) {
-	    ue_sched_ctl->dl_pow_off[CC_id] = 1;
-	  }
-	  
-	  dl_dci->has_dl_power_offset = 1;
-	  dl_dci->dl_power_offset = ue_sched_ctl->dl_pow_off[CC_id];
-	  dl_dci->has_precoding_info = 1;
-	  dl_dci->precoding_info = 5; // Is this right??
-	  
-	  break;
-	case 6:
-	  dl_dci->has_res_alloc = 1;
-	  dl_dci->res_alloc = 0;
-	  dl_dci->has_vrb_format = 1;
-	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
-	  dl_dci->has_format = 1;
-	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D;
-	  dl_dci->has_rb_bitmap = 1;
-	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
-	  dl_dci->has_rb_shift = 1;
-	  dl_dci->rb_shift = 0;
-	  dl_dci->n_ndi = 1;
-	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
-	  dl_dci->ndi[0] = ndi;
-	  dl_dci->n_rv = 1;
-	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
-	  dl_dci->rv[0] = round & 3;
-	  dl_dci->has_tpc = 1;
-	  dl_dci->tpc = tpc;
-	  dl_dci->n_mcs = 1;
-	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
-	  dl_dci->mcs[0] = mcs;
-	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
-	    dl_dci->has_dai = 1;
-	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
-	  }
-
-	  dl_dci->has_dl_power_offset = 1;
-	  dl_dci->dl_power_offset = ue_sched_ctl->dl_pow_off[CC_id];
-	  dl_dci->has_precoding_info = 1;
-	  dl_dci->precoding_info = 5; // Is this right??
-	  break;
-	}
+        	switch (mac_xface->get_transmission_mode(mod_id, CC_id, rnti)) {
+        	case 1:
+        	case 2:
+        	default:
+        	  dl_dci->has_res_alloc = 1;
+        	  dl_dci->res_alloc = 0;
+        	  dl_dci->has_vrb_format = 1;
+        	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+        	  dl_dci->has_format = 1;
+        	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1;
+        	  dl_dci->has_rb_bitmap = 1;
+        	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+        	  dl_dci->has_rb_shift = 1;
+        	  dl_dci->rb_shift = 0;
+        	  dl_dci->n_ndi = 1;
+        	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+        	  dl_dci->ndi[0] = ndi;
+        	  dl_dci->n_rv = 1;
+        	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+        	  dl_dci->rv[0] = round & 3;
+        	  dl_dci->has_tpc = 1;
+        	  dl_dci->tpc = tpc;
+        	  dl_dci->n_mcs = 1;
+        	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+        	  dl_dci->mcs[0] = mcs;
+        	  dl_dci->n_tbs_size = 1;
+        	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+        	  dl_dci->tbs_size[0] = dci_tbs;
+        	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+        	    dl_dci->has_dai = 1;
+        	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+        	  }
+        	  break;
+        	case 3:
+        	  dl_dci->has_res_alloc = 1;
+        	  dl_dci->res_alloc = 0;
+        	  dl_dci->has_vrb_format = 1;
+        	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+        	  dl_dci->has_format = 1;
+        	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A;
+        	  dl_dci->has_rb_bitmap = 1;
+        	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+        	  dl_dci->has_rb_shift = 1;
+        	  dl_dci->rb_shift = 0;
+        	  dl_dci->n_ndi = 2;
+        	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+        	  dl_dci->ndi[0] = ndi;
+        	  dl_dci->ndi[1] = ndi;
+        	  dl_dci->n_rv = 2;
+        	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+        	  dl_dci->rv[0] = round & 3;
+        	  dl_dci->rv[1] = round & 3;
+        	  dl_dci->has_tpc = 1;
+        	  dl_dci->tpc = tpc;
+        	  dl_dci->n_mcs = 2;
+        	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+        	  dl_dci->mcs[0] = mcs;
+        	  dl_dci->mcs[1] = mcs;
+        	  dl_dci->n_tbs_size = 2;
+        	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+        	  dl_dci->tbs_size[0] = dci_tbs;
+        	  dl_dci->tbs_size[1] = dci_tbs;
+        	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+        	    dl_dci->has_dai = 1;
+        	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+        	  }
+        	  break;
+        	case 4:
+        	  dl_dci->has_res_alloc = 1;
+        	  dl_dci->res_alloc = 0;
+        	  dl_dci->has_vrb_format = 1;
+        	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+        	  dl_dci->has_format = 1;
+        	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A;
+        	  dl_dci->has_rb_bitmap = 1;
+        	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+        	  dl_dci->has_rb_shift = 1;
+        	  dl_dci->rb_shift = 0;
+        	  dl_dci->n_ndi = 2;
+        	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+        	  dl_dci->ndi[0] = ndi;
+        	  dl_dci->ndi[1] = ndi;
+        	  dl_dci->n_rv = 2;
+        	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+        	  dl_dci->rv[0] = round & 3;
+        	  dl_dci->rv[1] = round & 3;
+        	  dl_dci->has_tpc = 1;
+        	  dl_dci->tpc = tpc;
+        	  dl_dci->n_mcs = 2;
+        	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+        	  dl_dci->mcs[0] = mcs;
+        	  dl_dci->mcs[1] = mcs;
+        	  dl_dci->n_tbs_size = 2;
+        	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+        	  dl_dci->tbs_size[0] = dci_tbs;
+        	  dl_dci->tbs_size[1] = dci_tbs;
+        	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+        	    dl_dci->has_dai = 1;
+        	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+        	  }
+        	  break;
+        	case 5:
+        	  dl_dci->has_res_alloc = 1;
+        	  dl_dci->res_alloc = 0;
+        	  dl_dci->has_vrb_format = 1;
+        	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+        	  dl_dci->has_format = 1;
+        	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D;
+        	  dl_dci->has_rb_bitmap = 1;
+        	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+        	  dl_dci->has_rb_shift = 1;
+        	  dl_dci->rb_shift = 0;
+        	  dl_dci->n_ndi = 1;
+        	  dl_dci->ndi[0] = ndi;
+        	  dl_dci->n_rv = 1;
+        	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+        	  dl_dci->rv[0] = round & 3;
+        	  dl_dci->has_tpc = 1;
+        	  dl_dci->tpc = tpc;
+        	  dl_dci->n_mcs = 1;
+        	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+        	  dl_dci->mcs[0] = mcs;
+        	  dl_dci->n_tbs_size = 1;
+        	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+        	  dl_dci->tbs_size[0] = dci_tbs;
+        	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+        	    dl_dci->has_dai = 1;
+        	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+        	  }
+        	  
+        	  if(ue_sched_ctl->dl_pow_off[CC_id] == 2) {
+        	    ue_sched_ctl->dl_pow_off[CC_id] = 1;
+        	  }
+        	  
+        	  dl_dci->has_dl_power_offset = 1;
+        	  dl_dci->dl_power_offset = ue_sched_ctl->dl_pow_off[CC_id];
+        	  dl_dci->has_precoding_info = 1;
+        	  dl_dci->precoding_info = 5; // Is this right??
+        	  
+        	  break;
+        	case 6:
+        	  dl_dci->has_res_alloc = 1;
+        	  dl_dci->res_alloc = 0;
+        	  dl_dci->has_vrb_format = 1;
+        	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+        	  dl_dci->has_format = 1;
+        	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D;
+        	  dl_dci->has_rb_bitmap = 1;
+        	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+        	  dl_dci->has_rb_shift = 1;
+        	  dl_dci->rb_shift = 0;
+        	  dl_dci->n_ndi = 1;
+        	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+        	  dl_dci->ndi[0] = ndi;
+        	  dl_dci->n_rv = 1;
+        	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+        	  dl_dci->rv[0] = round & 3;
+        	  dl_dci->has_tpc = 1;
+        	  dl_dci->tpc = tpc;
+        	  dl_dci->n_mcs = 1;
+        	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+        	  dl_dci->mcs[0] = mcs;
+        	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+        	    dl_dci->has_dai = 1;
+        	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+        	  }
+
+        	  dl_dci->has_dl_power_offset = 1;
+        	  dl_dci->dl_power_offset = ue_sched_ctl->dl_pow_off[CC_id];
+        	  dl_dci->has_precoding_info = 1;
+        	  dl_dci->precoding_info = 5; // Is this right??
+        	  break;
+        	}
       }
       
-      if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+      // if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
         
 	/* TODO */
 	//set_ul_DAI(mod_id, UE_id, CC_id, frame, subframe, frame_parms);
-      }
+      // }
     } // UE_id loop
    } // CC_id loop
 
diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_ulsch_ue.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_ulsch_ue.c
new file mode 100644
index 0000000000000000000000000000000000000000..86bb2407b630afb131c7aca8303a2d12c5e63eec
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_ulsch_ue.c
@@ -0,0 +1,1075 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.0  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file eNB_scheduler_ulsch.c
+ * \brief FlexRAN eNB procedures for the ULSCH transport channel
+ * \author shahab SHARIAT BAGHERI
+ * \date 2017
+ * \version 1.0
+ * @ingroup _mac
+
+ */
+
+#include "assertions.h"
+#include "PHY/defs.h"
+#include "PHY/extern.h"
+
+#include "SCHED/defs.h"
+#include "SCHED/extern.h"
+
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+#include "LAYER2/MAC/defs.h"
+#include "LAYER2/MAC/proto.h"
+#include "LAYER2/MAC/extern.h"
+#include "UTIL/LOG/log.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
+#include "OCG.h"
+#include "OCG_extern.h"
+
+#include "RRC/LITE/extern.h"
+#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
+
+//#include "LAYER2/MAC/pre_processor.c"
+#include "pdcp.h"
+
+#if defined(ENABLE_ITTI)
+# include "intertask_interface.h"
+#endif
+
+#include "T.h"
+
+/* number of active slices for  past and current time*/
+int n_active_slices_uplink = 2;
+int n_active_slices_uplink_current = 2;
+
+/* RB share for each slice for past and current time*/
+float slice_percentage_uplink[MAX_NUM_SLICES] = {0.5, 0.5, 0.0, 0.0};
+float slice_percentage_current_uplink[MAX_NUM_SLICES] = {0.5, 0.5, 0.0, 0.0};
+float total_slice_percentage_uplink = 0;
+
+// MAX MCS for each slice for past and current time
+int slice_maxmcs_uplink[MAX_NUM_SLICES] = {16, 16, 16, 16};
+int slice_maxmcs_current_uplink[MAX_NUM_SLICES] = {28, 28, 28, 28};
+
+/*resource blocks allowed*/
+uint16_t                nb_rbs_allowed_slice_uplink[MAX_NUM_CCs][MAX_NUM_SLICES];      
+/*Slice Update */
+int update_ul_scheduler[MAX_NUM_SLICES] = {1, 1, 1, 1};
+int update_ul_scheduler_current[MAX_NUM_SLICES] = {1, 1, 1, 1};
+
+ /* Slice Function Pointer */
+slice_scheduler_ul slice_sched_ul[MAX_NUM_SLICES] = {0};
+
+/* name of available scheduler*/
+char *ul_scheduler_type[MAX_NUM_SLICES] = {"flexran_schedule_ue_ul_spec_embb",
+					   "flexran_schedule_ue_ul_spec_urllc",
+					   "flexran_schedule_ue_ul_spec_mmtc",
+					   "flexran_schedule_ue_ul_spec_be"      // best effort 
+};
+
+
+uint16_t flexran_nb_rbs_allowed_slice_uplink(float rb_percentage, int total_rbs){
+  return  (uint16_t) floor(rb_percentage * total_rbs); 
+}
+
+
+void _assign_max_mcs_min_rb(module_id_t module_idP, int slice_id, int frameP, sub_frame_t subframeP, uint16_t *first_rb)
+{
+
+  int                i;
+  uint16_t           n,UE_id;
+  uint8_t            CC_id;
+  rnti_t             rnti           = -1;
+  int                mcs;
+  int                rb_table_index=0,tbs,tx_power;
+  eNB_MAC_INST       *eNB = &eNB_mac_inst[module_idP];
+  UE_list_t          *UE_list = &eNB->UE_list;
+
+  UE_TEMPLATE       *UE_template;
+  LTE_DL_FRAME_PARMS   *frame_parms;
+
+   
+  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
+    if (UE_list->active[i] != TRUE) continue;
+
+    rnti = UE_RNTI(module_idP,i);
+
+    if (rnti==NOT_A_RNTI)
+      continue;
+    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
+      continue;
+    if (!phy_stats_exist(module_idP, rnti))
+      continue;
+
+    if (UE_list->UE_sched_ctrl[i].phr_received == 1)
+      mcs = 20; // if we've received the power headroom information the UE, we can go to maximum mcs
+    else
+      mcs = 10; // otherwise, limit to QPSK PUSCH
+
+    UE_id = i;
+
+    for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
+      // This is the actual CC_id in the list
+      CC_id = UE_list->ordered_ULCCids[n][UE_id];
+
+      if (CC_id >= MAX_NUM_CCs) {
+        LOG_E( MAC, "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u",
+               CC_id,
+               MAX_NUM_CCs,
+               n,
+               UE_id,
+               UE_list->numactiveULCCs[UE_id]);
+      }
+
+      AssertFatal( CC_id < MAX_NUM_CCs, "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u",
+                   CC_id,
+                   MAX_NUM_CCs,
+                   n,
+                   UE_id,
+                   UE_list->numactiveULCCs[UE_id]);
+      frame_parms=mac_xface->get_lte_frame_parms(module_idP,CC_id);
+      UE_template = &UE_list->UE_template[CC_id][UE_id];
+      nb_rbs_allowed_slice_uplink[CC_id][UE_id] = flexran_nb_rbs_allowed_slice_uplink(slice_percentage_uplink[UE_id], flexran_get_N_RB_UL(module_idP, CC_id));
+      // if this UE has UL traffic
+      if (UE_template->ul_total_buffer > 0 ) {
+
+        tbs = mac_xface->get_TBS_UL(mcs,3);  // 1 or 2 PRB with cqi enabled does not work well!
+        // fixme: set use_srs flag
+        tx_power= mac_xface->estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,frame_parms->Ncp,0);
+
+        while ((((UE_template->phr_info - tx_power) < 0 ) || (tbs > UE_template->ul_total_buffer))&&
+               (mcs > 3)) {
+          // LOG_I(MAC,"UE_template->phr_info %d tx_power %d mcs %d\n", UE_template->phr_info,tx_power, mcs);
+          mcs--;
+          tbs = mac_xface->get_TBS_UL(mcs,rb_table[rb_table_index]);
+          tx_power = mac_xface->estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,frame_parms->Ncp,0); // fixme: set use_srs
+        }
+
+        while ((tbs < UE_template->ul_total_buffer) &&
+               (rb_table[rb_table_index]<(nb_rbs_allowed_slice_uplink[CC_id][UE_id]-first_rb[CC_id])) &&
+               ((UE_template->phr_info - tx_power) > 0) &&
+               (rb_table_index < 32 )) {
+          //  LOG_I(MAC,"tbs %d ul buffer %d rb table %d max ul rb %d\n", tbs, UE_template->ul_total_buffer, rb_table[rb_table_index], frame_parms->N_RB_UL-first_rb[CC_id]);
+          rb_table_index++;
+          tbs = mac_xface->get_TBS_UL(mcs,rb_table[rb_table_index]);
+          tx_power = mac_xface->estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,frame_parms->Ncp,0);
+        }
+
+        UE_template->ue_tx_power = tx_power;
+
+        if (rb_table[rb_table_index]>(nb_rbs_allowed_slice_uplink[CC_id][UE_id]-first_rb[CC_id]-1)) {
+          rb_table_index--;
+        }
+
+        // 1 or 2 PRB with cqi enabled does not work well!
+  if (rb_table[rb_table_index]<3) {
+          rb_table_index=2; //3PRB
+        }
+
+        UE_template->pre_assigned_mcs_ul=mcs;
+        UE_template->pre_allocated_rb_table_index_ul=rb_table_index;
+        UE_template->pre_allocated_nb_rb_ul= rb_table[rb_table_index];
+        LOG_D(MAC,"[eNB %d] frame %d subframe %d: for UE %d CC %d: pre-assigned mcs %d, pre-allocated rb_table[%d]=%d RBs (phr %d, tx power %d)\n",
+              module_idP, frameP, subframeP, UE_id, CC_id,
+              UE_template->pre_assigned_mcs_ul,
+              UE_template->pre_allocated_rb_table_index_ul,
+              UE_template->pre_allocated_nb_rb_ul,
+              UE_template->phr_info,tx_power);
+      } else {
+        UE_template->pre_allocated_rb_table_index_ul=-1;
+        UE_template->pre_allocated_nb_rb_ul=0;
+      }
+    }
+  }
+}
+
+
+
+
+void _ulsch_scheduler_pre_processor(module_id_t module_idP,
+                                   int slice_id,                                                     
+                                   int frameP,
+                                   sub_frame_t subframeP,
+                                   uint16_t *first_rb)
+{
+
+  int16_t            i;
+  uint16_t           UE_id,n,r;
+  uint8_t            CC_id, round, harq_pid;
+  uint16_t           nb_allocated_rbs[MAX_NUM_CCs][NUMBER_OF_UE_MAX],total_allocated_rbs[MAX_NUM_CCs],average_rbs_per_user[MAX_NUM_CCs];
+  uint16_t          nb_rbs_allowed_slice_uplink[MAX_NUM_CCs][MAX_NUM_SLICES];
+  int16_t            total_remaining_rbs[MAX_NUM_CCs];
+  uint16_t           max_num_ue_to_be_scheduled=0,total_ue_count=0;
+  rnti_t             rnti= -1;
+  UE_list_t          *UE_list = &eNB_mac_inst[module_idP].UE_list;
+  UE_TEMPLATE        *UE_template = 0;
+  LTE_DL_FRAME_PARMS   *frame_parms = 0;
+  UE_sched_ctrl *ue_sched_ctl;
+  
+
+  //LOG_I(MAC,"assign max mcs min rb\n");
+  // maximize MCS and then allocate required RB according to the buffer occupancy with the limit of max available UL RB
+  _assign_max_mcs_min_rb(module_idP, slice_id, frameP, subframeP, first_rb);
+
+  //LOG_I(MAC,"sort ue \n");
+  // sort ues
+  sort_ue_ul (module_idP,frameP, subframeP);
+
+
+  // we need to distribute RBs among UEs
+  // step1:  reset the vars
+  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+    total_allocated_rbs[CC_id]=0;
+    total_remaining_rbs[CC_id]=0;
+    average_rbs_per_user[CC_id]=0;
+
+    for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) {
+      nb_allocated_rbs[CC_id][i]=0;
+    }
+  }
+
+  //LOG_I(MAC,"step2 \n");
+  // step 2: calculate the average rb per UE
+  total_ue_count =0;
+  max_num_ue_to_be_scheduled=0;
+
+  for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) {
+
+    rnti = UE_RNTI(module_idP,i);
+
+    if (rnti==NOT_A_RNTI)
+      continue;
+
+    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
+      continue;
+
+    if (!phy_stats_exist(module_idP, rnti))
+      continue;
+
+    UE_id = i;
+
+    for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
+      // This is the actual CC_id in the list
+      CC_id = UE_list->ordered_ULCCids[n][UE_id];
+      UE_template = &UE_list->UE_template[CC_id][UE_id];
+      average_rbs_per_user[CC_id]=0;
+      frame_parms = mac_xface->get_lte_frame_parms(module_idP,CC_id);
+
+      if (UE_template->pre_allocated_nb_rb_ul > 0) {
+        total_ue_count+=1;
+      }
+      /*
+      if((mac_xface->get_nCCE_max(module_idP,CC_id,3,subframeP) - nCCE_to_be_used[CC_id])  > (1<<aggregation)) {
+        nCCE_to_be_used[CC_id] = nCCE_to_be_used[CC_id] + (1<<aggregation);
+        max_num_ue_to_be_scheduled+=1;
+  }*/
+
+      max_num_ue_to_be_scheduled+=1;
+
+     nb_rbs_allowed_slice_uplink[CC_id][UE_id] = flexran_nb_rbs_allowed_slice_uplink(slice_percentage_uplink[UE_id], flexran_get_N_RB_UL(module_idP, CC_id));
+
+      if (total_ue_count == 0) {
+        average_rbs_per_user[CC_id] = 0;
+      } else if (total_ue_count == 1 ) { // increase the available RBs, special case,
+        average_rbs_per_user[CC_id] = nb_rbs_allowed_slice_uplink[CC_id][i]-first_rb[CC_id]+1;
+      } else if( (total_ue_count <= (nb_rbs_allowed_slice_uplink[CC_id][i]-first_rb[CC_id])) &&
+                 (total_ue_count <= max_num_ue_to_be_scheduled)) {
+        average_rbs_per_user[CC_id] = (uint16_t) floor((nb_rbs_allowed_slice_uplink[CC_id][i]-first_rb[CC_id])/total_ue_count);
+      } else if (max_num_ue_to_be_scheduled > 0 ) {
+        average_rbs_per_user[CC_id] = (uint16_t) floor((nb_rbs_allowed_slice_uplink[CC_id][i]-first_rb[CC_id])/max_num_ue_to_be_scheduled);
+      } else {
+        average_rbs_per_user[CC_id]=1;
+        LOG_W(MAC,"[eNB %d] frame %d subframe %d: UE %d CC %d: can't get average rb per user (should not be here)\n",
+              module_idP,frameP,subframeP,UE_id,CC_id);
+      }
+    }
+  }
+  if (total_ue_count > 0)
+    LOG_D(MAC,"[eNB %d] Frame %d subframe %d: total ue to be scheduled %d/%d\n",
+    module_idP, frameP, subframeP,total_ue_count, max_num_ue_to_be_scheduled);
+
+  //LOG_D(MAC,"step3\n");
+
+  // step 3: assigne RBS
+  for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) {
+    rnti = UE_RNTI(module_idP,i);
+
+    if (rnti==NOT_A_RNTI)
+      continue;
+    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
+      continue;
+    if (!phy_stats_exist(module_idP, rnti))
+      continue;
+
+    UE_id = i;
+
+    for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
+      // This is the actual CC_id in the list
+      CC_id = UE_list->ordered_ULCCids[n][UE_id];
+      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];      
+      ue_sched_ctl->max_allowed_rbs[CC_id]=nb_rbs_allowed_slice_uplink[CC_id][UE_id];
+      // mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL);
+      flexran_get_harq(module_idP, CC_id, UE_id, 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];
+      } else {
+        nb_allocated_rbs[CC_id][UE_id] = cmin(UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul, average_rbs_per_user[CC_id]);
+      }
+
+      total_allocated_rbs[CC_id]+= nb_allocated_rbs[CC_id][UE_id];
+
+    }
+  }
+
+  // step 4: assigne the remaining RBs and set the pre_allocated rbs accordingly
+  for(r=0; r<2; r++) {
+
+    for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) {
+      rnti = UE_RNTI(module_idP,i);
+
+      if (rnti==NOT_A_RNTI)
+        continue;
+      if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
+  continue;
+      if (!phy_stats_exist(module_idP, rnti))
+        continue;
+
+      UE_id = i;
+
+      for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
+        // This is the actual CC_id in the list
+        CC_id = UE_list->ordered_ULCCids[n][UE_id];
+        UE_template = &UE_list->UE_template[CC_id][UE_id];        
+        frame_parms = mac_xface->get_lte_frame_parms(module_idP,CC_id);
+        total_remaining_rbs[CC_id]=nb_rbs_allowed_slice_uplink[CC_id][UE_id] - first_rb[CC_id] - total_allocated_rbs[CC_id];
+
+        if (total_ue_count == 1 ) {
+          total_remaining_rbs[CC_id]+=1;
+        }
+
+        if ( r == 0 ) {
+          while ( (UE_template->pre_allocated_nb_rb_ul > 0 ) &&
+                  (nb_allocated_rbs[CC_id][UE_id] < UE_template->pre_allocated_nb_rb_ul) &&
+                  (total_remaining_rbs[CC_id] > 0)) {
+            nb_allocated_rbs[CC_id][UE_id] = cmin(nb_allocated_rbs[CC_id][UE_id]+1,UE_template->pre_allocated_nb_rb_ul);
+            total_remaining_rbs[CC_id]--;
+            total_allocated_rbs[CC_id]++;
+          }
+        } else {
+          UE_template->pre_allocated_nb_rb_ul= nb_allocated_rbs[CC_id][UE_id];
+          LOG_D(MAC,"******************UL Scheduling Information for UE%d CC_id %d ************************\n",UE_id, CC_id);
+          LOG_D(MAC,"[eNB %d] total RB allocated for UE%d CC_id %d  = %d\n", module_idP, UE_id, CC_id, UE_template->pre_allocated_nb_rb_ul);
+        }
+      }
+    }
+  }
+
+  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+    frame_parms= mac_xface->get_lte_frame_parms(module_idP,CC_id);
+
+    if (total_allocated_rbs[CC_id]>0) {
+      LOG_D(MAC,"[eNB %d] total RB allocated for all UEs = %d/%d\n", module_idP, total_allocated_rbs[CC_id], nb_rbs_allowed_slice_uplink[CC_id][slice_id] - first_rb[CC_id]);
+    }
+  }
+}
+
+/*
+ * Main Uplink Slicing 
+ *
+ */
+
+void
+flexran_schedule_ue_ul_spec_default(mid_t   mod_id,
+				 uint32_t      frame,
+				 uint32_t      cooperation_flag,
+				 int           subframe,
+				 unsigned char sched_subframe,
+				 Protocol__FlexranMessage **ul_info)
+//------------------------------------------------------------------------------
+{
+  int i=0;
+  
+  flexran_agent_mac_create_empty_ul_config(mod_id, ul_info);
+   
+  for (i = 0; i < n_active_slices_uplink; i++) {
+    
+    // Load any updated functions
+    if (update_ul_scheduler[i] > 0 ) {
+      slice_sched_ul[i] = dlsym(NULL, ul_scheduler_type[i]); 
+      update_ul_scheduler[i] = 0;
+      update_ul_scheduler_current[i] = 0;
+      slice_percentage_current_uplink[i]= slice_percentage_uplink[i];
+      total_slice_percentage_uplink+=slice_percentage_uplink[i];
+      LOG_N(MAC,"update ul scheduler slice %d\n", i);
+    }
+ 
+    // check if the number of slices has changed, and log 
+    if (n_active_slices_uplink_current != n_active_slices_uplink ){
+      if ((n_active_slices_uplink > 0) && (n_active_slices_uplink <= MAX_NUM_SLICES)) {
+	LOG_N(MAC,"[eNB %d]frame %d subframe %d: number of active slices has changed: %d-->%d\n",
+	      mod_id, frame, subframe, n_active_slices_uplink_current, n_active_slices_uplink);
+
+	n_active_slices_uplink_current = n_active_slices_uplink;
+
+      } else {
+	LOG_W(MAC,"invalid number of slices %d, revert to the previous value %d\n",n_active_slices_uplink, n_active_slices_uplink_current);
+	n_active_slices_uplink = n_active_slices_uplink_current;
+      }
+    }
+    
+    // check if the slice rb share has changed, and log the console
+    if (slice_percentage_current_uplink[i] != slice_percentage_uplink[i]){
+ //      if ((slice_percentage_uplink[i] >= 0.0) && (slice_percentage_uplink[i] <= 1.0)){
+	// if ((total_slice_percentage_uplink - slice_percentage_current_uplink[i]  + slice_percentage_uplink[i]) <= 1.0) {
+	//   total_slice_percentage_uplink=total_slice_percentage_uplink - slice_percentage_current_uplink[i]  + slice_percentage_uplink[i];
+	  LOG_N(MAC,"[eNB %d][SLICE %d] frame %d subframe %d: total percentage %f, slice RB percentage has changed: %f-->%f\n",
+		mod_id, i, frame, subframe, total_slice_percentage_uplink, slice_percentage_current_uplink[i], slice_percentage_uplink[i]);
+
+	  slice_percentage_current_uplink[i] = slice_percentage_uplink[i];
+
+	// } else {
+	//   LOG_W(MAC,"[eNB %d][SLICE %d] invalid total RB share (%f->%f), revert the previous value (%f->%f)\n",
+	// 	mod_id,i,  
+	// 	total_slice_percentage_uplink,
+	// 	total_slice_percentage_uplink - slice_percentage_current_uplink[i]  + slice_percentage_uplink[i],
+	// 	slice_percentage_uplink[i],slice_percentage_current_uplink[i]);
+
+	//   slice_percentage_uplink[i]= slice_percentage_current_uplink[i];
+
+	// }
+ //      } else {
+	// LOG_W(MAC,"[eNB %d][SLICE %d] invalid slice RB share, revert the previous value (%f->%f)\n",mod_id, i,  slice_percentage_uplink[i],slice_percentage_current_uplink[i]);
+
+	// slice_percentage_uplink[i]= slice_percentage_current_uplink[i];
+
+      // }
+    }
+  
+    // check if a new scheduler, and log the console
+    if (update_ul_scheduler_current[i] != update_ul_scheduler[i]){
+      LOG_N(MAC,"[eNB %d][SLICE %d] frame %d subframe %d: DL scheduler for this slice is updated: %s \n",
+	    mod_id, i, frame, subframe, ul_scheduler_type[i]);
+
+      update_ul_scheduler_current[i] = update_ul_scheduler[i];
+      
+    }
+
+    // Run each enabled slice-specific schedulers one by one
+    //LOG_N(MAC,"[eNB %d]frame %d subframe %d slice %d: calling the scheduler\n", mod_id, frame, subframe,i);
+    
+
+    
+
+  }
+
+    slice_sched_ul[0](mod_id, frame, cooperation_flag, subframe, sched_subframe,ul_info);
+  
+}
+
+void
+flexran_schedule_ue_ul_spec_embb(mid_t  mod_id,
+			                    frame_t frame, 
+			                    unsigned char cooperation_flag,
+                		        uint32_t      subframe,
+			                    unsigned char sched_subframe,
+			                    Protocol__FlexranMessage **ul_info)
+
+{
+  flexran_agent_schedule_ulsch_ue_spec(mod_id,
+				                      frame,
+				                      cooperation_flag,
+				                      subframe,
+				                      sched_subframe,
+				                      ul_info);
+  
+}
+
+
+void flexran_agent_schedule_ulsch_ue_spec(mid_t module_idP, 
+		    frame_t frameP,
+		    unsigned char cooperation_flag,
+		    sub_frame_t subframeP, 
+		    unsigned char sched_subframe,
+        Protocol__FlexranMessage **ul_info) {
+
+
+  uint16_t first_rb[MAX_NUM_CCs],i;
+  int CC_id;
+  eNB_MAC_INST *eNB=&eNB_mac_inst[module_idP];
+
+  start_meas(&eNB->schedule_ulsch);
+
+
+  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+
+    //leave out first RB for PUCCH
+    first_rb[CC_id] = 1;
+
+    // UE data info;
+    // check which UE has data to transmit
+    // function to decide the scheduling
+    // e.g. scheduling_rslt = Greedy(granted_UEs, nb_RB)
+
+    // default function for default scheduling
+    //
+
+    // output of scheduling, the UE numbers in RBs, where it is in the code???
+    // check if RA (Msg3) is active in this subframeP, if so skip the PRBs used for Msg3
+    // Msg3 is using 1 PRB so we need to increase first_rb accordingly
+    // not sure about the break (can there be more than 1 active RA procedure?)
+
+    for (i=0; i<NB_RA_PROC_MAX; i++) {
+      if ((eNB->common_channels[CC_id].RA_template[i].RA_active == TRUE) &&
+          (eNB->common_channels[CC_id].RA_template[i].generate_rar == 0) &&
+          (eNB->common_channels[CC_id].RA_template[i].generate_Msg4 == 0) &&
+          (eNB->common_channels[CC_id].RA_template[i].wait_ack_Msg4 == 0) &&
+          (eNB->common_channels[CC_id].RA_template[i].Msg3_subframe == sched_subframe)) {
+        first_rb[CC_id]++;
+        eNB->common_channels[CC_id].RA_template[i].Msg3_subframe = -1;
+        break;
+      }
+    }
+
+    /*
+    if (mac_xface->is_prach_subframe(&(mac_xface->lte_frame_parms),frameP,subframeP)) {
+      first_rb[CC_id] = (mac_xface->get_prach_prb_offset(&(mac_xface->lte_frame_parms),
+    */
+
+  }
+
+  flexran_agent_schedule_ulsch_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe,first_rb);
+
+  stop_meas(&eNB->schedule_ulsch);
+
+}
+
+
+
+void flexran_agent_schedule_ulsch_rnti(module_id_t   module_idP,
+                         unsigned char cooperation_flag,
+                         frame_t       frameP,
+                         sub_frame_t   subframeP,
+                         unsigned char sched_subframe,
+                         uint16_t     *first_rb)
+{
+
+  int                UE_id;
+  uint8_t            aggregation    = 2;
+  rnti_t             rnti           = -1;
+  uint8_t            round          = 0;
+  uint8_t            harq_pid       = 0;
+  void              *ULSCH_dci      = NULL;
+  LTE_eNB_UE_stats  *eNB_UE_stats   = NULL;
+  DCI_PDU           *DCI_pdu;
+  uint8_t                 status         = 0;
+  uint8_t                 rb_table_index = -1;
+  uint16_t                TBS = 0;
+  //  int32_t                buffer_occupancy=0;
+  uint32_t                cqi_req,cshift,ndi,mcs=0,rballoc,tpc;
+  int32_t                 normalized_rx_power, target_rx_power=-90;
+  static int32_t          tpc_accumulated=0;
+
+  int n,CC_id = 0;
+  eNB_MAC_INST      *eNB=&eNB_mac_inst[module_idP];
+  UE_list_t         *UE_list=&eNB->UE_list;
+  UE_TEMPLATE       *UE_template;
+  UE_sched_ctrl     *UE_sched_ctrl;
+
+  //  int                rvidx_tab[4] = {0,2,3,1};
+  LTE_DL_FRAME_PARMS   *frame_parms;
+  int drop_ue=0;
+
+  //  LOG_I(MAC,"entering ulsch preprocesor\n");
+
+
+  /*TODO*/
+  int slice_id = 0;
+
+  
+  _ulsch_scheduler_pre_processor(module_idP,
+                                slice_id,  
+                                frameP,
+                                subframeP,
+                                first_rb);
+
+  //  LOG_I(MAC,"exiting ulsch preprocesor\n");
+
+  // loop over all active UEs
+  for (UE_id=UE_list->head_ul; UE_id>=0; UE_id=UE_list->next_ul[UE_id]) {
+
+    // don't schedule if Msg4 is not received yet
+    if (UE_list->UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured==FALSE) {
+      LOG_I(MAC,"[eNB %d] frame %d subfarme %d, UE %d: not configured, skipping UE scheduling \n", 
+	    module_idP,frameP,subframeP,UE_id);
+      continue;
+    }
+
+    rnti = flexran_get_ue_crnti(module_idP, UE_id);
+
+    if (rnti==NOT_A_RNTI) {
+      LOG_W(MAC,"[eNB %d] frame %d subfarme %d, UE %d: no RNTI \n", module_idP,frameP,subframeP,UE_id);
+      continue;
+    }
+
+    /* let's drop the UE if get_eNB_UE_stats returns NULL when calling it with any of the UE's active UL CCs */
+    /* TODO: refine? */
+    drop_ue = 0;
+    for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
+      CC_id = UE_list->ordered_ULCCids[n][UE_id];
+      if (mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti) == NULL) {
+        LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: no PHY context\n", module_idP,frameP,subframeP,UE_id,rnti,CC_id);
+        drop_ue = 1;
+        break;
+      }
+    }
+    if (drop_ue == 1) {
+/* we can't come here, ulsch_scheduler_pre_processor won't put in the list a UE with no PHY context */
+abort();
+      /* TODO: this is a hack. Sometimes the UE has no PHY context but
+       * is still present in the MAC with 'ul_failure_timer' = 0 and
+       * 'ul_out_of_sync' = 0. It seems wrong and the UE stays there forever. Let's
+       * start an UL out of sync procedure in this case.
+       * The root cause of this problem has to be found and corrected.
+       * In the meantime, this hack...
+       */
+      if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 0 &&
+          UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 0) {
+        LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: UE in weird state, let's put it 'out of sync'\n",
+              module_idP,frameP,subframeP,UE_id,rnti,CC_id);
+        // inform RRC of failure and clear timer
+        mac_eNB_rrc_ul_failure(module_idP,CC_id,frameP,subframeP,rnti);
+        UE_list->UE_sched_ctrl[UE_id].ul_failure_timer=0;
+        UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync=1;
+      }
+      continue;
+    }
+
+    // loop over all active UL CC_ids for this UE
+    for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
+      // This is the actual CC_id in the list
+      CC_id = UE_list->ordered_ULCCids[n][UE_id];
+      frame_parms = mac_xface->get_lte_frame_parms(module_idP,CC_id);
+      eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti);
+
+      aggregation=get_aggregation(get_bw_index(module_idP,CC_id), 
+				  eNB_UE_stats->DL_cqi[0],
+				  format0);
+      
+      if (CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,aggregation,rnti)) {
+        LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: not enough nCCE\n", module_idP,frameP,subframeP,UE_id,rnti,CC_id);
+        continue; // break;
+      } else{
+	LOG_D(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d mode %s: aggregation level %d\n", 
+	      module_idP,frameP,subframeP,UE_id,rnti,CC_id, mode_string[eNB_UE_stats->mode], 1<<aggregation);
+      }
+
+
+      if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel
+
+        DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu;
+        UE_template   = &UE_list->UE_template[CC_id][UE_id];
+        UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
+
+        if (flexran_get_harq(module_idP, CC_id, UE_id, 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);
+          continue;
+        } else
+          LOG_T(MAC,"[eNB %d] Frame %d, subframeP %d, UE %d CC %d : got harq pid %d  round %d (rnti %x,mode %s)\n",
+                module_idP,frameP,subframeP,UE_id,CC_id, harq_pid, round,rnti,mode_string[eNB_UE_stats->mode]);
+
+	PHY_vars_eNB_g[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP] = UE_template->ul_total_buffer;
+	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO,PHY_vars_eNB_g[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP]);	
+        if (((UE_is_to_be_scheduled(module_idP,CC_id,UE_id)>0)) || (round>0))// || ((frameP%10)==0))
+          // if there is information on bsr of DCCH, DTCH or if there is UL_SR, or if there is a packet to retransmit, or we want to schedule a periodic feedback every 10 frames
+        {
+	  LOG_D(MAC,"[eNB %d][PUSCH] Frame %d subframe %d Scheduling UE %d/%x in round %d(SR %d,UL_inactivity timer %d,UL_failure timer %d)\n",
+		module_idP,frameP,subframeP,UE_id,rnti,round,UE_template->ul_SR,
+		UE_sched_ctrl->ul_inactivity_timer,
+		UE_sched_ctrl->ul_failure_timer);
+          // reset the scheduling request
+          UE_template->ul_SR = 0;
+          // status = mac_eNB_get_rrc_status(module_idP,rnti);
+          status = flexran_get_rrc_status(module_idP, rnti);
+
+	  if (status < RRC_CONNECTED)
+	    cqi_req = 0;
+	  else if (UE_sched_ctrl->cqi_req_timer>30) {
+	    cqi_req = 1;
+	    UE_sched_ctrl->cqi_req_timer=0;
+	  }
+	  else
+	    cqi_req = 0;
+
+          //power control
+          //compute the expected ULSCH RX power (for the stats)
+
+          // this is the normalized RX power and this should be constant (regardless of mcs
+          normalized_rx_power = eNB_UE_stats->UL_rssi[0];
+          target_rx_power = mac_xface->get_target_pusch_rx_power(module_idP,CC_id);
+
+          // this assumes accumulated tpc
+	  // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
+	  int32_t framex10psubframe = UE_template->pusch_tpc_tx_frame*10+UE_template->pusch_tpc_tx_subframe;
+          if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case
+	      ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around
+	    {
+	    UE_template->pusch_tpc_tx_frame=frameP;
+	    UE_template->pusch_tpc_tx_subframe=subframeP;
+            if (normalized_rx_power>(target_rx_power+1)) {
+              tpc = 0; //-1
+              tpc_accumulated--;
+            } else if (normalized_rx_power<(target_rx_power-1)) {
+              tpc = 2; //+1
+              tpc_accumulated++;
+            } else {
+              tpc = 1; //0
+            }
+          } else {
+            tpc = 1; //0
+          }
+
+	  if (tpc!=1) {
+	    LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
+		  module_idP,frameP,subframeP,harq_pid,tpc,
+		  tpc_accumulated,normalized_rx_power,target_rx_power);
+	  }
+
+          // new transmission
+          if (round==0) {
+
+            ndi = 1-UE_template->oldNDI_UL[harq_pid];
+            UE_template->oldNDI_UL[harq_pid]=ndi;
+	    UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power;
+	    UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power;
+	    UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul;
+            mcs = UE_template->pre_assigned_mcs_ul;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS
+            if (UE_template->pre_allocated_rb_table_index_ul >=0) {
+              rb_table_index=UE_template->pre_allocated_rb_table_index_ul;
+            } else {
+	      mcs=10;//cmin (10, openair_daq_vars.target_ue_ul_mcs);
+              rb_table_index=5; // for PHR
+	    }
+
+            UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=mcs;
+	    //            buffer_occupancy = UE_template->ul_total_buffer;
+
+            while (((rb_table[rb_table_index]>(nb_rbs_allowed_slice_uplink[CC_id][UE_id]-1-first_rb[CC_id])) ||
+		    (rb_table[rb_table_index]>45)) &&
+                   (rb_table_index>0)) {
+              rb_table_index--;
+            }
+
+            TBS = mac_xface->get_TBS_UL(mcs,rb_table[rb_table_index]);
+	    UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=rb_table[rb_table_index];
+	    UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=TBS;
+	    //            buffer_occupancy -= TBS;
+            rballoc = mac_xface->computeRIV(frame_parms->N_RB_UL,
+                                            first_rb[CC_id],
+                                            rb_table[rb_table_index]);
+
+            T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP),
+              T_INT(subframeP), T_INT(harq_pid), T_INT(mcs), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]),
+              T_INT(TBS), T_INT(ndi));
+
+	    if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED)
+	      LOG_I(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n",
+		    module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,mcs,
+		    first_rb[CC_id],rb_table[rb_table_index],
+		    rb_table_index,TBS,harq_pid);
+
+	    // bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
+            // increment for next UE allocation
+            first_rb[CC_id]+=rb_table[rb_table_index];
+            //store for possible retransmission
+            UE_template->nb_rb_ul[harq_pid] = rb_table[rb_table_index];
+	    UE_sched_ctrl->ul_scheduled |= (1<<harq_pid);
+	    if (UE_id == UE_list->head)
+	      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED,UE_sched_ctrl->ul_scheduled);
+
+	    // adjust total UL buffer status by TBS, wait for UL sdus to do final update
+	    LOG_D(MAC,"[eNB %d] CC_id %d UE %d/%x : adjusting ul_total_buffer, old %d, TBS %d\n", module_idP,CC_id,UE_id,rnti,UE_template->ul_total_buffer,TBS);
+	    if (UE_template->ul_total_buffer > TBS)
+	      UE_template->ul_total_buffer -= TBS;
+	    else
+	      UE_template->ul_total_buffer = 0;
+	    LOG_D(MAC,"ul_total_buffer, new %d\n", UE_template->ul_total_buffer);
+	    // Cyclic shift for DM RS
+	    cshift = 0;// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1)
+	    	    
+	    if (frame_parms->frame_type == TDD) {
+	      switch (frame_parms->N_RB_UL) {
+	      case 6:
+		ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
+		
+		((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->type     = 0;
+		((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->hopping  = 0;
+		((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->rballoc  = rballoc;
+		((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->mcs      = mcs;
+		((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->ndi      = ndi;
+		((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->TPC      = tpc;
+		((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->cshift   = cshift;
+		((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->padding  = 0;
+		((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->dai      = UE_template->DAI_ul[sched_subframe];
+		((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req  = cqi_req;
+		
+		add_ue_spec_dci(DCI_pdu,
+				ULSCH_dci,
+				rnti,
+				sizeof(DCI0_1_5MHz_TDD_1_6_t),
+				aggregation,
+				sizeof_DCI0_1_5MHz_TDD_1_6_t,
+				format0,
+				0);
+		break;
+		
+	      default:
+	      case 25:
+		ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
+		
+		((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->type     = 0;
+		((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->hopping  = 0;
+		((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->rballoc  = rballoc;
+		((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->mcs      = mcs;
+		((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->ndi      = ndi;
+		((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->TPC      = tpc;
+		((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->cshift   = cshift;
+		((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->padding  = 0;
+		((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->dai      = UE_template->DAI_ul[sched_subframe];
+		((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req  = cqi_req;
+		
+		add_ue_spec_dci(DCI_pdu,
+				ULSCH_dci,
+				rnti,
+				sizeof(DCI0_5MHz_TDD_1_6_t),
+				aggregation,
+				sizeof_DCI0_5MHz_TDD_1_6_t,
+				format0,
+				0);
+		break;
+		
+	      case 50:
+		ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
+		
+		((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->type     = 0;
+		((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->hopping  = 0;
+		((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->rballoc  = rballoc;
+		((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->mcs      = mcs;
+		((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->ndi      = ndi;
+		((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->TPC      = tpc;
+		((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->cshift   = cshift;
+		((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->padding  = 0;
+		((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->dai      = UE_template->DAI_ul[sched_subframe];
+		((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req  = cqi_req;
+		
+		add_ue_spec_dci(DCI_pdu,
+				ULSCH_dci,
+				rnti,
+				sizeof(DCI0_10MHz_TDD_1_6_t),
+				aggregation,
+				sizeof_DCI0_10MHz_TDD_1_6_t,
+				format0,
+				0);
+		break;
+		
+	      case 100:
+		ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
+		
+		((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->type     = 0;
+		((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->hopping  = 0;
+		((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->rballoc  = rballoc;
+		((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->mcs      = mcs;
+		((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->ndi      = ndi;
+		((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->TPC      = tpc;
+		((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->cshift   = cshift;
+		((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->padding  = 0;
+		((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->dai      = UE_template->DAI_ul[sched_subframe];
+		((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req  = cqi_req;
+		
+		add_ue_spec_dci(DCI_pdu,
+				ULSCH_dci,
+				rnti,
+				sizeof(DCI0_20MHz_TDD_1_6_t),
+				aggregation,
+				sizeof_DCI0_20MHz_TDD_1_6_t,
+				format0,
+				0);
+		break;
+	      }
+	    } // TDD
+	    else { //FDD
+	      switch (frame_parms->N_RB_UL) {
+	      case 25:
+	      default:
+		
+		ULSCH_dci          = UE_template->ULSCH_DCI[harq_pid];
+		
+		((DCI0_5MHz_FDD_t *)ULSCH_dci)->type     = 0;
+		((DCI0_5MHz_FDD_t *)ULSCH_dci)->hopping  = 0;
+		((DCI0_5MHz_FDD_t *)ULSCH_dci)->rballoc  = rballoc;
+		((DCI0_5MHz_FDD_t *)ULSCH_dci)->mcs      = mcs;
+		((DCI0_5MHz_FDD_t *)ULSCH_dci)->ndi      = ndi;
+		((DCI0_5MHz_FDD_t *)ULSCH_dci)->TPC      = tpc;
+		((DCI0_5MHz_FDD_t *)ULSCH_dci)->cshift   = cshift;
+		((DCI0_5MHz_FDD_t *)ULSCH_dci)->padding  = 0;
+		((DCI0_5MHz_FDD_t *)ULSCH_dci)->cqi_req  = cqi_req;
+		
+		add_ue_spec_dci(DCI_pdu,
+				ULSCH_dci,
+				rnti,
+				sizeof(DCI0_5MHz_FDD_t),
+				aggregation,
+				sizeof_DCI0_5MHz_FDD_t,
+				format0,
+				0);
+		break;
+		
+	      case 6:
+		ULSCH_dci          = UE_template->ULSCH_DCI[harq_pid];
+		
+		((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->type     = 0;
+		((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->hopping  = 0;
+		((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->rballoc  = rballoc;
+		((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->mcs      = mcs;
+		((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->ndi      = ndi;
+		((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->TPC      = tpc;
+		((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->cshift   = cshift;
+		((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->padding  = 0;
+		((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->cqi_req  = cqi_req;
+		
+		add_ue_spec_dci(DCI_pdu,
+				ULSCH_dci,
+				rnti,
+				sizeof(DCI0_1_5MHz_FDD_t),
+				aggregation,
+				sizeof_DCI0_1_5MHz_FDD_t,
+				format0,
+				0);
+		break;
+		
+	      case 50:
+		ULSCH_dci          = UE_template->ULSCH_DCI[harq_pid];
+		
+		((DCI0_10MHz_FDD_t *)ULSCH_dci)->type     = 0;
+		((DCI0_10MHz_FDD_t *)ULSCH_dci)->hopping  = 0;
+		((DCI0_10MHz_FDD_t *)ULSCH_dci)->rballoc  = rballoc;
+		((DCI0_10MHz_FDD_t *)ULSCH_dci)->mcs      = mcs;
+		((DCI0_10MHz_FDD_t *)ULSCH_dci)->ndi      = ndi;
+		((DCI0_10MHz_FDD_t *)ULSCH_dci)->TPC      = tpc;
+		((DCI0_10MHz_FDD_t *)ULSCH_dci)->padding  = 0;
+		((DCI0_10MHz_FDD_t *)ULSCH_dci)->cshift   = cshift;
+		((DCI0_10MHz_FDD_t *)ULSCH_dci)->cqi_req  = cqi_req;
+		
+		add_ue_spec_dci(DCI_pdu,
+				ULSCH_dci,
+				rnti,
+				sizeof(DCI0_10MHz_FDD_t),
+				aggregation,
+				sizeof_DCI0_10MHz_FDD_t,
+				format0,
+				0);
+		break;
+		
+	      case 100:
+		ULSCH_dci          = UE_template->ULSCH_DCI[harq_pid];
+		
+		((DCI0_20MHz_FDD_t *)ULSCH_dci)->type     = 0;
+		((DCI0_20MHz_FDD_t *)ULSCH_dci)->hopping  = 0;
+		((DCI0_20MHz_FDD_t *)ULSCH_dci)->rballoc  = rballoc;
+		((DCI0_20MHz_FDD_t *)ULSCH_dci)->mcs      = mcs;
+		((DCI0_20MHz_FDD_t *)ULSCH_dci)->ndi      = ndi;
+		((DCI0_20MHz_FDD_t *)ULSCH_dci)->TPC      = tpc;
+		((DCI0_20MHz_FDD_t *)ULSCH_dci)->padding  = 0;
+		((DCI0_20MHz_FDD_t *)ULSCH_dci)->cshift   = cshift;
+		((DCI0_20MHz_FDD_t *)ULSCH_dci)->cqi_req  = cqi_req;
+		
+		add_ue_spec_dci(DCI_pdu,
+				ULSCH_dci,
+				rnti,
+				sizeof(DCI0_20MHz_FDD_t),
+				aggregation,
+				sizeof_DCI0_20MHz_FDD_t,
+				format0,
+				0);
+		break;
+		
+	      }
+	    }
+
+
+	    add_ue_ulsch_info(module_idP,
+			      CC_id,
+			      UE_id,
+			      subframeP,
+			      S_UL_SCHEDULED);
+	    
+	    LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", module_idP,CC_id,frameP,subframeP,UE_id);
+#ifdef DEBUG
+	    dump_dci(frame_parms, &DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci-1]);
+#endif
+	    
+          }
+	  else {
+            T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP),
+              T_INT(subframeP), T_INT(harq_pid), T_INT(mcs), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]),
+              T_INT(round));
+
+            LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled (PHICH) UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d,round %d)\n",
+                  module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,mcs,
+                  first_rb[CC_id],rb_table[rb_table_index],
+                  rb_table_index,TBS,harq_pid,round);
+	  }/* 
+	  else if (round > 0) { //we schedule a retransmission
+
+            ndi = UE_template->oldNDI_UL[harq_pid];
+
+            if ((round&3)==0) {
+              mcs = openair_daq_vars.target_ue_ul_mcs;
+            } else {
+              mcs = rvidx_tab[round&3] + 28; //not correct for round==4!
+
+            }
+
+            LOG_I(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE retransmission (mcs %d, first rb %d, nb_rb %d, harq_pid %d, round %d)\n",
+                  module_idP,UE_id,rnti,CC_id,frameP,subframeP,mcs,
+                  first_rb[CC_id],UE_template->nb_rb_ul[harq_pid],
+		  harq_pid, round);
+
+            rballoc = mac_xface->computeRIV(frame_parms->N_RB_UL,
+                                            first_rb[CC_id],
+                                            UE_template->nb_rb_ul[harq_pid]);
+            first_rb[CC_id]+=UE_template->nb_rb_ul[harq_pid];  // increment for next UE allocation
+         
+	    UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission_rx+=1;
+	    UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx_rx=UE_template->nb_rb_ul[harq_pid];
+	    UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=UE_template->nb_rb_ul[harq_pid];
+	    UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=mcs;
+	    UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=mcs;
+	  }
+	   */
+
+        } // UE_is_to_be_scheduled
+      } // UE is in PUSCH
+    } // loop over UE_id
+  } // loop of CC_id
+}
+