diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h
index 3f736e5b3cf5406c1b22d930142320aa393282dc..a94d785bee67be30819e53da06699980eb115f5c 100644
--- a/openair2/COMMON/platform_types.h
+++ b/openair2/COMMON/platform_types.h
@@ -110,7 +110,8 @@ typedef enum {
     CR_HOL   = 2,
     CR_LC    = 3,
     CR_CQI   = 4,
-    CR_NUM   = 5
+    CR_LCP   = 5,
+    CR_NUM   = 6
 } sorting_criterion_t;
 
 //-----------------------------------------------------------------------------
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
index 44083a461085eba47f90cab1727d46decfe3d0f0..472c4e2a118488680f5de536eb6730450f735ef7 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
@@ -70,6 +70,7 @@ extern RAN_CONTEXT_t RC;
 extern uint8_t nfapi_mode;
 extern pre_processor_results_t pre_processor_results[MAX_NUM_SLICES];
 extern int slice_isolation[MAX_NUM_SLICES];
+extern int slice_priority[MAX_NUM_SLICES];
 
 //------------------------------------------------------------------------------
 void
@@ -534,23 +535,44 @@ schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, in
     }
 
     // Check for new sorting policy
-    if (slice_sorting_policy_current[i] != slice_sorting_policy[i]) {
+    if (slice_sorting_current[i] != slice_sorting[i]) {
       LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: UE sorting policy has changed (%x-->%x)\n",
-            module_idP, i, frameP, subframeP, slice_sorting_policy_current[i], slice_sorting_policy[i]);
-      slice_sorting_policy_current[i] = slice_sorting_policy[i];
+            module_idP, i, frameP, subframeP, slice_sorting_current[i], slice_sorting[i]);
+      slice_sorting_current[i] = slice_sorting[i];
+    }
+
+    // Check for new slice isolation
+    if (slice_isolation_current[i] != slice_isolation[i]) {
+      if (slice_isolation[i] != 1 && slice_isolation[i] != 0) {
+        LOG_W(MAC,
+              "[eNB %d][SLICE %d][DL] frame %d subframe %d: invalid slice isolation setting (%d), revert to its previous value (%d)\n",
+              module_idP, i, frameP, subframeP, slice_isolation[i], slice_isolation_current[i]);
+        slice_isolation[i] = slice_isolation_current[i];
+      } else {
+        LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: slice isolation setting has changed (%x-->%x)\n",
+              module_idP, i, frameP, subframeP, slice_isolation_current[i], slice_isolation[i]);
+        slice_isolation_current[i] = slice_isolation[i];
+      }
+    }
+
+    // Check for new slice priority
+    if (slice_priority_current[i] != slice_priority[i]) {
+      LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: slice priority setting has changed (%x-->%x)\n",
+            module_idP, i, frameP, subframeP, slice_priority_current[i], slice_priority[i]);
+      slice_priority_current[i] = slice_priority[i];
     }
 
     // Check for new accounting policy
-    if (slice_accounting_policy_current[i] != slice_accounting_policy[i]) {
-      if (slice_accounting_policy[i] > 1 || slice_accounting_policy[i] < 0) {
+    if (slice_accounting_current[i] != slice_accounting[i]) {
+      if (slice_accounting[i] > 1 || slice_accounting[i] < 0) {
         LOG_W(MAC,
               "[eNB %d][SLICE %d][DL] frame %d subframe %d: invalid accounting policy (%d), revert to its previous value (%d)\n",
-              module_idP, i, frameP, subframeP, slice_accounting_policy[i], slice_accounting_policy_current[i]);
-        slice_accounting_policy[i] = slice_accounting_policy_current[i];
+              module_idP, i, frameP, subframeP, slice_accounting[i], slice_accounting_current[i]);
+        slice_accounting[i] = slice_accounting_current[i];
       } else {
         LOG_N(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: UE sorting policy has changed (%x-->%x)\n",
-              module_idP, i, frameP, subframeP, slice_accounting_policy_current[i], slice_accounting_policy[i]);
-        slice_accounting_policy_current[i] = slice_accounting_policy[i];
+              module_idP, i, frameP, subframeP, slice_accounting_current[i], slice_accounting[i]);
+        slice_accounting_current[i] = slice_accounting[i];
       }
     }
 
