main.c 11 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * 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
 */

22
/*! \file main.c
23
 * \brief top init of Layer 2
24
 * \author  Navid Nikaein and Raymond Knopp
25
 * \date 2010 - 2014
26
 * \version 1.0
27 28
 * \email: navid.nikaein@eurecom.fr
 * @ingroup _mac
29

30
 */
31

32
#include <dlfcn.h>
33 34 35
#include "mac.h"
#include "mac_proto.h"
#include "mac_extern.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
36
#include "assertions.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
37
#include "LAYER2/PDCP_v10.1.0/pdcp.h"
38
#include "RRC/LTE/rrc_defs.h"
39
#include "common/utils/LOG/log.h"
40
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
41
#include "common/ran_context.h"
42
#include "intertask_interface.h"
43
#include <pthread.h>
44 45

extern RAN_CONTEXT_t RC;
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
extern int oai_exit;

void *mac_stats_thread(void *param) {
  eNB_MAC_INST     *mac      = (eNB_MAC_INST *)param;
  FILE *fd;
  UE_info_t        *UE_info  = &(mac->UE_info);

  while (!oai_exit) {
    sleep(1);
    fd=fopen("MAC_stats.log","w+");
    AssertFatal(fd!=NULL,"Cannot open MAC_stats.log\n");

    for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
      if (UE_info->active[UE_id]) {
        int rnti = UE_RNTI(mac->Mod_id, UE_id);
        int CC_id = UE_PCCID(mac->Mod_id, UE_id);
        UE_sched_ctrl_t *UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]);

64 65 66 67 68 69 70
        double total_bler;
        if(UE_scheduling_control->pusch_rx_num[CC_id] == 0 && UE_scheduling_control->pusch_rx_error_num[CC_id] == 0) {
          total_bler = 0;
        }
        else {
          total_bler = (double)UE_scheduling_control->pusch_rx_error_num[CC_id] / (double)(UE_scheduling_control->pusch_rx_error_num[CC_id] + UE_scheduling_control->pusch_rx_num[CC_id]) * 100;
        }
71
        fprintf(fd,"MAC UE rnti %x : %s, PHR %d DLCQI %d PUSCH %d PUCCH %d RLC disc %d UL-stat rcv %lu err %lu bler %lf (%lf/%lf) total_bler %lf mcsoff %d pre_allocated nb_rb %d, mcs %d, bsr %u sched %u tbs %lu cnt %u , DL-stat tbs %lu cnt %u rb %u buf %u 1st %u ret %u ri %d\n",
72 73 74 75
              rnti,
              UE_scheduling_control->ul_out_of_sync == 0 ? "in synch" : "out of sync",
              UE_info->UE_template[CC_id][UE_id].phr_info,
              UE_scheduling_control->dl_cqi[CC_id],
76 77 78 79 80
              UE_scheduling_control->pusch_snr/*_avg*/[CC_id],
              UE_scheduling_control->pucch1_snr[CC_id],
              UE_scheduling_control->rlc_out_of_resources_cnt,
              UE_scheduling_control->pusch_rx_num[CC_id],
              UE_scheduling_control->pusch_rx_error_num[CC_id],
81 82
              UE_scheduling_control->pusch_bler[CC_id],
              mac->bler_lower,mac->bler_upper,total_bler,
83
              UE_scheduling_control->mcs_offset[CC_id],
84 85
              UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul,
              UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul,
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
              UE_info->UE_template[CC_id][UE_id].estimated_ul_buffer,
              UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes,
              UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx,
              UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus_rx,
              UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes,
              UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus,
              UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used,
#if defined(PRE_SCD_THREAD)
              UE_info->UE_template[CC_id][UE_id].dl_buffer_total,
#else
              0,
#endif
              UE_scheduling_control->first_cnt[CC_id],
              UE_scheduling_control->ret_cnt[CC_id],
              UE_scheduling_control->aperiodic_ri_received[CC_id]
        );
        fprintf(fd,"              ULSCH rounds %d/%d/%d/%d, DLSCH rounds %d/%d/%d/%d, ULSCH errors %d, DLSCH errors %d\n",
103 104 105 106 107 108 109 110 111 112
              UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_rounds[0],
              UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_rounds[1],
              UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_rounds[2],
              UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_rounds[3],
              UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_rounds[0],
              UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_rounds[1],
              UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_rounds[2],
              UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_rounds[3],
              UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_errors,
              UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_errors);
113 114


115 116 117 118 119 120
      }
    }
    fclose(fd);
  }
  return(NULL);
}
121

