From 08b6211956680d58de451737b096a69a4aac06b6 Mon Sep 17 00:00:00 2001
From: cig <guido.casati@iis.fraunhofer.de>
Date: Mon, 4 May 2020 17:16:18 +0200
Subject: [PATCH] Scheduling of Msg2

---
 openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c |  74 ++++++++++++-
 openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h |   4 +
 openair2/LAYER2/NR_MAC_UE/mac_defs.h          |   4 +
 openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c  | 100 +++++++++++++++++-
 openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c |   2 +-
 .../NR_MAC_gNB/gNB_scheduler_primitives.c     |  75 -------------
 openair2/LAYER2/NR_MAC_gNB/mac_proto.h        |   4 -
 openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c   |  10 +-
 8 files changed, 189 insertions(+), 84 deletions(-)

diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
index baab2f5809e..95690e19e3a 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
@@ -47,6 +47,8 @@ uint16_t NCS_unrestricted_delta_f_RA_15[16] = {0,2,4,6,8,10,12,13,15,17,19,23,27
 
 const char *prachfmt[]={"A1","A2","A3","B1","B2","B3","B4","C0","C2"};
 
+const uint16_t nr_slots_per_frame[5] = {10, 20, 40, 80, 160};
+
 uint16_t get_NCS(uint8_t index, uint16_t format0, uint8_t restricted_set_config) {
 
   if (format0 < 3) {
@@ -876,7 +878,77 @@ int get_format0(uint8_t index,
 
   return format;
 }
-                
+
+void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss,
+                                               uint16_t *slot_period,
+                                               uint16_t *offset) {
+
+  switch(ss->monitoringSlotPeriodicityAndOffset->present) {
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1:
+      *slot_period = 1;
+      *offset = 0;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2:
+      *slot_period = 2;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4:
+      *slot_period = 4;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl4;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5:
+      *slot_period = 5;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl5;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8:
+      *slot_period = 8;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl8;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10:
+      *slot_period = 10;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl10;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16:
+      *slot_period = 16;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl16;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20:
+      *slot_period = 20;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl20;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40:
+      *slot_period = 40;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl40;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80:
+      *slot_period = 80;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl80;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160:
+      *slot_period = 160;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl160;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320:
+      *slot_period = 320;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl320;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640:
+      *slot_period = 640;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl640;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280:
+      *slot_period = 1280;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl1280;
+      break;
+    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560:
+      *slot_period = 2560;
+      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2560;
+      break;
+  default:
+    AssertFatal(1==0,"Invalid monitoring slot periodicity and offset value\n");
+    break;
+  }
+}
 
 int get_nr_prach_info_from_index(uint8_t index,
                                  int frame,
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
index a3114886ba5..8f5ee851605 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
@@ -78,6 +78,10 @@ int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP);
 
 uint16_t nr_dci_size(nr_dci_format_t format, nr_rnti_type_t rnti_type, uint16_t N_RB);
 
+void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss,
+                                               uint16_t *slot_period,
+                                               uint16_t *offset);
+
 int get_nr_prach_info_from_index(uint8_t index,
                                  int frame,
                                  int slot,
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index 8da2d29d752..368eae96824 100755
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -220,6 +220,10 @@ typedef struct {
   uint32_t RA_tx_frame;
   /// Random-access variable for window calculation (subframe of last change in window counter)
   uint8_t RA_tx_subframe;
+  /// Scheduled RX frame for RA Msg2
+  uint16_t msg2_rx_frame;
+  /// Scheduled RX slot for RA Msg2
+  uint16_t msg2_rx_slot;
   /// Random-access Group B maximum path-loss
   /// Random-access variable for backoff (frame of last change in backoff counter)
   uint32_t RA_backoff_frame;
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 50ea64c7243..c33a469a84d 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -42,6 +42,7 @@
 #include "NR_RACH-ConfigCommon.h"
 #include "NR_RACH-ConfigGeneric.h"
 #include "NR_FrequencyInfoDL.h"
+#include "NR_PDCCH-ConfigCommon.h"
 
 /* MAC */
 #include "mac_defs.h"
@@ -73,6 +74,8 @@
 //#define ENABLE_MAC_PAYLOAD_DEBUG 1
 #define DEBUG_EXTRACT_DCI 1
 
+extern const uint16_t nr_slots_per_frame[5];
+
 extern void mac_rlc_data_ind     (
 				  const module_id_t         module_idP,
 				  const rnti_t              rntiP,
@@ -720,8 +723,6 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
       // get Coreset and SearchSpace Information from spCellConfigDedicated
       // DCI configuration done for BWP 1, Coreset 0, SearchSpace 0
 
-      // TBR first thing to do : schedule msg2 
-
       // TBR program DCI for slot 1 if PDSCH
       // TBR program DCI for slot 7 if RAR DCI PDSCH
 
@@ -769,6 +770,101 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
   return UE_CONNECTION_OK;
 }
 
+// Note: msg2 is scheduled in the mixed slot or in the last dl slot
+// if they are allowed by search space configuration
+void nr_ue_msg2_scheduler(module_id_t mod_id,
+                          uint16_t rach_frame,
+                          uint16_t rach_slot,
+                          uint16_t *msg2_frame,
+                          uint16_t *msg2_slot){
+
+  uint8_t bwp_id = 1;
+  NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
+  NR_ServingCellConfig_t *scd = mac->scd;
+  NR_ServingCellConfigCommon_t *scc = mac->scc;
+  NR_BWP_Downlink_t *bwp = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1];
+  NR_SearchSpace_t *ss;
+  struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
+  uint8_t mu = *scc->ssbSubcarrierSpacing;
+  uint8_t response_window = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow;
+  uint8_t slot_window, slot_limit, frame_limit;
+  uint16_t start_next_period, monitoring_slot_period, monitoring_offset;
+
+  // number of mixed slot or of last dl slot if there is no mixed slot
+  uint16_t last_dl_slot_period = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
+  uint16_t nr_dl_symbols = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols;
+  uint16_t nr_ul_symbols = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols;
+
+  // lenght of tdd period in slots
+  uint16_t tdd_period_slot = last_dl_slot_period + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
+
+  AssertFatal(commonSearchSpaceList->list.count > 0, "PDCCH common SearchSpace list has 0 elements\n");
+  
+  LOG_D(MAC, "Frame %d, Slot %d: Scheduling Msg2 reception \n", rach_frame, rach_slot);
+
+  // Common searchspace list
+  for (int i = 0; i < commonSearchSpaceList->list.count; i++) {
+    ss = commonSearchSpaceList->list.array[i];
+    if(ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace)
+    // retrieving ra pdcch monitoring period and offset
+    find_monitoring_periodicity_offset_common(ss, &monitoring_slot_period, &monitoring_offset);
+  }
+
+  if (nr_dl_symbols == 0)
+    last_dl_slot_period--;
+  if ((nr_dl_symbols > 0) || (nr_ul_symbols > 0))
+    tdd_period_slot++;
+
+  // computing start of next period
+  start_next_period = (rach_slot - (rach_slot % tdd_period_slot) + tdd_period_slot) % nr_slots_per_frame[mu];
+  *msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot
+  *msg2_frame = (*msg2_slot > rach_slot) ? rach_frame : (rach_frame +1);
+
+  switch(response_window){
+  case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
+    slot_window = 1;
+    break;
+  case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2:
+    slot_window = 2;
+    break;
+  case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4:
+    slot_window = 4;
+    break;
+  case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8:
+    slot_window = 8;
+    break;
+  case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10:
+    slot_window = 10;
+    break;
+  case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20:
+    slot_window = 20;
+    break;
+  case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40:
+    slot_window = 40;
+    break;
+  case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80:
+    slot_window = 80;
+    break;
+  default:
+    AssertFatal(1==0,"Invalid response window value %d\n",response_window);
+  }
+  AssertFatal(slot_window<=nr_slots_per_frame[mu], "Msg2 response window needs to be lower or equal to 10ms");
+
+  // slot and frame limit to transmit msg2 according to response window
+  slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu];
+  frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1);
+
+  // go to previous slot if the current scheduled slot is beyond the response window
+  // and if the slot is not among the PDCCH monitored ones (38.213 10.1)
+  while ((*msg2_slot > slot_limit) || ((*msg2_frame*nr_slots_per_frame[mu] + *msg2_slot - monitoring_offset) % monitoring_slot_period != 0))  {
+    if((*msg2_slot % tdd_period_slot) > 0)
+      *msg2_slot--;
+    else
+      AssertFatal(1 == 0, "No available DL slot to schedule reception of msg2 has been found");
+  }
+  LOG_D(MAC, "Scheduled Msg2 reception in Frame %d, Slot %d:  \n", *msg2_frame, *msg2_slot);
+}
+
 // This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x
 // It fills the PRACH PDU per each FD occasion.
 // PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3.
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
index 56c3d272100..719571e29c4 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
@@ -42,7 +42,7 @@
 #include "SIMULATION/TOOLS/sim.h" // for taus
 
 extern RAN_CONTEXT_t RC;
