From 9956b96049a32ec9ccb3aa9e78ff6aa0008044f8 Mon Sep 17 00:00:00 2001
From: Robert Schmidt <robert.schmidt@eurecom.fr>
Date: Sun, 12 Apr 2020 14:38:05 +0200
Subject: [PATCH] Use fptr for preproc and align UL PP definition

---
 openair2/ENB_APP/enb_config.c                 |  9 +--
 openair2/LAYER2/MAC/eNB_scheduler_dlsch.c     |  5 +-
 .../LAYER2/MAC/eNB_scheduler_primitives.c     | 12 ++++
 openair2/LAYER2/MAC/eNB_scheduler_ulsch.c     |  4 +-
 openair2/LAYER2/MAC/mac.h                     | 59 +++++++++++++++++--
 openair2/LAYER2/MAC/mac_proto.h               |  6 +-
 openair2/LAYER2/MAC/main.c                    | 13 ++--
 openair2/LAYER2/MAC/pre_processor.c           | 46 +++++++--------
 8 files changed, 110 insertions(+), 44 deletions(-)

diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 0308c2fd79..1d189832b4 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -266,10 +266,11 @@ void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) {
       void *d = dlsym(NULL, s);
       AssertFatal(d, "%s(): no default scheduler DL algo '%s' found\n", __func__, s);
       // release default, add new
-      RC.mac[j]->dl_algo.unset(&RC.mac[j]->dl_algo.data);
-      RC.mac[j]->dl_algo = *(default_sched_dl_algo_t *) d;
-      RC.mac[j]->dl_algo.data = RC.mac[j]->dl_algo.setup();
-      LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", RC.mac[j]->dl_algo.name);
+      pp_impl_param_t *dl_pp = &RC.mac[j]->pre_processor_dl;
+      dl_pp->dl_algo.unset(&dl_pp->dl_algo.data);
+      dl_pp->dl_algo = *(default_sched_dl_algo_t *) d;
+      dl_pp->dl_algo.data = dl_pp->dl_algo.setup();
+      LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", dl_pp->dl_algo.name);
     }// j=0..num_inst
   } /*else {// MacRLC_ParamList.numelt > 0 // ignore it
 
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
index 783d4e8b1a..1f99f50ece 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
@@ -573,10 +573,7 @@ schedule_ue_spec(module_id_t module_idP,
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,
                                           VCD_FUNCTION_IN);
   start_meas(&eNB->schedule_dlsch_preprocessor);
-  dlsch_scheduler_pre_processor(module_idP,
-                                CC_id,
-                                frameP,
-                                subframeP);
+  eNB->pre_processor_dl.dl(module_idP, CC_id, frameP, subframeP);
   stop_meas(&eNB->schedule_dlsch_preprocessor);
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,
                                           VCD_FUNCTION_OUT);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
index b75ab774c6..89c2ecc83d 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
@@ -2199,6 +2199,12 @@ add_new_ue(module_id_t mod_idP,
     UE_info->active[UE_id] = TRUE;
     add_ue_list(&UE_info->list, UE_id);
     dump_ue_list(&UE_info->list);
+    pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl;
+    if (dl->slices) // inform slice implementation about new UE
+      dl->add_UE(dl->slices, UE_id);
+    pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul;
+    if (ul->slices) // inform slice implementation about new UE
+      ul->add_UE(ul->slices, UE_id);
     if (IS_SOFTMODEM_IQPLAYER)// not specific to record/playback ?
       UE_info->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0;
     UE_info->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type;
@@ -2262,6 +2268,12 @@ rrc_mac_remove_ue(module_id_t mod_idP,
   UE_info->num_UEs--;
 
   remove_ue_list(&UE_info->list, UE_id);
+  pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl;
+  if (dl->slices) // inform slice implementation about new UE
+    dl->remove_UE(dl->slices, UE_id);
+  pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul;
+  if (ul->slices) // inform slice implementation about new UE
+    ul->remove_UE(ul->slices, UE_id);
 
   /* Clear all remaining pending transmissions */
   memset(&UE_info->UE_template[pCC_id][UE_id], 0, sizeof(UE_TEMPLATE));
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
index 3062e5c964..2de45db856 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
@@ -1301,11 +1301,11 @@ schedule_ulsch_rnti(module_id_t   module_idP,
 
   /*
    * ULSCH preprocessor: set UE_template->
-   * pre_allocated_nb_rb_ul[slice_idx]
+   * pre_allocated_nb_rb_ul
    * pre_assigned_mcs_ul
    * pre_allocated_rb_table_index_ul
    */
-  ulsch_scheduler_pre_processor(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP);
+  mac->pre_processor_ul.ul(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP);
 
   for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
     if (UE_info->UE_template[CC_id][UE_id].rach_resource_type > 0)
diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h
index 8349d84d48..faefc481f6 100644
--- a/openair2/LAYER2/MAC/mac.h
+++ b/openair2/LAYER2/MAC/mac.h
@@ -540,7 +540,6 @@ typedef enum {
   SCHED_MODE_FAIR_RR      /// fair raund robin
 } SCHEDULER_MODES;
 
-
 /*! \brief temporary struct for ULSCH sched */
 typedef struct {
   rnti_t rnti;
@@ -1199,6 +1198,56 @@ typedef struct {
   void *data;
 } default_sched_ul_algo_t;
 
+typedef void (*pp_impl_dl)(module_id_t mod_id,
+                           int CC_id,
+                           frame_t frame,
+                           sub_frame_t subframe);
+typedef void (*pp_impl_ul)(module_id_t mod_id,
+                           int CC_id,
+                           frame_t frame,
+                           sub_frame_t subframe,
+                           frame_t sched_frame,
+                           sub_frame_t sched_subframe);
+
+struct slice_info_s;
+typedef struct {
+  int algorithm;
+
+  /// inform the slice algorithm about a new UE
+  void (*add_UE)(struct slice_info_s *s, int UE_id);
+  /// inform the slice algorithm about a UE that disconnected
+  void (*remove_UE)(struct slice_info_s *s, int UE_id);
+  /// move a UE to a slice in DL/UL, -1 means don't move (no-op).
+  void (*move_UE)(struct slice_info_s *s, int UE_id, int idx);
+
+  /// Adds a new slice through admission control. slice_params are
+  /// algorithm-specific parameters. sched is either a default_sched_ul_algo_t
+  /// or default_sched_dl_algo_t, depending on whether this implementation
+  /// handles UL/DL. If slice at index exists, updates existing
+  /// slice. Returns index of new slice or -1 on failure.
+  int (*addmod_slice)(struct slice_info_s *s,
+                      int id,
+                      char *label,
+                      void *sched,
+                      void *slice_params);
+  /// Returns slice through slice_idx. 1 if successful, 0 if not.
+  int (*remove_slice)(struct slice_info_s *s, uint8_t slice_idx);
+
+  union {
+    pp_impl_dl dl;
+    pp_impl_ul ul;
+  };
+
+  union {
+    default_sched_ul_algo_t ul_algo;
+    default_sched_dl_algo_t dl_algo;
+  };
+
+  void (*destroy)(struct slice_info_s **s);
+
+  struct slice_info_s *slices;
+} pp_impl_param_t;
+
 /*! \brief eNB common channels */
 typedef struct {
   int physCellId;
@@ -1354,9 +1403,11 @@ typedef struct eNB_MAC_INST_s {
   UE_free_list_t UE_free_list;
   /// for scheduling selection
   SCHEDULER_MODES scheduler_mode;
-  /// scheduling algorithm used in default scheduler
-  default_sched_dl_algo_t dl_algo;
-  default_sched_ul_algo_t ul_algo;
+  /// Default scheduler: Pre-processor implementation. Algorithms for UL/DL
+  /// are called by ULSCH/DLSCH, respectively. Pro-processor implementation can
+  /// encapsulate slicing.
+  pp_impl_param_t pre_processor_dl;
+  pp_impl_param_t pre_processor_ul;
 
   int32_t puSch10xSnr;
   int32_t puCch10xSnr;
diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h
index 818eb834fb..9d49fdffd5 100644
--- a/openair2/LAYER2/MAC/mac_proto.h
+++ b/openair2/LAYER2/MAC/mac_proto.h
@@ -674,10 +674,10 @@ void set_ul_DAI(int module_idP,
 
 void ulsch_scheduler_pre_processor(module_id_t module_idP,
                                    int CC_id,
-                                   int frameP,
+                                   frame_t frameP,
                                    sub_frame_t subframeP,
-                                   int sched_frameP,
-                                   unsigned char sched_subframeP);
+                                   frame_t sched_frameP,
+                                   sub_frame_t sched_subframeP);
 
 int phy_stats_exist(module_id_t Mod_id, int rnti);
 
diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c
index 659c7250e8..24038e60d5 100644
--- a/openair2/LAYER2/MAC/main.c
+++ b/openair2/LAYER2/MAC/main.c
@@ -99,16 +99,21 @@ void mac_top_init_eNB(void)
     }
 
     mac[i]->if_inst = IF_Module_init(i);
+
+    mac[i]->pre_processor_dl.dl = dlsch_scheduler_pre_processor;
     char *s = "round_robin_dl";
     void *d = dlsym(NULL, s);
     AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s);
-    mac[i]->dl_algo = *(default_sched_dl_algo_t *) d;
-    mac[i]->dl_algo.data = mac[i]->dl_algo.setup();
+    mac[i]->pre_processor_dl.dl_algo = *(default_sched_dl_algo_t *) d;
+    mac[i]->pre_processor_dl.dl_algo.data = mac[i]->pre_processor_dl.dl_algo.setup();
+
+    mac[i]->pre_processor_ul.ul = ulsch_scheduler_pre_processor;
     s = "round_robin_ul";
     d = dlsym(NULL, s);
     AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s);
-    mac[i]->ul_algo = *(default_sched_ul_algo_t *) d;
-    mac[i]->ul_algo.data = mac[i]->ul_algo.setup();
+    mac[i]->pre_processor_ul.ul_algo = *(default_sched_ul_algo_t *) d;
+    mac[i]->pre_processor_ul.ul_algo.data = mac[i]->pre_processor_ul.ul_algo.setup();
+
     init_UE_info(&mac[i]->UE_info);
   }
 
diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c
index d7dfc7816a..6477d60021 100644
--- a/openair2/LAYER2/MAC/pre_processor.c
+++ b/openair2/LAYER2/MAC/pre_processor.c
@@ -703,15 +703,15 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
     n_rbg_sched += rbgalloc_mask[i];
   }
 
-  mac->dl_algo.run(Mod_id,
-                   CC_id,
-                   frameP,
-                   subframeP,
-                   &UE_to_sched,
-                   4, // max_num_ue
-                   n_rbg_sched,
-                   rbgalloc_mask,
-                   mac->dl_algo.data);
+  mac->pre_processor_dl.dl_algo.run(Mod_id,
+                                    CC_id,
+                                    frameP,
+                                    subframeP,
+                                    &UE_to_sched,
+                                    4, // max_num_ue
+                                    n_rbg_sched,
+                                    rbgalloc_mask,
+                                    mac->pre_processor_dl.dl_algo.data);
 
   // the following block is meant for validation of the pre-processor to check
   // whether all UE allocations are non-overlapping and is not necessary for
@@ -1080,10 +1080,10 @@ default_sched_ul_algo_t round_robin_ul = {
 
 void ulsch_scheduler_pre_processor(module_id_t Mod_id,
                                    int CC_id,
-                                   int frameP,
+                                   frame_t frameP,
                                    sub_frame_t subframeP,
-                                   int sched_frameP,
-                                   unsigned char sched_subframeP) {
+                                   frame_t sched_frameP,
+                                   sub_frame_t sched_subframeP) {
   eNB_MAC_INST *mac = RC.mac[Mod_id];
   UE_info_t *UE_info = &mac->UE_info;
   const int N_RB_UL = to_prb(mac->common_channels[CC_id].ul_Bandwidth);
@@ -1140,17 +1140,17 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id,
     }
   }
 
-  mac->ul_algo.run(Mod_id,
-                   CC_id,
-                   frameP,
-                   subframeP,
-                   sched_frameP,
-                   sched_subframeP,
-                   &UE_to_sched,
-                   4, // max_num_ue
-                   n_contig,
-                   rbs,
-                   mac->ul_algo.data);
+  mac->pre_processor_ul.ul_algo.run(Mod_id,
+                                    CC_id,
+                                    frameP,
+                                    subframeP,
+                                    sched_frameP,
+                                    sched_subframeP,
+                                    &UE_to_sched,
+                                    4, // max_num_ue
+                                    n_contig,
+                                    rbs,
+                                    mac->pre_processor_ul.ul_algo.data);
 
   // the following block is meant for validation of the pre-processor to check
   // whether all UE allocations are non-overlapping and is not necessary for
-- 
2.26.2