122
void init_UE_info(UE_info_t *UE_info)
123
{
124
  UE_info->num_UEs = 0;
125
  init_ue_list(&UE_info->list);
126 127 128 129 130
  memset(UE_info->DLSCH_pdu, 0, sizeof(UE_info->DLSCH_pdu));
  memset(UE_info->UE_template, 0, sizeof(UE_info->UE_template));
  memset(UE_info->eNB_UE_stats, 0, sizeof(UE_info->eNB_UE_stats));
  memset(UE_info->UE_sched_ctrl, 0, sizeof(UE_info->UE_sched_ctrl));
  memset(UE_info->active, 0, sizeof(UE_info->active));
131 132
}

133
void mac_top_init_eNB(void)
134
{
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
  module_id_t i, j;
  eNB_MAC_INST **mac;

  LOG_I(MAC, "[MAIN] Init function start:nb_macrlc_inst=%d\n",
        RC.nb_macrlc_inst);

  if (RC.nb_macrlc_inst <= 0) {
    RC.mac = NULL;
    return;
  }

  mac = malloc16(RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *));
  AssertFatal(mac != NULL,
              "can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n",
              RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *),
              RC.nb_macrlc_inst, sizeof(eNB_MAC_INST));
  for (i = 0; i < RC.nb_macrlc_inst; i++) {
    mac[i] = malloc16(sizeof(eNB_MAC_INST));
    AssertFatal(mac[i] != NULL,
                "can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n",
                RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *),
                RC.nb_macrlc_inst, sizeof(eNB_MAC_INST));
    LOG_D(MAC,
          "[MAIN] ALLOCATE %zu Bytes for %d eNB_MAC_INST @ %p\n",
          sizeof(eNB_MAC_INST), RC.nb_macrlc_inst, mac);
    bzero(mac[i], sizeof(eNB_MAC_INST));
    mac[i]->Mod_id = i;
    for (j = 0; j < MAX_NUM_CCs; j++) {
      mac[i]->DL_req[j].dl_config_request_body.dl_config_pdu_list =
          mac[i]->dl_config_pdu_list[j];
      mac[i]->UL_req[j].ul_config_request_body.ul_config_pdu_list =
          mac[i]->ul_config_pdu_list[j];
      for (int k = 0; k < 10; k++)
        mac[i]->UL_req_tmp[j][k].ul_config_request_body.ul_config_pdu_list =
            mac[i]->ul_config_pdu_list_tmp[j][k];
      for(int sf=0;sf<10;sf++)
        mac[i]->HI_DCI0_req[j][sf].hi_dci0_request_body.hi_dci0_pdu_list =
            mac[i]->hi_dci0_pdu_list[j][sf];
      mac[i]->TX_req[j].tx_request_body.tx_pdu_list = mac[i]->tx_request_pdu[j];
      mac[i]->ul_handle = 0;
175
    }
176

177
    mac[i]->if_inst = IF_Module_init(i);
178

179
    mac[i]->pre_processor_dl.algorithm = 0;
180
    mac[i]->pre_processor_dl.dl = dlsch_scheduler_pre_processor;
181 182 183
    char *s = "round_robin_dl";
    void *d = dlsym(NULL, s);
    AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s);
184 185 186
    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();

187
    mac[i]->pre_processor_ul.algorithm = 0;
188
    mac[i]->pre_processor_ul.ul = ulsch_scheduler_pre_processor;
189 190 191
    s = "round_robin_ul";
    d = dlsym(NULL, s);
    AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s);
192 193 194
    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();

195
    init_UE_info(&mac[i]->UE_info);
196 197 198 199
  }

  RC.mac = mac;

