flexran_agent_scheduler_dlsch_ue_remote.c 6.73 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * 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
 */ 
21

22
/*! \file flexran_agent_scheduler_dlsch_ue_remote.c
23 24 25 26 27 28 29 30 31
 * \brief procedures related to remote scheduling in the DLSCH transport channel
 * \author Xenofon Foukas
 * \date 2016
 * \email: x.foukas@sms.ed.ac.uk
 * \version 0.1
 * @ingroup _mac

 */

32
#include "flexran_agent_common_internal.h"
33

34
#include "flexran_agent_scheduler_dlsch_ue_remote.h"
35

36 37 38
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"

39 40 41 42
struct DlMacConfigHead queue_head;

int queue_initialized = 0;

43 44 45 46
//uint32_t skip_subframe = 1;
//uint32_t period = 10;
//uint32_t sched [] = {1, 2, 3};

47 48
void flexran_schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, uint32_t subframe,
				     int *mbsfn_flag, Protocol__FlexranMessage **dl_info) {
49

50 51 52 53 54 55 56 57 58 59 60 61
  
  //if ((subframe == skip_subframe) && (frame % period == 0)) {
  //  LOG_I(MAC, "Will skip subframe %d %d\n", subframe, frame);
  //  for (int i = 0; i < 3; i++) {
  //    LOG_I(MAC, "%d\n", sched[i]);
  //  }
  //}

  /* if (frame == 500 && subframe == 1) { */
  /*   char policy[] = "rrc: \n - ul_scheduler: \n    behavior : tester_function\n    parameters:\n      period: !!int 3\nmac: \n - dl_scheduler: \n    parameters: \n      period : !!int 40\n      skip_subframe : !!int 3\n      sched : [!!int 4, !!int 5, !!int 6]"; */
  /*   apply_reconfiguration_policy(mod_id, policy, strlen(policy)); */
  /* } */
62 63 64

  eNB_MAC_INST *eNB;

65
  if (!queue_initialized) {
66 67 68
    TAILQ_INIT(&queue_head);
    queue_initialized = 1;
  }
69 70

  eNB = &eNB_mac_inst[mod_id]; 
71
  
72 73 74
  dl_mac_config_element_t *dl_config_elem;

  int diff;
75
  LOG_D(MAC, "[TEST] Current frame and subframe %d, %d\n", frame, subframe);
76 77 78
  // First we check to see if we have a scheduling decision for this sfn_sf already in our queue
  while(queue_head.tqh_first != NULL) {
    dl_config_elem = queue_head.tqh_first;
79
  
80 81 82
    diff = get_sf_difference(mod_id, dl_config_elem->dl_info->dl_mac_config_msg->sfn_sf);
    // Check if this decision is for now, for a later or a previous subframe
    if ( diff == 0) { // Now
83
      LOG_D(MAC, "Found a decision for this subframe in the queue. Let's use it!\n");
84 85 86
      TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs);
      *dl_info = dl_config_elem->dl_info;
      free(dl_config_elem);
87
      eNB->eNB_stats[mod_id].sched_decisions++;
88 89
      return;
    } else if (diff < 0) { //previous subframe , delete message and free memory
90
      LOG_D(MAC, "Found a decision for a previous subframe in the queue. Let's get rid of it\n");
91
      TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs);
92
      flexran_agent_mac_destroy_dl_config(dl_config_elem->dl_info);
93
      free(dl_config_elem);
94 95
      eNB->eNB_stats[mod_id].sched_decisions++;
      eNB->eNB_stats[mod_id].missed_deadlines++;
96
    } else { // next subframe, nothing to do now
97
      LOG_D(MAC, "Found a decision for a future subframe in the queue. Nothing to do now\n");
98
      flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
99 100 101 102 103
      return;
    }
  }

  //Done with the local cache. Now we need to check if something new arrived
104
  flexran_agent_get_pending_dl_mac_config(mod_id, dl_info);
105 106 107 108
  while (*dl_info != NULL) {

    diff = get_sf_difference(mod_id, (*dl_info)->dl_mac_config_msg->sfn_sf);
    if (diff == 0) { // Got a command for this sfn_sf
109
      LOG_D(MAC, "Found a decision for this subframe pending. Let's use it\n");
110
      eNB->eNB_stats[mod_id].sched_decisions++;
111 112
      return;
    } else if (diff < 0) {
113
      LOG_D(MAC, "Found a decision for a previous subframe. Let's get rid of it\n");
114
      flexran_agent_mac_destroy_dl_config(*dl_info);
115
      *dl_info = NULL;
116
      flexran_agent_get_pending_dl_mac_config(mod_id, dl_info);
117 118
      eNB->eNB_stats[mod_id].sched_decisions++;
      eNB->eNB_stats[mod_id].missed_deadlines++;
119
    } else { // Intended for future subframe. Store it in local cache
120
      LOG_D(MAC, "Found a decision for a future subframe in the queue. Let's store it in the cache\n");
121
      dl_mac_config_element_t *e = malloc(sizeof(dl_mac_config_element_t));
122
      e->dl_info = *dl_info;
123
      TAILQ_INSERT_TAIL(&queue_head, e, configs);
124
      flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
125 126 127 128 129 130
      // No need to look for another. Messages arrive ordered
      return;
    }
  }
  
  // We found no pending command, so we will simply pass an empty one
131
  flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
132 133
}

134
int get_sf_difference(mid_t mod_id, uint32_t sfn_sf) {
135 136
  int diff_in_subframes;
  
137 138 139
  uint16_t current_frame = flexran_get_current_system_frame_num(mod_id);
  uint16_t current_subframe = flexran_get_current_subframe(mod_id);
  uint32_t current_sfn_sf = flexran_get_sfn_sf(mod_id);
140 141 142 143 144
  
  if (sfn_sf == current_sfn_sf) {
    return 0;
  }
  
145 146
  uint16_t frame_mask = ((1<<12) - 1);
  uint16_t frame = (sfn_sf & (frame_mask << 4)) >> 4;
147
  
148
  uint16_t sf_mask = ((1<<4) - 1);
149
  uint16_t subframe = (sfn_sf & sf_mask);
150

151
 LOG_D(MAC, "[TEST] Target frame and subframe %d, %d\n", frame, subframe);
152 153 154 155
  
  if (frame == current_frame) {
    return subframe - current_subframe;
  } else if (frame > current_frame) {
156 157 158 159 160
    diff_in_subframes = ((frame*10)+subframe) - ((current_frame*10)+current_subframe);
    
    //    diff_in_subframes = 9 - current_subframe;
    //diff_in_subframes += (subframe + 1);
    //diff_in_subframes += (frame-2) * 10;
161 162 163 164 165 166
    if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) {
      return -1;
    } else {
      return 1;
    }
  } else { //frame < current_frame
167 168 169 170 171 172 173
    //diff_in_subframes = 9 - current_subframe;
    //diff_in_subframes += (subframe + 1);
    //if (frame > 0) {
    //  diff_in_subframes += (frame - 1) * 10;
    //}
    //diff_in_subframes += (1023 - current_frame) * 10;
    diff_in_subframes = 10240 - ((current_frame*10)+current_subframe) + ((frame*10)+subframe);
174 175 176 177 178 179 180
    if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) {
      return -1;
    } else {
      return 1;
    }
  }
}