@@ -1570,6 +1592,7 @@ void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id, int frameP, sub
   COMMON_channels_t *cc;
   int N_RBG[NFAPI_CC_MAX];
 
+  int slice_sorted_list[MAX_NUM_SLICES], slice_id;
   int8_t free_rbgs_map[NFAPI_CC_MAX][N_RBG_MAX];
   int has_traffic[NFAPI_CC_MAX][MAX_NUM_SLICES];
   uint8_t allocation_mask[NFAPI_CC_MAX][N_RBG_MAX];
@@ -1613,7 +1636,7 @@ void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id, int frameP, sub
     }
   }
 
-  // TODO: Sort slices by priority and use the sorted list in the code below (For now we assume 0 = max_priority)
+  slice_priority_sort(slice_sorted_list);
 
   // MULTIPLEXING
   // This part is an adaptation of dlsch_scheduler_pre_processor_allocate() code
@@ -1623,8 +1646,9 @@ void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id, int frameP, sub
     min_rb_unit = get_min_rb_unit(Mod_id, CC_id);
 
     for (i = 0; i < n_active_slices; ++i) {
+      slice_id = slice_sorted_list[i];
 
-      if (has_traffic[CC_id][i] == 0) continue;
+      if (has_traffic[CC_id][slice_id] == 0) continue;
 
       // Build an ad-hoc allocation mask fo the slice
       for (rbg = 0; rbg < N_RBG[CC_id]; ++rbg) {
@@ -1644,12 +1668,13 @@ void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id, int frameP, sub
 
       // Sort UE again
       // (UE list gets sorted every time pre_processor is called so it is probably dirty at this point)
-      sort_UEs(Mod_id, (slice_id_t) i, frameP, subframeP);
+      // FIXME: There is only one UE_list for all slices, so it must be sorted again each time we use it
+      sort_UEs(Mod_id, (slice_id_t) slice_id, frameP, subframeP);
 
-      nb_rbs_remaining = pre_processor_results[i].nb_rbs_remaining;
-      nb_rbs_required = pre_processor_results[i].nb_rbs_required;
-      rballoc_sub = pre_processor_results[i].slice_allocated_rbgs;
-      MIMO_mode_indicator = pre_processor_results[i].MIMO_mode_indicator;
+      nb_rbs_remaining = pre_processor_results[slice_id].nb_rbs_remaining;
+      nb_rbs_required = pre_processor_results[slice_id].nb_rbs_required;
+      rballoc_sub = pre_processor_results[slice_id].slice_allocated_rbgs;
+      MIMO_mode_indicator = pre_processor_results[slice_id].MIMO_mode_indicator;
 
       // Allocation
       for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
@@ -1699,6 +1724,32 @@ void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id, int frameP, sub
   }
 }
 