Cedric Roux's avatar
Cedric Roux committed
200
  AssertFatal(rlc_module_init(1) == 0,
201 202 203 204 205 206
      "Could not initialize RLC layer\n");

  // These should be out of here later
  pdcp_layer_init();

  rrc_init_global_param();
207 208 209

  for (i=0;i<RC.nb_macrlc_inst; i++) pthread_create(&mac[i]->mac_stats_thread,NULL,mac_stats_thread,(void*)mac[i]);

210
}
211

212 213
void mac_init_cell_params(int Mod_idP, int CC_idP)
{
214

215 216
    int j;
    UE_TEMPLATE *UE_template;
217

218
    LOG_D(MAC, "[MSC_NEW][FRAME 00000][MAC_eNB][MOD %02d][]\n", Mod_idP);
219
    //COMMON_channels_t *cc = &RC.mac[Mod_idP]->common_channels[CC_idP];
220

221 222
    memset(&RC.mac[Mod_idP]->eNB_stats, 0, sizeof(eNB_STATS));
    UE_template =
223
	(UE_TEMPLATE *) & RC.mac[Mod_idP]->UE_info.UE_template[CC_idP][0];
224

225
    for (j = 0; j < MAX_MOBILES_PER_ENB; j++) {
226 227
	UE_template[j].rnti = 0;
	// initiallize the eNB to UE statistics
228
	memset(&RC.mac[Mod_idP]->UE_info.eNB_UE_stats[CC_idP][j], 0,
229
	       sizeof(eNB_UE_STATS));
230 231 232 233 234 235
    }

}


int rlcmac_init_global_param(void)
236
{
237

238

239
    LOG_I(MAC, "[MAIN] CALLING RLC_MODULE_INIT...\n");
240

Cedric Roux's avatar
Cedric Roux committed
241
    if (rlc_module_init(1) != 0) {
242 243
	return (-1);
    }
244

245
    pdcp_layer_init();
246

247
    LOG_I(MAC, "[MAIN] Init Global Param Done\n");
248

249
    return 0;
250 251 252
}


253 254
void mac_top_cleanup(void)
{
255

256 257 258
    if (NB_UE_INST > 0) {
	free(UE_mac_inst);
    }
259

260 261 262
    if (RC.nb_macrlc_inst > 0) {
	free(RC.mac);
    }
263

264 265
}

266
int l2_init_eNB(void)
267
{
268 269 270



271
    LOG_I(MAC, "[MAIN] MAC_INIT_GLOBAL_PARAM IN...\n");
272

273
    rlcmac_init_global_param();
274

275
    LOG_D(MAC, "[MAIN] ALL INIT OK\n");
276 277


278
    return (1);
279
}
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300

//-----------------------------------------------------------------------------
/*
 * Main loop of MAC itti message handling
 */
void *mac_enb_task(void *arg)
//-----------------------------------------------------------------------------
{
  MessageDef *received_msg = NULL;
  int         result;

  itti_mark_task_ready(TASK_MAC_ENB); // void function 10/2019
  LOG_I(MAC,"Starting main loop of MAC message task\n");

  while (1) {
    itti_receive_msg(TASK_MAC_ENB, &received_msg);

    switch (ITTI_MSG_ID(received_msg)) {
      case RRC_MAC_DRX_CONFIG_REQ:
        LOG_I(MAC, "MAC Task Received RRC_MAC_DRX_CONFIG_REQ\n");
        /* Set timers and thresholds values in local MAC context of UE */
301
        eNB_Config_Local_DRX(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.rrc_mac_drx_config_req);
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
        break;

      case TERMINATE_MESSAGE:
        LOG_W(MAC, " *** Exiting MAC thread\n");
        itti_exit_task();
        break;

      default:
        LOG_E(MAC, "MAC instance received unhandled message: %d:%s\n",
              ITTI_MSG_ID(received_msg), 
              ITTI_MSG_NAME(received_msg));
        break;  
    } // end switch

    result = itti_free(ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
    AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
    
    received_msg = NULL;
  } // end while

  return NULL;
323
}