-uint16_t nr_slots_per_frame[5] = {10, 20, 40, 80, 160};
+extern const uint16_t nr_slots_per_frame[5];
 uint8_t DELTA[4]= {2,3,4,6};
 
 void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) {
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
index 5575f05e1f2..fb0a53b4cea 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
@@ -998,81 +998,6 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){
   return -1;
 }
 
-
-void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss,
-                                               uint16_t *slot_period,
-                                               uint16_t *offset) {
-
-
-  switch(ss->monitoringSlotPeriodicityAndOffset->present) {
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1:
-      *slot_period = 1;
-      *offset = 0;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2:
-      *slot_period = 2;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4:
-      *slot_period = 4;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl4;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5:
-      *slot_period = 5;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl5;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8:
-      *slot_period = 8;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl8;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10:
-      *slot_period = 10;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl10;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16:
-      *slot_period = 16;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl16;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20:
-      *slot_period = 20;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl20;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40:
-      *slot_period = 40;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl40;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80:
-      *slot_period = 80;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl80;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160:
-      *slot_period = 160;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl160;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320:
-      *slot_period = 320;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl320;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640:
-      *slot_period = 640;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl640;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280:
-      *slot_period = 1280;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl1280;
-      break;
-    case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560:
-      *slot_period = 2560;
-      *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2560;
-      break;
-  default:
-    AssertFatal(1==0,"Invalid monitoring slot periodicity and offset value\n");
-    break;
-  }
-}
-
-
-
 /*void fill_nfapi_coresets_and_searchspaces(NR_CellGroupConfig_t *cg,
 					  nfapi_nr_coreset_t *coreset,
 					  nfapi_nr_search_space_t *search_space) {
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index e3ce305180c..37f06e143a8 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -245,10 +245,6 @@ void nr_schedule_reception_msg3(module_id_t module_idP, int CC_id, frame_t frame
 
 int find_aggregation_level (NR_SearchSpace_t *ss);
 
-void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss,
-                                               uint16_t *slot_period,
-                                               uint16_t *offset);
-
 void nr_process_mac_pdu(
     module_id_t module_idP,
     uint8_t CC_id,
diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
index 4cda82366c7..3fba88c9841 100644
--- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
+++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
@@ -115,8 +115,16 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){
 
   ret = nr_ue_scheduler(NULL, ul_info);
 
-  if (is_nr_UL_slot(mac->scc, ul_info->slot_tx) && mac->ra_state <= WAIT_RAR && get_softmodem_params()->do_ra)
+  if (is_nr_UL_slot(mac->scc, ul_info->slot_tx) && mac->ra_state == RA_UE_IDLE && get_softmodem_params()->do_ra){
     nr_ue_prach_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx);
+    if (mac->generate_nr_prach){
+      uint16_t monitoring_slot_period, monitoring_offset;
+      uint16_t rach_frame = mac->scheduled_response.ul_config->sfn;
+      uint16_t rx_rach_frame = (rach_frame + 2) % MAX_FRAME_NUMBER; // compensate 2 frames offset delay at gNB side
+      uint16_t rach_slot  = mac->scheduled_response.ul_config->slot;
+      nr_ue_msg2_scheduler(module_id, rx_rach_frame, rach_slot, &mac->msg2_rx_frame, &mac->msg2_rx_slot);
+    }
+  }
 
   switch(ret){
   case UE_CONNECTION_OK:
-- 
GitLab