+//------------------------------------------------------------------------------
+void dlsch_scheduler_qos_multiplexing(module_id_t Mod_id, int frameP, sub_frame_t subframeP)
+//------------------------------------------------------------------------------
+{
+  int UE_id, CC_id, i;
+  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
+  UE_sched_ctrl *ue_sched_ctl;
+
+  for (CC_id = 0; CC_id < MAX_NUM_CCs; ++CC_id) {
+    for (i = 0; i < n_active_slices; ++i) {
+
+      // Sort UE again
+      // FIXME: There is only one UE_list for all slices, so it must be sorted again each time we use it
+      sort_UEs(Mod_id, (slice_id_t) i, frameP, subframeP);
+
+      for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
+        ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+
+        // TODO: Do something here
+        ue_sched_ctl->pre_nb_available_rbs[CC_id];
+      }
+    }
+  }
+}
+
+
 //------------------------------------------------------------------------------
 void
 fill_DLSCH_dci(module_id_t module_idP,
@@ -2252,3 +2303,24 @@ void schedule_PCH(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
   stop_meas(&eNB->schedule_pch);
   return;
 }
+
+static int slice_priority_compare(const void *_a, const void *_b) {
+
+  int slice_id1 = *(const int *) _a;
+  int slice_id2 = *(const int *) _b;
+
+  if (slice_priority[slice_id1] > slice_priority[slice_id2]) {
+    return -1;
+  }
+  return 1;
+}
+
+void slice_priority_sort(int slice_list[MAX_NUM_SLICES]) {
+
+  int i;
+  for (i = 0; i < MAX_NUM_SLICES; ++i) {
+    slice_list[i] = i;
+  }
+
+  qsort(slice_list, MAX_NUM_SLICES, sizeof(int), slice_priority_compare);
+}
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.h b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.h
index 8bd227645cb78fe5dc8b2ad46de34dadb0d9c02d..321f83c20df9862e249f5d18554a01fde574ed74 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.h
+++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.h
@@ -48,7 +48,11 @@ float     slice_percentage_current[MAX_NUM_SLICES] = {1.0, 0.0, 0.0, 0.0};
 float     slice_percentage_total = 0;
 float     slice_percentage_total_current = 0;
 float     slice_percentage_avg = 0.25;
+
 int       slice_isolation[MAX_NUM_SLICES] = {0, 0, 0, 0};
+int       slice_isolation_current[MAX_NUM_SLICES] = {0, 0, 0, 0};
+int       slice_priority[MAX_NUM_SLICES] = {10, 5, 2, 0};
+int       slice_priority_current[MAX_NUM_SLICES] = {10, 5, 2, 0};
 
 // Frequency ranges for slice positioning
 int       slice_position[MAX_NUM_SLICES*2]         = {0, N_RBG_MAX, 0, N_RBG_MAX, 0, N_RBG_MAX, 0, N_RBG_MAX};
@@ -59,12 +63,12 @@ int       slice_maxmcs[MAX_NUM_SLICES]         = { 28, 28, 28, 28 };
 int       slice_maxmcs_current[MAX_NUM_SLICES] = { 28, 28, 28, 28 };
 
 // The lists of criteria that enforce the sorting policies of the slices
-uint32_t  slice_sorting_policy[MAX_NUM_SLICES]         = {0x01234, 0x01234, 0x01234, 0x01234};
-uint32_t  slice_sorting_policy_current[MAX_NUM_SLICES] = {0x01234, 0x01234, 0x01234, 0x01234};
+uint32_t  slice_sorting[MAX_NUM_SLICES]         = {0x012345, 0x012345, 0x012345, 0x012345};
+uint32_t  slice_sorting_current[MAX_NUM_SLICES] = {0x012345, 0x012345, 0x012345, 0x012345};
 
 // Accounting policy (just greedy(1) or fair(0) setting for now)
-int       slice_accounting_policy[MAX_NUM_SLICES]         = {0, 0, 0, 0};
-int       slice_accounting_policy_current[MAX_NUM_SLICES] = {0, 0, 0, 0};
+int       slice_accounting[MAX_NUM_SLICES]         = {0, 0, 0, 0};
+int       slice_accounting_current[MAX_NUM_SLICES] = {0, 0, 0, 0};
 
 int       update_dl_scheduler[MAX_NUM_SLICES]         = { 1, 1, 1, 1 };
 int       update_dl_scheduler_current[MAX_NUM_SLICES] = { 1, 1, 1, 1 };
diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h
index 56bf7a25d42c6e72468d8011e0b6012f24905796..98b6c8fbe0d0008f5ea033255bff959ac21e008b 100644
--- a/openair2/LAYER2/MAC/mac_proto.h
+++ b/openair2/LAYER2/MAC/mac_proto.h
@@ -260,10 +260,16 @@ void dlsch_scheduler_pre_processor_intraslice_sharing(module_id_t Mod_id,
                                                       uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
                                                       uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]);
 
+void slice_priority_sort(int slice_list[MAX_NUM_SLICES]);
+
 void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id,
                                              int frameP,
                                              sub_frame_t subframeP);
 
+void dlsch_scheduler_qos_multiplexing(module_id_t Mod_id,
+                                      int frameP,
+                                      sub_frame_t subframeP);
+
 void dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id,
                                             int UE_id,
                                             uint8_t CC_id,
diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c
index 73f9724c8a800d6ad781bcf32b7d214fb338ee71..48987d785e3e69b897029a764e487868b4695322 100644
--- a/openair2/LAYER2/MAC/pre_processor.c
+++ b/openair2/LAYER2/MAC/pre_processor.c
@@ -57,8 +57,8 @@ extern RAN_CONTEXT_t RC;
 extern float    slice_percentage[MAX_NUM_SLICES];
 extern float    slice_percentage_uplink[MAX_NUM_SLICES];
 extern int      slice_position[MAX_NUM_SLICES*2];
-extern uint32_t slice_sorting_policy[MAX_NUM_SLICES];
-extern int      slice_accounting_policy[MAX_NUM_SLICES];
+extern uint32_t slice_sorting[MAX_NUM_SLICES];
+extern int      slice_accounting[MAX_NUM_SLICES];
 extern int      slice_maxmcs[MAX_NUM_SLICES];
 extern int      slice_maxmcs_uplink[MAX_NUM_SLICES];
 extern pre_processor_results_t pre_processor_results[MAX_NUM_SLICES];
@@ -315,6 +315,20 @@ int maxcqi(module_id_t Mod_id, int32_t UE_id) {
   return CQI;
 }
 
+long min_lcgidpriority(module_id_t Mod_id, int32_t UE_id) {
+  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
+  int i;
+  int pCC_id = UE_PCCID(Mod_id, UE_id);
+  long ret = UE_list->UE_template[pCC_id][UE_id].lcgidpriority[0];
+
+  for (i = 1; i < 11; ++i) {
+    if (UE_list->UE_template[pCC_id][UE_id].lcgidpriority[i] < ret)
+      ret = UE_list->UE_template[pCC_id][UE_id].lcgidpriority[i];
+  }
+
+  return ret;
+}
+
 struct sort_ue_dl_params {
     int Mod_idP;
     int frameP;
@@ -343,6 +357,9 @@ static int ue_dl_compare(const void *_a, const void *_b, void *_params)
   int cqi1 = maxcqi(params->Mod_idP, UE_id1);
   int cqi2 = maxcqi(params->Mod_idP, UE_id2);
 
+  long lcgid1 = min_lcgidpriority(params->Mod_idP, UE_id1);
+  long lcgid2 = min_lcgidpriority(params->Mod_idP, UE_id2);
+
   for (i = 0; i < CR_NUM; ++i) {
     switch (UE_list->sorting_criteria[slice_id][i]) {
 
@@ -390,6 +407,12 @@ static int ue_dl_compare(const void *_a, const void *_b, void *_params)
         if (cqi1 < cqi2)
           return 1;
 
+      case CR_LCP :
+        if (lcgid1 < lcgid2)
+          return -1;
+        if (lcgid1 > lcgid2)
+          return 1;
+
       default :
         break;
     }
@@ -402,7 +425,7 @@ void decode_sorting_policy(module_id_t Mod_idP, slice_id_t slice_id) {
   int i;
 
   UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list;
-  uint32_t policy = slice_sorting_policy[slice_id];
+  uint32_t policy = slice_sorting[slice_id];
   uint32_t mask = 0x0000000F;
   uint16_t criterion;
 
@@ -410,7 +433,7 @@ void decode_sorting_policy(module_id_t Mod_idP, slice_id_t slice_id) {
     criterion = (uint16_t) (policy >> 4 * (CR_NUM - 1 - i) & mask);
     if (criterion >= CR_NUM) {
       LOG_W(MAC, "Invalid criterion in slice %d policy, revert to default policy \n", slice_id);
-      slice_sorting_policy[slice_id] = 0x1234;
+      slice_sorting[slice_id] = 0x1234;
       break;
     }
     UE_list->sorting_criteria[slice_id][i] = criterion;
@@ -649,7 +672,7 @@ void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id,
   // Reduces the available RBs according to slicing configuration
   dlsch_scheduler_pre_processor_partitioning(Mod_id, slice_id, rbs_retx);
 
-  switch (slice_accounting_policy[slice_id]) {
+  switch (slice_accounting[slice_id]) {
 
     // If greedy scheduling, try to account all the required RBs
     case 1: