flexran_agent_common.c 75.4 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_common.c
23
 * \brief common primitives for all agents 
24
 * \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
25 26 27 28
 * \date 2016
 * \version 0.1
 */

29 30
#include<stdio.h>
#include <time.h>
31

32 33 34
#include "flexran_agent_common.h"
#include "flexran_agent_common_internal.h"
#include "flexran_agent_extern.h"
35
#include "flexran_agent_net_comm.h"
MKassem's avatar
MKassem committed
36
#include "PHY/extern.h"
37 38
#include "log.h"

39
#include "SCHED/defs.h"
40 41
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
42
#include "rrc_eNB_UE_context.h"
43

44 45
void * enb[NUM_MAX_ENB];
void * enb_ue[NUM_MAX_ENB];
MKassem's avatar
MKassem committed
46
void * enb_rrc[NUM_MAX_ENB];
47

48 49 50 51
/*
 * message primitives
 */

52
int flexran_agent_serialize_message(Protocol__FlexranMessage *msg, void **buf, int *size) {
53

54
  *size = protocol__flexran_message__get_packed_size(msg);
55 56 57 58 59
  
  *buf = malloc(*size);
  if (buf == NULL)
    goto error;
  
60
  protocol__flexran_message__pack(msg, *buf);
61 62 63 64
  
  return 0;
  
 error:
65
  LOG_E(FLEXRAN_AGENT, "an error occured\n"); // change the com
66 67 68 69 70 71 72
  return -1;
}



/* We assume that the buffer size is equal to the message size.
   Should be chekced durint Tx/Rx */
73
int flexran_agent_deserialize_message(void *data, int size, Protocol__FlexranMessage **msg) {
74
  *msg = protocol__flexran_message__unpack(NULL, size, data);
75 76
  if (*msg == NULL)
    goto error;
77

78 79 80 81 82 83 84 85 86
  return 0;
  
 error:
  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
  return -1;
}



87
int flexran_create_header(xid_t xid, Protocol__FlexType type,  Protocol__FlexHeader **header) {
88
  
89
  *header = malloc(sizeof(Protocol__FlexHeader));
90 91 92
  if(*header == NULL)
    goto error;
  
93 94
  protocol__flex_header__init(*header);
  (*header)->version = FLEXRAN_VERSION;
95 96 97 98 99 100 101 102 103
  (*header)->has_version = 1; 
  // check if the type is set
  (*header)->type = type;
  (*header)->has_type = 1;
  (*header)->xid = xid;
  (*header)->has_xid = 1;
  return 0;

 error:
104
  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
105 106 107 108
  return -1;
}


109
int flexran_agent_hello(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
110
 
111
  Protocol__FlexHeader *header;
112 113
  /*TODO: Need to set random xid or xid from received hello message*/
  xid_t xid = 1;
114

115 116
  Protocol__FlexHello *hello_msg;
  hello_msg = malloc(sizeof(Protocol__FlexHello));
117 118
  if(hello_msg == NULL)
    goto error;
119
  protocol__flex_hello__init(hello_msg);
120 121 122 123

  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_HELLO, &header) != 0)
    goto error;

124 125
  hello_msg->header = header;

126
  *msg = malloc(sizeof(Protocol__FlexranMessage));
127 128 129
  if(*msg == NULL)
    goto error;
  
130 131 132
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_HELLO_MSG;
  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
133
  (*msg)->has_msg_dir = 1;
134 135 136 137 138 139 140 141 142 143
  (*msg)->hello_msg = hello_msg;
  return 0;
  
 error:
  if(header != NULL)
    free(header);
  if(hello_msg != NULL)
    free(hello_msg);
  if(*msg != NULL)
    free(*msg);
144
  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
145 146 147 148
  return -1;
}


149
int flexran_agent_destroy_hello(Protocol__FlexranMessage *msg) {
150
  
151
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_HELLO_MSG)
152 153 154 155 156 157 158 159
    goto error;
  
  free(msg->hello_msg->header);
  free(msg->hello_msg);
  free(msg);
  return 0;

 error:
160
  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
161 162 163 164
  return -1;
}


165
int flexran_agent_echo_request(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg) {
166
  Protocol__FlexHeader *header;
167 168
  /*TODO: Need to set a random xid*/
  xid_t xid = 1;
169

170
  Protocol__FlexEchoRequest *echo_request_msg = NULL;
171
  echo_request_msg = malloc(sizeof(Protocol__FlexEchoRequest));
172 173
  if(echo_request_msg == NULL)
    goto error;
174
  protocol__flex_echo_request__init(echo_request_msg);
175 176 177 178

  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_ECHO_REQUEST, &header) != 0)
    goto error;

179 180
  echo_request_msg->header = header;

181
  *msg = malloc(sizeof(Protocol__FlexranMessage));
182 183
  if(*msg == NULL)
    goto error;
184 185 186
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REQUEST_MSG;
  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
  (*msg)->echo_request_msg = echo_request_msg;
  return 0;

 error:
  if(header != NULL)
    free(header);
  if(echo_request_msg != NULL)
    free(echo_request_msg);
  if(*msg != NULL)
    free(*msg);
  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
  return -1;
}


202
int flexran_agent_destroy_echo_request(Protocol__FlexranMessage *msg) {
203
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REQUEST_MSG)
204 205 206 207 208 209 210 211
    goto error;
  
  free(msg->echo_request_msg->header);
  free(msg->echo_request_msg);
  free(msg);
  return 0;
  
 error:
212
  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
213 214 215 216 217
  return -1;
}



218
int flexran_agent_echo_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
219 220
  
  xid_t xid;
221 222
  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
  Protocol__FlexEchoRequest *echo_req = input->echo_request_msg;
223 224
  xid = (echo_req->header)->xid;

225
  Protocol__FlexEchoReply *echo_reply_msg = NULL;
226
  echo_reply_msg = malloc(sizeof(Protocol__FlexEchoReply));
227 228
  if(echo_reply_msg == NULL)
    goto error;
229
  protocol__flex_echo_reply__init(echo_reply_msg);
230 231 232 233 234

  Protocol__FlexHeader *header;
  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_ECHO_REPLY, &header) != 0)
    goto error;

235 236
  echo_reply_msg->header = header;

237
  *msg = malloc(sizeof(Protocol__FlexranMessage));
238 239
  if(*msg == NULL)
    goto error;
240 241 242
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REPLY_MSG;
  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
243
  (*msg)->has_msg_dir = 1;
244 245 246 247 248 249 250 251 252 253
  (*msg)->echo_reply_msg = echo_reply_msg;
  return 0;

 error:
  if(header != NULL)
    free(header);
  if(echo_reply_msg != NULL)
    free(echo_reply_msg);
  if(*msg != NULL)
    free(*msg);
254
  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
255 256 257 258
  return -1;
}


259
int flexran_agent_destroy_echo_reply(Protocol__FlexranMessage *msg) {
260
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REPLY_MSG)
261 262 263 264 265 266 267 268
    goto error;
  
  free(msg->echo_reply_msg->header);
  free(msg->echo_reply_msg);
  free(msg);
  return 0;
  
 error:
269
  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
270 271
  return -1;
}
272

273

274
int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
275
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG)
276 277 278
    goto error;
  free(msg->enb_config_reply_msg->header);
  int i, j;
279
  Protocol__FlexEnbConfigReply *reply = msg->enb_config_reply_msg;
280
  
281
  for(i = 0; i < reply->n_cell_config;i++) {
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
    free(reply->cell_config[i]->mbsfn_subframe_config_rfoffset);
    free(reply->cell_config[i]->mbsfn_subframe_config_rfperiod);
    free(reply->cell_config[i]->mbsfn_subframe_config_sfalloc);
    if (reply->cell_config[i]->si_config != NULL) {
      for(j = 0; j < reply->cell_config[i]->si_config->n_si_message;j++){
	free(reply->cell_config[i]->si_config->si_message[j]);
      }
      free(reply->cell_config[i]->si_config->si_message);
      free(reply->cell_config[i]->si_config);
    }
    free(reply->cell_config[i]);
  }
  free(reply->cell_config);
  free(reply);
  free(msg);
  
  return 0;
 error:
300
  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
301
  return -1;
302 303
}

304
int flexran_agent_destroy_ue_config_reply(Protocol__FlexranMessage *msg) {
305
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG)
306 307
    goto error;
  free(msg->ue_config_reply_msg->header);
308
  int i;
309
  Protocol__FlexUeConfigReply *reply = msg->ue_config_reply_msg;
310 311 312 313 314 315 316 317 318
  
  for(i = 0; i < reply->n_ue_config;i++){
    free(reply->ue_config[i]->capabilities);
    free(reply->ue_config[i]);
  }
  free(reply->ue_config);
  free(reply);
  free(msg);

319
  return 0;
320
 error:
321
  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
322
  return -1;
323 324
}

325
int flexran_agent_destroy_lc_config_reply(Protocol__FlexranMessage *msg) {
326
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REPLY_MSG)
327 328 329 330 331 332 333 334 335 336 337 338 339 340
    goto error;

  int i, j;
  free(msg->lc_config_reply_msg->header);
  for (i = 0; i < msg->lc_config_reply_msg->n_lc_ue_config; i++) {
    for (j = 0; j < msg->lc_config_reply_msg->lc_ue_config[i]->n_lc_config; j++) {
      free(msg->lc_config_reply_msg->lc_ue_config[i]->lc_config[j]);
    }
    free(msg->lc_config_reply_msg->lc_ue_config[i]->lc_config);
    free(msg->lc_config_reply_msg->lc_ue_config[i]);
  }
  free(msg->lc_config_reply_msg->lc_ue_config);
  free(msg->lc_config_reply_msg);
  free(msg);
341
  return 0;
342
 error:
343
  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
344
  return -1;
345 346
}

347
int flexran_agent_destroy_ue_state_change(Protocol__FlexranMessage *msg) {
348
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG)
349 350 351 352 353
    goto error;
  free(msg->ue_state_change_msg->header);
  //TODO: Free the contents of the UE config structure
  free(msg->ue_state_change_msg);
  free(msg);
354
  return 0;
355 356 357 358

 error:
  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
  return -1;
359 360
}

361
int flexran_agent_destroy_enb_config_request(Protocol__FlexranMessage *msg) {
362
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REQUEST_MSG)
363 364 365 366 367 368 369
    goto error;
  free(msg->enb_config_request_msg->header);
  free(msg->enb_config_request_msg);
  free(msg);
  return 0;
  
 error:
370
  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
371
  return -1;
372 373
}

374
int flexran_agent_destroy_ue_config_request(Protocol__FlexranMessage *msg) {
375 376 377 378
  /* TODO: Deallocate memory for a dynamically allocated UE config message */
  return 0;
}

379
int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg) {
380 381 382 383
  /* TODO: Deallocate memory for a dynamically allocated LC config message */
  return 0;
}

384
// call this function to start a nanosecond-resolution timer
385
struct timespec timer_start(void) {
386 387 388 389 390 391 392 393 394 395 396 397 398
    struct timespec start_time;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
    return start_time;
}

// call this function to end a timer, returning nanoseconds elapsed as a long
long timer_end(struct timespec start_time){
    struct timespec end_time;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
    long diffInNanos = end_time.tv_nsec - start_time.tv_nsec;
    return diffInNanos;
}

399
int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
400

401 402
  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
  Protocol__FlexControlDelegation *control_delegation_msg = input->control_delegation_msg;
403

404
  //  struct timespec vartime = timer_start();
405 406 407 408
  
  //Write the payload lib into a file in the cache and load the lib
  char lib_name[120];
  char target[512];
409
  snprintf(lib_name, sizeof(lib_name), "/%s.so", control_delegation_msg->name);
410 411 412 413 414 415 416 417
  strcpy(target, local_cache);
  strcat(target, lib_name);

  FILE *f;
  f = fopen(target, "wb");
  fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f);
  fclose(f);

418
  //  long time_elapsed_nanos = timer_end(vartime);
419 420 421 422 423
  *msg = NULL;
  return 0;

}

424
int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg) {
425
  /*TODO: Dealocate memory for a dynamically allocated control delegation message*/
426
  return 0;
427 428
}

429
int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
430 431
  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
  Protocol__FlexAgentReconfiguration *agent_reconfiguration_msg = input->agent_reconfiguration_msg;
432 433 434 435 436 437 438

  apply_reconfiguration_policy(mod_id, agent_reconfiguration_msg->policy, strlen(agent_reconfiguration_msg->policy));

  *msg = NULL;
  return 0;
}

439
int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg) {
440
  /*TODO: Dealocate memory for a dynamically allocated agent reconfiguration message*/
441
  return 0;
442 443
}

444

445 446 447 448
/*
 * get generic info from RAN
 */

449
void flexran_set_enb_vars(mid_t mod_id, ran_name_t ran){
450 451 452 453 454

  switch (ran){
  case RAN_LTE_OAI :
    enb[mod_id] =  (void *)&eNB_mac_inst[mod_id];
    enb_ue[mod_id] = (void *)&eNB_mac_inst[mod_id].UE_list;
MKassem's avatar
MKassem committed
455
    enb_rrc[mod_id] = (void *)&eNB_rrc_inst[mod_id];
456 457 458 459 460 461 462 463
    break;
  default :
    goto error;
  }

  return; 

 error:
464
  LOG_E(FLEXRAN_AGENT, "unknown RAN name %d\n", ran);
465 466
}

467
int flexran_get_current_time_ms (mid_t mod_id, int subframe_flag){
468 469 470 471 472 473 474 475 476

  if (subframe_flag == 1){
    return ((eNB_MAC_INST *)enb[mod_id])->frame*10 + ((eNB_MAC_INST *)enb[mod_id])->subframe;
  }else {
    return ((eNB_MAC_INST *)enb[mod_id])->frame*10;
  }
   
}

477
unsigned int flexran_get_current_frame (mid_t mod_id) {
478

479
  //  #warning "SFN will not be in [0-1023] when oaisim is used"
480 481 482 483
  return ((eNB_MAC_INST *)enb[mod_id])->frame;
  
}

484 485
unsigned int flexran_get_current_system_frame_num(mid_t mod_id) {
  return (flexran_get_current_frame(mod_id) %1024);
486 487
}

488
unsigned int flexran_get_current_subframe (mid_t mod_id) {
489 490 491 492 493

  return ((eNB_MAC_INST *)enb[mod_id])->subframe;
  
}

494
uint16_t flexran_get_sfn_sf (mid_t mod_id) {
495
  
496 497 498 499
  frame_t frame;
  sub_frame_t subframe;
  uint16_t sfn_sf, frame_mask, sf_mask;
  
500 501
  frame = (frame_t) flexran_get_current_system_frame_num(mod_id);
  subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
502
  frame_mask = ((1<<12) - 1);
503
  sf_mask = ((1<<4) - 1);
504
  sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4);
505 506 507 508
  
  return sfn_sf;
}

509
uint16_t flexran_get_future_sfn_sf (mid_t mod_id, int ahead_of_time) {
510 511 512 513 514
  
  frame_t frame;
  sub_frame_t subframe;
  uint16_t sfn_sf, frame_mask, sf_mask;
  
515 516
  frame = (frame_t) flexran_get_current_system_frame_num(mod_id);
  subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
517 518 519 520 521 522 523

  subframe = ((subframe + ahead_of_time) % 10);

  int full_frames_ahead = ((ahead_of_time / 10) % 10);
  
  frame = frame + full_frames_ahead;

524
  if (subframe < flexran_get_current_subframe(mod_id)) {
525 526 527 528 529 530 531 532 533 534
    frame++;
  }

  frame_mask = ((1<<12) - 1);
  sf_mask = ((1<<4) - 1);
  sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4);
  
  return sfn_sf;
}

535
int flexran_get_num_ues (mid_t mod_id){
536 537 538 539

  return  ((UE_list_t *)enb_ue[mod_id])->num_UEs;
}

540
int flexran_get_ue_crnti (mid_t mod_id, mid_t ue_id) {
541

542
  return  UE_RNTI(mod_id, ue_id);
543 544
}

545
int flexran_get_ue_bsr (mid_t mod_id, mid_t ue_id, lcid_t lcid) {
546 547 548 549

  return ((UE_list_t *)enb_ue[mod_id])->UE_template[UE_PCCID(mod_id,ue_id)][ue_id].bsr_info[lcid];
}

550
int flexran_get_ue_phr (mid_t mod_id, mid_t ue_id) {
551 552 553 554

  return ((UE_list_t *)enb_ue[mod_id])->UE_template[UE_PCCID(mod_id,ue_id)][ue_id].phr_info;
}

555
int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id) {
556 557
  return ((UE_list_t *)enb_ue[mod_id])->eNB_UE_stats[UE_PCCID(mod_id,ue_id)][ue_id].dl_cqi;
}
558 559 560 561

int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
	rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
	uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id);
562 563 564
	mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id,frame,ENB_FLAG_YES,MBMS_FLAG_NO,channel_id,0);
	return rlc_status.bytes_in_buffer;
}
565

566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
int flexran_update_TA(mid_t mod_id, mid_t ue_id, int CC_id) {
  
  UE_list_t *UE_list=&eNB_mac_inst[mod_id].UE_list;
  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id];
  int rnti;

  rnti = flexran_get_ue_crnti(mod_id, ue_id);
  if (ue_sched_ctl->ta_timer == 0) {

    // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...                                                                         
    LTE_eNB_UE_stats		*eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
    ue_sched_ctl->ta_timer		      = 20;	// wait 20 subframes before taking TA measurement from PHY                                         
    switch (PHY_vars_eNB_g[mod_id][CC_id]->frame_parms.N_RB_DL) {
    case 6:
      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update;
      break;

    case 15:
      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update/2;
      break;

    case 25:
      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update/4;
      break;

    case 50:
      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update/8;
      break;

    case 75:
      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update/12;
      break;

    case 100:
      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update/16;
      break;
    }
    // clear the update in case PHY does not have a new measurement after timer expiry                                               
    eNB_UE_stats->timing_advance_update	      = 0;
  }
  else {
    ue_sched_ctl->ta_timer--;
    ue_sched_ctl->ta_update		      = 0;	// don't trigger a timing advance command                                                          
  }
610

611
  return ue_sched_ctl->ta_update	      = 0;
612

613
}
614

615 616 617 618
int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id,int CC_id) {
  
  UE_list_t			*UE_list      = &eNB_mac_inst[mod_id].UE_list;
  UE_sched_ctrl			*ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id];
619

620 621 622 623 624 625
  rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
  LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
  
  if (eNB_UE_stats == NULL) {
    return 0;
  }
626

627 628 629 630 631
  if (ue_sched_ctl->ta_update == 0) {
    return 1;
  } else {
    return 0;
  }
632

633
}
634

635
int flexran_get_active_CC(mid_t mod_id, mid_t ue_id) {
636 637 638
	return ((UE_list_t *)enb_ue[mod_id])->numactiveCCs[ue_id];
}

639
int flexran_get_current_RI(mid_t mod_id, mid_t ue_id, int CC_id) {
640
	LTE_eNB_UE_stats	*eNB_UE_stats = NULL;
641

642
	rnti_t			 rnti	      = flexran_get_ue_crnti(mod_id,ue_id);
643

644
	eNB_UE_stats			      = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
645 646 647 648 649
	
	if (eNB_UE_stats == NULL) {
	  return 0;
	}

650 651 652
	return eNB_UE_stats[CC_id].rank;
}

653
int flexran_get_tpc(mid_t mod_id, mid_t ue_id) {
654 655 656
	LTE_eNB_UE_stats	*eNB_UE_stats = NULL;
	int32_t			 normalized_rx_power, target_rx_power;
	int			 tpc	      = 1;
MKassem's avatar
MKassem committed
657

658 659
	int			 pCCid	      = UE_PCCID(mod_id,ue_id);
	rnti_t			 rnti	      = flexran_get_ue_crnti(mod_id,ue_id);
MKassem's avatar
MKassem committed
660

661
	eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, pCCid, rnti);
MKassem's avatar
MKassem committed
662 663 664

	target_rx_power = mac_xface->get_target_pusch_rx_power(mod_id,pCCid);

665 666 667 668 669 670 671 672
	if (eNB_UE_stats == NULL) {
	  normalized_rx_power = target_rx_power;
	} else if (eNB_UE_stats->UL_rssi != NULL) {
	  normalized_rx_power = eNB_UE_stats->UL_rssi[0];
	} else {
	  normalized_rx_power = target_rx_power;
	}

MKassem's avatar
MKassem committed
673
	if (normalized_rx_power>(target_rx_power+1)) {
674
		tpc = 0;	//-1
MKassem's avatar
MKassem committed
675
	} else if (normalized_rx_power<(target_rx_power-1)) {
676
		tpc = 2;	//+1
MKassem's avatar
MKassem committed
677
	} else {
678
		tpc = 1;	//0
MKassem's avatar
MKassem committed
679 680 681 682
	}
	return tpc;
}

683 684
int flexran_get_harq(const mid_t mod_id, const uint8_t CC_id, const mid_t ue_id, const int frame, const uint8_t subframe, 
		     unsigned char *id, unsigned char *round)	{ //flag_id_status = 0 then id, else status
MKassem's avatar
MKassem committed
685 686 687 688
	/*TODO: Add int TB in function parameters to get the status of the second TB. This can be done to by editing in
	 * get_ue_active_harq_pid function in line 272 file: phy_procedures_lte_eNB.c to add
	 * DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch_eNB[(uint32_t)UE_id][1];*/

689
  uint8_t harq_pid;
690
  uint8_t harq_round;
691
  
MKassem's avatar
MKassem committed
692

693
  uint16_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
MKassem's avatar
MKassem committed
694

695
  mac_xface->get_ue_active_harq_pid(mod_id,CC_id,rnti,frame,subframe,&harq_pid,&harq_round,openair_harq_DL);
MKassem's avatar
MKassem committed
696

697
  *id = harq_pid;
698 699 700 701 702 703
  *round = harq_round;
  /* if (round > 0) { */
  /*   *status = 1; */
  /* } else { */
  /*   *status = 0; */
  /* } */
704

705
  /* return 0; */
706
  return *round;
MKassem's avatar
MKassem committed
707 708
}

709
int flexran_get_p0_pucch_dbm(mid_t mod_id, mid_t ue_id, int CC_id) {
710
	LTE_eNB_UE_stats *eNB_UE_stats = NULL;
711
	uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
712 713

	eNB_UE_stats =  mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
714 715 716 717 718
	
	if (eNB_UE_stats == NULL) {
	  return -1;
	}
	
719
	if(eNB_UE_stats->Po_PUCCH_update == 1) {
720 721 722 723 724 725
		return eNB_UE_stats->Po_PUCCH_dBm;
	}
	else
		return -1;
}

726
int flexran_get_p0_nominal_pucch(mid_t mod_id, int CC_id) {
727 728 729 730
	int32_t pucch_rx_received = mac_xface->get_target_pucch_rx_power(mod_id, CC_id);
	return pucch_rx_received;
}

731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
int flexran_get_p0_pucch_status(mid_t mod_id, mid_t ue_id, int CC_id) {
        LTE_eNB_UE_stats *eNB_UE_stats = NULL;
	uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);

	eNB_UE_stats =  mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
	return eNB_UE_stats->Po_PUCCH_update;
}

int flexran_update_p0_pucch(mid_t mod_id, mid_t ue_id, int CC_id) {
          LTE_eNB_UE_stats *eNB_UE_stats = NULL;
	uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);

	eNB_UE_stats =  mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
	eNB_UE_stats->Po_PUCCH_update = 0;

	return 0;
}

MKassem's avatar
MKassem committed
749 750 751 752 753 754 755

/*
 * ************************************
 * Get Messages for eNB Configuration Reply
 * ************************************
 */

756
int flexran_get_hopping_offset(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
757 758 759 760 761
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->pusch_config_common.pusch_HoppingOffset;
}
762

763
int flexran_get_hopping_mode(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
764 765 766 767 768
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->pusch_config_common.hoppingMode;
}
769

770
int flexran_get_n_SB(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
771 772 773 774 775
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->pusch_config_common.n_SB;
}
776

777
int flexran_get_enable64QAM(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
778 779 780 781 782
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->pusch_config_common.enable64QAM;
}
783

784
int flexran_get_phich_duration(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
785 786 787 788 789
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->phich_config_common.phich_duration;
}
790

791
int flexran_get_phich_resource(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
792 793 794 795 796 797 798 799 800 801 802 803 804 805
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	if(frame_parms->phich_config_common.phich_resource == oneSixth)
		return 0;
	else if(frame_parms->phich_config_common.phich_resource == half)
		return 1;
	else if(frame_parms->phich_config_common.phich_resource == one)
		return 2;
	else if(frame_parms->phich_config_common.phich_resource == two)
		return 3;

	return -1;
}
806

807
int flexran_get_n1pucch_an(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
808 809 810 811 812
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->pucch_config_common.n1PUCCH_AN;
}
813

814
int flexran_get_nRB_CQI(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
815 816 817 818 819
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->pucch_config_common.nRB_CQI;
}
820

821
int flexran_get_deltaPUCCH_Shift(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
822 823 824 825 826
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->pucch_config_common.deltaPUCCH_Shift;
}
827

828
int flexran_get_prach_ConfigIndex(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
829 830 831 832 833
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex;
}
834

835
int flexran_get_prach_FreqOffset(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
836 837 838 839 840
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset;
}
841

842
int flexran_get_maxHARQ_Msg3Tx(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
843 844 845 846 847
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->maxHARQ_Msg3Tx;
}
848

849
int flexran_get_ul_cyclic_prefix_length(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
850 851 852 853 854
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->Ncp_UL;
}
855

856
int flexran_get_dl_cyclic_prefix_length(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
857 858 859 860 861
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->Ncp;
}
862

863
int flexran_get_cell_id(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
864 865 866 867 868
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->Nid_cell;
}
869

870
int flexran_get_srs_BandwidthConfig(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
871 872 873 874 875
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig;
}
876

877
int flexran_get_srs_SubframeConfig(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
878 879 880 881 882
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->soundingrs_ul_config_common.srs_SubframeConfig;
}
883

884
int flexran_get_srs_MaxUpPts(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
885 886 887 888 889
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->soundingrs_ul_config_common.srs_MaxUpPts;
}
890

891
int flexran_get_N_RB_DL(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
892 893 894 895 896
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->N_RB_DL;
}
897

898
int flexran_get_N_RB_UL(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
899 900 901 902 903
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->N_RB_UL;
}
904

905 906 907 908 909 910 911
int flexran_get_N_RBG(mid_t mod_id, int CC_id) {
  	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->N_RBG;
}

912
int flexran_get_subframe_assignment(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
913 914 915 916 917
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->tdd_config;
}
918

919
int flexran_get_special_subframe_assignment(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
920 921 922 923 924
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
	return frame_parms->tdd_config_S;
}
925

926
int flexran_get_ra_ResponseWindowSize(mid_t mod_id, int CC_id) {
927
  return enb_config_get()->properties[mod_id]->rach_raResponseWindowSize[CC_id];
MKassem's avatar
MKassem committed
928
}
929

930
int flexran_get_mac_ContentionResolutionTimer(mid_t mod_id, int CC_id) {
931
  return enb_config_get()->properties[mod_id]->rach_macContentionResolutionTimer[CC_id];
MKassem's avatar
MKassem committed
932
}
933

934
int flexran_get_duplex_mode(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
935 936 937
	LTE_DL_FRAME_PARMS   *frame_parms;

	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
938 939 940 941
	if(frame_parms->frame_type == TDD)
		return PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD;
	else if (frame_parms->frame_type == FDD)
		return PROTOCOL__FLEX_DUPLEX_MODE__FLDM_FDD;
MKassem's avatar
MKassem committed
942 943 944

	return -1;
}
945

946
long flexran_get_si_window_length(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
947 948
	return  ((eNB_RRC_INST *)enb_rrc[mod_id])->carrier[CC_id].sib1->si_WindowLength;
}
949

950
int flexran_get_sib1_length(mid_t mod_id, int CC_id) {
MKassem's avatar
MKassem committed
951 952
	return  ((eNB_RRC_INST *)enb_rrc[mod_id])->carrier[CC_id].sizeof_SIB1;
}
953

954
int flexran_get_num_pdcch_symb(mid_t mod_id, int CC_id) {
955 956 957
  /* TODO: This should return the number of PDCCH symbols initially used by the cell CC_id */
  return 0;
  //(PHY_vars_UE_g[mod_id][CC_id]->lte_ue_pdcch_vars[mod_id]->num_pdcch_symbols);
MKassem's avatar
MKassem committed
958 959
}

960 961


962
/*
963 964 965
 * ************************************
 * Get Messages for UE Configuration Reply
 * ************************************
966 967
 */

968

969
int flexran_get_time_alignment_timer(mid_t mod_id, mid_t ue_id) {
970 971 972 973 974 975 976 977 978 979 980 981 982
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.mac_MainConfig != NULL) {
      return ue_context_p->ue_context.mac_MainConfig->timeAlignmentTimerDedicated;
    } else {
      return -1;
    }
  } else {
    return -1;
  }
983 984
}

985
int flexran_get_meas_gap_config(mid_t mod_id, mid_t ue_id) {
986
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
987
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
988

989 990
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  if(ue_context_p != NULL) {
991
    if(ue_context_p->ue_context.measGapConfig != NULL) {
992 993
      if(ue_context_p->ue_context.measGapConfig->present == MeasGapConfig_PR_setup) {
	if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp0) {
994
	  return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_GP1;
995
	} else if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp1) {
996
	  return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_GP2;
997
	} else {
998
	  return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF;
999
	}
1000 1001 1002 1003
      }
    }
  }
  return -1;
1004 1005
}

1006

1007
int flexran_get_meas_gap_config_offset(mid_t mod_id, mid_t ue_id) {
1008
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
1009
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.measGapConfig != NULL){
      if(ue_context_p->ue_context.measGapConfig->present == MeasGapConfig_PR_setup) {
	if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp0) {
	  return ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.choice.gp0;
	} else if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp1) {
	  return ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.choice.gp0;
	} 
      }
    }
  }
  return -1;
1025 1026
}

1027
int flexran_get_ue_aggregated_max_bitrate_dl (mid_t mod_id, mid_t ue_id) {
1028 1029 1030
	return ((UE_list_t *)enb_ue[mod_id])->UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL;
}

1031
int flexran_get_ue_aggregated_max_bitrate_ul (mid_t mod_id, mid_t ue_id) {
1032 1033 1034
	return ((UE_list_t *)enb_ue[mod_id])->UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateUL;
}

1035
int flexran_get_half_duplex(mid_t ue_id) {
1036
  // TODO
1037 1038 1039 1040 1041 1042 1043
	//int halfduplex = 0;
	//int bands_to_scan = ((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;
	//for (int i =0; i < bands_to_scan; i++){
		//if(((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->halfDuplex > 0)
		//	halfduplex = 1;
	//}
	//return halfduplex;
1044
  return 0;
1045 1046
}

1047
int flexran_get_intra_sf_hopping(mid_t ue_id) {
1048 1049 1050
	//TODO:Get proper value
	//temp = (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->featureGroupIndicators->buf);
	//return (0 & ( 1 << (31)));
1051
  return 0;
1052 1053
}

1054
int flexran_get_type2_sb_1(mid_t ue_id) {
1055 1056 1057 1058
	//TODO:Get proper value
	//uint8_t temp = 0;
	//temp = (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->featureGroupIndicators->buf);
	//return (temp & ( 1 << (11)));
1059
  return 0;
1060 1061
}

1062
int flexran_get_ue_category(mid_t ue_id) {
1063 1064
	//TODO:Get proper value
	//return (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->ue_Category);
1065
  return 0;
1066 1067
}

1068
int flexran_get_res_alloc_type1(mid_t ue_id) {
1069 1070 1071 1072
	//TODO:Get proper value
	//uint8_t temp = 0;
	//temp = (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->featureGroupIndicators->buf);
	//return (temp & ( 1 << (30)));
1073
  return 0;
1074 1075
}

1076
int flexran_get_ue_transmission_mode(mid_t mod_id, mid_t ue_id) {
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
      return ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode;
    } else {
      return -1;
    }
  } else {
    return -1;
  }
1091 1092
}

1093
int flexran_get_tti_bundling(mid_t mod_id, mid_t ue_id) {
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.mac_MainConfig != NULL){
      return ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config->ttiBundling;
    } else {
      return -1;
    }
  }
  else {
    return -1;
  }
1108 1109
}

1110
int flexran_get_maxHARQ_TX(mid_t mod_id, mid_t ue_id) {
1111
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
1112
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
1113 1114 1115 1116 1117 1118 1119 1120
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.mac_MainConfig != NULL){
      return *ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config->maxHARQ_Tx;
    }
  }
  return -1;
1121 1122
}

1123
int flexran_get_beta_offset_ack_index(mid_t mod_id, mid_t ue_id) {
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
      return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_ACK_Index;
    } else {
      return -1;
    } 
  } else {
    return -1;
  }
1137 1138
}

1139
int flexran_get_beta_offset_ri_index(mid_t mod_id, mid_t ue_id) {
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
      return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index;
    } else {
      return -1;
    }
  } else {
    return -1;
  }
1153 1154
}

1155
int flexran_get_beta_offset_cqi_index(mid_t mod_id, mid_t ue_id) {
1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
      return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index;
    } else {
      return -1;
    }
  }
  else {
    return -1;
  }
1170 1171
}

1172
int flexran_get_simultaneous_ack_nack_cqi(mid_t mod_id, mid_t ue_id) {
1173
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
1174
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
      if (ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic != NULL) {
	return ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.simultaneousAckNackAndCQI;
      }
    }
  }
  return -1;
1185 1186
}

1187
int flexran_get_ack_nack_simultaneous_trans(mid_t mod_id,mid_t ue_id) {
1188
	return (&eNB_rrc_inst[mod_id])->carrier[0].sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission;
1189 1190
}

1191
int flexran_get_aperiodic_cqi_rep_mode(mid_t mod_id,mid_t ue_id) {
1192
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
1193
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
1194 1195 1196 1197 1198 1199 1200 1201 1202
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
      return *ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic;
    }
  }
  return -1;
1203 1204
}

1205
int flexran_get_tdd_ack_nack_feedback(mid_t mod_id, mid_t ue_id) {
1206 1207
  // TODO: This needs fixing
  return -1;
1208

1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
  /* struct rrc_eNB_ue_context_s* ue_context_p = NULL; */
  /* uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id); */
  
  /* ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP); */
  
  /* if(ue_context_p != NULL) { */
  /*   if(ue_context_p->ue_context.physicalConfigDedicated != NULL){ */
  /*     return ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode; */
  /*   } else { */
  /*     return -1; */
  /*   } */
  /* } else { */
  /*   return -1; */
  /* } */
1223 1224
}

1225
int flexran_get_ack_nack_repetition_factor(mid_t mod_id, mid_t ue_id) {
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
      return ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->ackNackRepetition.choice.setup.repetitionFactor;
    } else {
      return -1;
    }
  } else {
    return -1;
  }
1239 1240
}

1241
int flexran_get_extended_bsr_size(mid_t mod_id, mid_t ue_id) {
1242 1243
  //TODO: need to double check
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
1244
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
1245

1246 1247 1248 1249 1250 1251 1252
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.mac_MainConfig != NULL){
      if(ue_context_p->ue_context.mac_MainConfig->ext2 != NULL){
	long val = (*(ue_context_p->ue_context.mac_MainConfig->ext2->mac_MainConfig_v1020->extendedBSR_Sizes_r10));
	if (val > 0) {
	  return 1;
1253
	}
1254 1255 1256 1257
      }
    }
  }
  return -1;
1258 1259
}

1260
int flexran_get_ue_transmission_antenna(mid_t mod_id, mid_t ue_id) {
1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
  
  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
  
  if(ue_context_p != NULL) {
    if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
      if(ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.choice.setup == AntennaInfoDedicated__ue_TransmitAntennaSelection__setup_closedLoop) {
	return 2;
      } else if(ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.choice.setup == AntennaInfoDedicated__ue_TransmitAntennaSelection__setup_openLoop) {
	return 1;
      } else {
	return 0;
      }
    } else {
      return -1;
    }
  } else {
    return -1;
  }
1281 1282
}

1283
int flexran_get_lcg(mid_t ue_id, mid_t lc_id) {
1284 1285 1286
  if (UE_mac_inst == NULL) {
    return -1;
  }
1287 1288 1289 1290 1291
  if(UE_mac_inst[ue_id].logicalChannelConfig[lc_id] != NULL) {
    return *UE_mac_inst[ue_id].logicalChannelConfig[lc_id]->ul_SpecificParameters->logicalChannelGroup;
  } else {
    return -1;
  }
1292 1293
}

1294
int flexran_get_direction(mid_t ue_id, mid_t lc_id) {
1295
	/*TODO: fill with the value for the rest of LCID*/
1296
  if(lc_id == DCCH || lc_id == DCCH1) {
1297
    return 2;
1298
  } else if(lc_id == DTCH) {
1299
    return 1;
1300 1301 1302
  } else {
    return -1;
  }
1303 1304
}

1305
int flexran_agent_ue_state_change(mid_t mod_id, uint32_t rnti, uint8_t state_change) {
1306
  int size;
1307 1308
  Protocol__FlexranMessage *msg;
  Protocol__FlexHeader *header;
1309
  void *data;
1310
  int priority = 0;
1311 1312 1313

  int xid = 0;

1314
  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_UE_STATE_CHANGE, &header) != 0)
1315 1316
    goto error;

1317 1318
  Protocol__FlexUeStateChange *ue_state_change_msg;
  ue_state_change_msg = malloc(sizeof(Protocol__FlexUeStateChange));
1319 1320 1321
  if(ue_state_change_msg == NULL) {
    goto error;
  }
1322
  protocol__flex_ue_state_change__init(ue_state_change_msg);
1323 1324 1325
  ue_state_change_msg->has_type = 1;
  ue_state_change_msg->type = state_change;

1326 1327
  Protocol__FlexUeConfig *config;
  config = malloc(sizeof(Protocol__FlexUeConfig));
1328 1329 1330
  if (config == NULL) {
    goto error;
  }
1331 1332
  protocol__flex_ue_config__init(config);
  if (state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED) {
1333 1334 1335
    // Simply set the rnti of the UE
    config->has_rnti = 1;
    config->rnti = rnti;
1336 1337
  } else if (state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED
	     || state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED) {
1338 1339 1340 1341 1342
	  	  int i = find_UE_id(mod_id, rnti);
		  config->has_rnti = 1;
		  config->rnti = rnti;
	  	  if(flexran_get_time_alignment_timer(mod_id,i) != -1) {
	  		  config->time_alignment_timer = flexran_get_time_alignment_timer(mod_id,i);
1343 1344
	  		  config->has_time_alignment_timer = 1;
	  	  }
1345 1346
	  	  if(flexran_get_meas_gap_config(mod_id,i) != -1){
	  		  config->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id,i);
1347 1348
	  	  	  config->has_meas_gap_config_pattern = 1;
	  	  }
1349
	  	  if(config->has_meas_gap_config_pattern == 1 &&
1350
		     config->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
1351
		    config->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id,i);
1352
		    config->has_meas_gap_config_sf_offset = 1;
1353 1354
	  	  }
	  	  //TODO: Set the SPS configuration (Optional)
1355
	  	  //Not supported for now, so we do not set it
1356 1357 1358 1359 1360 1361

	  	  //TODO: Set the SR configuration (Optional)
	  	  //We do not set it for now

	  	  //TODO: Set the CQI configuration (Optional)
	  	  //We do not set it for now
1362
		  
1363 1364
		  if(flexran_get_ue_transmission_mode(mod_id,i) != -1) {
	  		  config->transmission_mode = flexran_get_ue_transmission_mode(mod_id,i);
1365 1366 1367
	  		  config->has_transmission_mode = 1;
	  	  }

1368
		  config->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id,i);
1369 1370
	  	  config->has_ue_aggregated_max_bitrate_ul = 1;

1371
		  config->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id,i);
1372 1373 1374
	  	  config->has_ue_aggregated_max_bitrate_dl = 1;

	  	  //TODO: Set the UE capabilities
1375 1376 1377
	  	  Protocol__FlexUeCapabilities *c_capabilities;
	  	  c_capabilities = malloc(sizeof(Protocol__FlexUeCapabilities));
	  	  protocol__flex_ue_capabilities__init(c_capabilities);
1378
	  	  //TODO: Set half duplex (FDD operation)
1379
	  	  c_capabilities->has_half_duplex = 0;
1380
	  	  c_capabilities->half_duplex = 1;//flexran_get_half_duplex(i);
1381
	  	  //TODO: Set intra-frame hopping flag
1382
	  	  c_capabilities->has_intra_sf_hopping = 0;
1383
	  	  c_capabilities->intra_sf_hopping = 1;//flexran_get_intra_sf_hopping(i);
1384
	  	  //TODO: Set support for type 2 hopping with n_sb > 1
1385
	  	  c_capabilities->has_type2_sb_1 = 0;
1386
	  	  c_capabilities->type2_sb_1 = 1;//flexran_get_type2_sb_1(i);
1387
	  	  //TODO: Set ue category
1388
	  	  c_capabilities->has_ue_category = 0;
1389
	  	  c_capabilities->ue_category = 1;//flexran_get_ue_category(i);
1390
	  	  //TODO: Set UE support for resource allocation type 1
1391
	  	  c_capabilities->has_res_alloc_type1 = 0;
1392
	  	  c_capabilities->res_alloc_type1 = 1;//flexran_get_res_alloc_type1(i);
1393 1394
	  	  //Set the capabilites to the message
	  	  config->capabilities = c_capabilities;
1395
		  
1396 1397 1398
	  	  if(flexran_get_ue_transmission_antenna(mod_id,i) != -1) {
		    config->has_ue_transmission_antenna = 1;
		    config->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id,i);
1399
	  	  }
1400

1401 1402 1403
	  	  if(flexran_get_tti_bundling(mod_id,i) != -1) {
		    config->has_tti_bundling = 1;
		    config->tti_bundling = flexran_get_tti_bundling(mod_id,i);
1404
	  	  }
1405

1406 1407 1408
	  	  if(flexran_get_maxHARQ_TX(mod_id,i) != -1){
		    config->has_max_harq_tx = 1;
		    config->max_harq_tx = flexran_get_maxHARQ_TX(mod_id,i);
1409
	  	  }
1410

1411 1412 1413
	  	  if(flexran_get_beta_offset_ack_index(mod_id,i) != -1) {
		    config->has_beta_offset_ack_index = 1;
		    config->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id,i);
1414
	  	  }
1415

1416 1417 1418
	  	  if(flexran_get_beta_offset_ri_index(mod_id,i) != -1) {
		    config->has_beta_offset_ri_index = 1;
		    config->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id,i);
1419
	  	  }
1420

1421 1422 1423
	  	  if(flexran_get_beta_offset_cqi_index(mod_id,i) != -1) {
		    config->has_beta_offset_cqi_index = 1;
		    config->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id,i);
1424
	  	  }
1425

1426 1427 1428
	  	  if(flexran_get_ack_nack_simultaneous_trans(mod_id,i) != -1) {
		    config->has_ack_nack_simultaneous_trans = 1;
		    config->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id,i);
1429
	  	  }
1430

1431 1432 1433
	  	  if(flexran_get_simultaneous_ack_nack_cqi(mod_id,i) != -1) {
		    config->has_simultaneous_ack_nack_cqi = 1;
		    config->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id,i);
1434
	  	  }
1435

1436 1437 1438 1439 1440 1441 1442 1443
	  	  if(flexran_get_aperiodic_cqi_rep_mode(mod_id,i) != -1) {
		    config->has_aperiodic_cqi_rep_mode = 1;
		    int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id,i);
		    if (mode > 4) {
		      config->aperiodic_cqi_rep_mode = PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
		    } else {
		      config->aperiodic_cqi_rep_mode = mode;
		    }
1444
	  	  }
1445

1446 1447 1448
	  	  if(flexran_get_tdd_ack_nack_feedback(mod_id, i) != -1) {
		    config->has_tdd_ack_nack_feedback = 1;
		    config->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback(mod_id,i);
1449
	  	  }
1450

1451 1452 1453
	  	  if(flexran_get_ack_nack_repetition_factor(mod_id, i) != -1) {
		    config->has_ack_nack_repetition_factor = 1;
		    config->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id,i);
1454
	  	  }
1455

1456 1457 1458
	  	  if(flexran_get_extended_bsr_size(mod_id, i) != -1) {
		    config->has_extended_bsr_size = 1;
		    config->extended_bsr_size = flexran_get_extended_bsr_size(mod_id,i);
1459
	  	  }
1460

1461 1462
		  config->has_pcell_carrier_index = 1;
		  config->pcell_carrier_index = UE_PCCID(mod_id, i);
1463 1464 1465 1466
	  	  //TODO: Set carrier aggregation support (boolean)
	  	  config->has_ca_support = 0;
	  	  config->ca_support = 0;
	  	  if(config->has_ca_support){
1467 1468 1469 1470 1471 1472 1473 1474 1475
		    //TODO: Set cross carrier scheduling support (boolean)
		    config->has_cross_carrier_sched_support = 1;
		    config->cross_carrier_sched_support = 0;
		    //TODO: Set secondary cells configuration
		    // We do not set it for now. No carrier aggregation support
		    
		    //TODO: Set deactivation timer for secondary cell
		    config->has_scell_deactivation_timer = 0;
		    config->scell_deactivation_timer = 0;
1476
	  	  }
1477
  } else if (state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_MOVED) {
1478 1479 1480 1481
    // TODO: Not supported for now. Leave blank
  }

  ue_state_change_msg->config = config;
1482
  msg = malloc(sizeof(Protocol__FlexranMessage));
1483 1484 1485
  if (msg == NULL) {
    goto error;
  }
1486 1487 1488
  protocol__flexran_message__init(msg);
  msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG;
  msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
1489 1490
  msg->ue_state_change_msg = ue_state_change_msg;

1491
  data = flexran_agent_pack_message(msg, &size);
1492
  /*Send sr info using the MAC channel of the eNB*/
1493
  if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_DEFAULT, data, size, priority)) {
1494 1495 1496
    goto error;
  }

1497
  LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
1498
  return 0;
1499
 error:
1500
  LOG_D(FLEXRAN_AGENT, "Could not send UE state message\n");
1501
  return -1;
1502
}
1503

1504

1505

1506
int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
1507 1508

  xid_t xid;
1509 1510
  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
  Protocol__FlexLcConfigRequest *lc_config_request_msg = input->lc_config_request_msg;
1511 1512 1513 1514
  xid = (lc_config_request_msg->header)->xid;

  int i, j;

1515 1516
  Protocol__FlexLcConfigReply *lc_config_reply_msg;
  lc_config_reply_msg = malloc(sizeof(Protocol__FlexLcConfigReply));
1517 1518
  if(lc_config_reply_msg == NULL)
    goto error;
1519
  protocol__flex_lc_config_reply__init(lc_config_reply_msg);
1520 1521 1522 1523 1524

  Protocol__FlexHeader *header;
  if(flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_GET_LC_CONFIG_REPLY, &header) != 0)
    goto error;

1525 1526
  lc_config_reply_msg->header = header;

1527
  lc_config_reply_msg->n_lc_ue_config = flexran_get_num_ues(mod_id);
1528

1529
  Protocol__FlexLcUeConfig **lc_ue_config;
1530
  if (lc_config_reply_msg->n_lc_ue_config > 0) {
1531
    lc_ue_config = malloc(sizeof(Protocol__FlexLcUeConfig *) * lc_config_reply_msg->n_lc_ue_config);
1532 1533 1534 1535 1536
    if (lc_ue_config == NULL) {
      goto error;
    }
    // Fill the config for each UE
    for (i = 0; i < lc_config_reply_msg->n_lc_ue_config; i++) {
1537 1538
      lc_ue_config[i] = malloc(sizeof(Protocol__FlexLcUeConfig));
      protocol__flex_lc_ue_config__init(lc_ue_config[i]);
1539

1540
      lc_ue_config[i]->has_rnti = 1;
1541
      lc_ue_config[i]->rnti = flexran_get_ue_crnti(mod_id,i);
1542

1543
      //TODO: Set the number of LC configurations that will be reported for this UE
1544 1545
      //Set this according to the current state of the UE. This is only a temporary fix
      int status = 0;
1546
      status = mac_eNB_get_rrc_status(mod_id, flexran_get_ue_crnti(mod_id, i));
1547 1548 1549 1550 1551 1552 1553
      if (status < RRC_CONNECTED) {
	lc_ue_config[i]->n_lc_config = 0;
      } else if (status == RRC_CONNECTED) {
	lc_ue_config[i]->n_lc_config = 1;
      } else {
	lc_ue_config[i]->n_lc_config = 3;
      }
1554

1555
      Protocol__FlexLcConfig **lc_config;
1556
      if (lc_ue_config[i]->n_lc_config > 0) {
1557
	lc_config = malloc(sizeof(Protocol__FlexLcConfig *) * lc_ue_config[i]->n_lc_config);
1558 1559 1560 1561
	if (lc_config == NULL) {
	  goto error;
	}
	for (j = 0; j < lc_ue_config[i]->n_lc_config; j++) {
1562 1563
	  lc_config[j] = malloc(sizeof(Protocol__FlexLcConfig));
	  protocol__flex_lc_config__init(lc_config[j]);
1564
	 
1565 1566
	  lc_config[j]->has_lcid = 1;
	  lc_config[j]->lcid = j+1;
1567
	 
1568
	  int lcg = flexran_get_lcg(i, j+1);
1569 1570
	  if (lcg >= 0 && lcg <= 3) {
	    lc_config[j]->has_lcg = 1;
1571
	    lc_config[j]->lcg = flexran_get_lcg(i,j+1);
1572
	  }
1573
	 
1574
	  lc_config[j]->has_direction = 1;
1575
	  lc_config[j]->direction = flexran_get_direction(i,j+1);
1576
	  //TODO: Bearer type. One of FLQBT_* values. Currently only default bearer supported
1577
	  lc_config[j]->has_qos_bearer_type = 1;
1578
	  lc_config[j]->qos_bearer_type = PROTOCOL__FLEX_QOS_BEARER_TYPE__FLQBT_NON_GBR;
1579

1580
	  //TODO: Set the QCI defined in TS 23.203, coded as defined in TS 36.413
1581
	  // One less than the actual QCI value. Needs to be generalized
1582 1583
	  lc_config[j]->has_qci = 1;
	  lc_config[j]->qci = 1;
1584
	  if (lc_config[j]->direction == PROTOCOL__FLEX_QOS_BEARER_TYPE__FLQBT_GBR) {
1585
	    //TODO: Set the max bitrate (UL)
1586 1587
	    lc_config[j]->has_e_rab_max_bitrate_ul = 0;
	    lc_config[j]->e_rab_max_bitrate_ul = 0;
1588
	    //TODO: Set the max bitrate (DL)
1589 1590
	    lc_config[j]->has_e_rab_max_bitrate_dl = 0;
	    lc_config[j]->e_rab_max_bitrate_dl = 0;
1591
	    //TODO: Set the guaranteed bitrate (UL)
1592 1593
	    lc_config[j]->has_e_rab_guaranteed_bitrate_ul = 0;
	    lc_config[j]->e_rab_guaranteed_bitrate_ul = 0;
1594
	    //TODO: Set the guaranteed bitrate (DL)
1595 1596
	    lc_config[j]->has_e_rab_guaranteed_bitrate_dl = 0;
	    lc_config[j]->e_rab_guaranteed_bitrate_dl = 0;
1597 1598 1599 1600 1601 1602 1603
	  }
	}
	lc_ue_config[i]->lc_config = lc_config;
      }
    } // end for UE
    lc_config_reply_msg->lc_ue_config = lc_ue_config;
  } // lc_config_reply_msg->n_lc_ue_config > 0
1604
  *msg = malloc(sizeof(Protocol__FlexranMessage));
1605 1606
  if (*msg == NULL)
    goto error;
1607 1608 1609
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REPLY_MSG;
  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621
  (*msg)->lc_config_reply_msg = lc_config_reply_msg;

  return 0;

 error:
  // TODO: Need to make proper error handling
  if (header != NULL)
    free(header);
  if (lc_config_reply_msg != NULL)
    free(lc_config_reply_msg);
  if(*msg != NULL)
    free(*msg);
1622
  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
1623 1624 1625 1626 1627 1628 1629 1630 1631
  return -1;
}

/*
 * ************************************
 * UE Configuration Reply
 * ************************************
 */

1632
int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
1633 1634

  xid_t xid;
1635 1636
  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
  Protocol__FlexUeConfigRequest *ue_config_request_msg = input->ue_config_request_msg;
1637 1638 1639 1640
  xid = (ue_config_request_msg->header)->xid;

  int i;

1641 1642
  Protocol__FlexUeConfigReply *ue_config_reply_msg;
  ue_config_reply_msg = malloc(sizeof(Protocol__FlexUeConfigReply));
1643 1644
  if(ue_config_reply_msg == NULL)
    goto error;
1645
  protocol__flex_ue_config_reply__init(ue_config_reply_msg);
1646 1647 1648 1649 1650

  Protocol__FlexHeader *header;
  if(flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_GET_UE_CONFIG_REPLY, &header) != 0)
    goto error;

1651 1652
  ue_config_reply_msg->header = header;

1653
  ue_config_reply_msg->n_ue_config = flexran_get_num_ues(mod_id);
1654

1655
  Protocol__FlexUeConfig **ue_config;
1656
  if (ue_config_reply_msg->n_ue_config > 0) {
1657
    ue_config = malloc(sizeof(Protocol__FlexUeConfig *) * ue_config_reply_msg->n_ue_config);
1658 1659 1660 1661
    if (ue_config == NULL) {
      goto error;
    }
    for (i = 0; i < ue_config_reply_msg->n_ue_config; i++) {
1662 1663
      ue_config[i] = malloc(sizeof(Protocol__FlexUeConfig));
      protocol__flex_ue_config__init(ue_config[i]);
1664

1665
      ue_config[i]->rnti = flexran_get_ue_crnti(mod_id,i);
1666 1667 1668 1669
      ue_config[i]->has_rnti = 1;
      //TODO: Set the DRX configuration (optional)
      //Not supported for now, so we do not set it

1670 1671
      if (flexran_get_time_alignment_timer(mod_id,i) != -1) {
    	  ue_config[i]->time_alignment_timer = flexran_get_time_alignment_timer(mod_id,i);
1672
    	  ue_config[i]->has_time_alignment_timer = 1;
1673
      }
1674

1675 1676
      if (flexran_get_meas_gap_config(mod_id,i) != -1) {
    	  ue_config[i]->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id,i);
1677
    	  ue_config[i]->has_meas_gap_config_pattern = 1;
1678
      }
1679
 
1680
      if (ue_config[i]->has_meas_gap_config_pattern == 1 &&
1681
	 ue_config[i]->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
1682
	ue_config[i]->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id,i);
1683 1684
	ue_config[i]->has_meas_gap_config_sf_offset = 1;
      }
1685 1686 1687 1688 1689 1690 1691 1692 1693
      //TODO: Set the SPS configuration (Optional)
      //Not supported for noe, so we do not set it

      //TODO: Set the SR configuration (Optional)
      //We do not set it for now

      //TODO: Set the CQI configuration (Optional)
      //We do not set it for now

1694 1695 1696 1697
      if (flexran_get_ue_transmission_mode(mod_id,i) != -1) {
	ue_config[i]->transmission_mode = flexran_get_ue_transmission_mode(mod_id,i);
	ue_config[i]->has_transmission_mode = 1;
      }
1698

1699
      ue_config[i]->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id,i);
1700 1701
      ue_config[i]->has_ue_aggregated_max_bitrate_ul = 1;

1702
      ue_config[i]->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id,i);
1703 1704
      ue_config[i]->has_ue_aggregated_max_bitrate_dl = 1;

1705 1706 1707
      Protocol__FlexUeCapabilities *capabilities;
      capabilities = malloc(sizeof(Protocol__FlexUeCapabilities));
      protocol__flex_ue_capabilities__init(capabilities);
1708
      //TODO: Set half duplex (FDD operation)
1709
      capabilities->has_half_duplex = 0;
1710
      capabilities->half_duplex = 0;//flexran_get_half_duplex(i);
1711
      //TODO: Set intra-frame hopping flag
1712
      capabilities->has_intra_sf_hopping = 0;
1713
      capabilities->intra_sf_hopping = 1;//flexran_get_intra_sf_hopping(i);
1714
      //TODO: Set support for type 2 hopping with n_sb > 1
1715
      capabilities->has_type2_sb_1 = 0;
1716
      capabilities->type2_sb_1 = 1;//flexran_get_type2_sb_1(i);
1717
      //TODO: Set ue category
1718
      capabilities->has_ue_category = 0;
1719
      capabilities->ue_category = 1;//flexran_get_ue_category(i);
1720
      //TODO: Set UE support for resource allocation type 1
1721
      capabilities->has_res_alloc_type1 = 0;
1722
      capabilities->res_alloc_type1 = 1;//flexran_get_res_alloc_type1(i);
1723 1724
      //Set the capabilites to the message
      ue_config[i]->capabilities = capabilities;
1725

1726 1727 1728 1729
      if (flexran_get_ue_transmission_antenna(mod_id,i) != -1) {
	ue_config[i]->has_ue_transmission_antenna = 1;
	ue_config[i]->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id,i);
      }
1730

1731 1732 1733 1734
      if (flexran_get_tti_bundling(mod_id,i) != -1) {
	ue_config[i]->has_tti_bundling = 1;
	ue_config[i]->tti_bundling = flexran_get_tti_bundling(mod_id,i);
      }
1735

1736 1737 1738 1739
      if (flexran_get_maxHARQ_TX(mod_id,i) != -1) {
	ue_config[i]->has_max_harq_tx = 1;
	ue_config[i]->max_harq_tx = flexran_get_maxHARQ_TX(mod_id,i);
      }
1740

1741 1742 1743 1744
      if (flexran_get_beta_offset_ack_index(mod_id,i) != -1) {
	ue_config[i]->has_beta_offset_ack_index = 1;
	ue_config[i]->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id,i);
      }
1745

1746 1747 1748 1749
      if (flexran_get_beta_offset_ri_index(mod_id,i) != -1) {
	ue_config[i]->has_beta_offset_ri_index = 1;
    	  ue_config[i]->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id,i);
      }
1750

1751 1752 1753
      if (flexran_get_beta_offset_cqi_index(mod_id,i) != -1) {
	ue_config[i]->has_beta_offset_cqi_index = 1;
	ue_config[i]->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id,i);
1754 1755
      }
      
1756 1757 1758 1759
      if (flexran_get_ack_nack_simultaneous_trans(mod_id,i) != -1) {
	ue_config[i]->has_ack_nack_simultaneous_trans = 1;
	ue_config[i]->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id,i);
      }
1760
      
1761 1762 1763 1764
      if (flexran_get_simultaneous_ack_nack_cqi(mod_id,i) != -1) {
	ue_config[i]->has_simultaneous_ack_nack_cqi = 1;
	ue_config[i]->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id,i);
      }
1765
      
1766 1767 1768 1769 1770 1771 1772 1773
      if (flexran_get_aperiodic_cqi_rep_mode(mod_id,i) != -1) {
	ue_config[i]->has_aperiodic_cqi_rep_mode = 1;
	int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id,i);
	if (mode > 4) {
	  ue_config[i]->aperiodic_cqi_rep_mode = PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
	} else {
	  ue_config[i]->aperiodic_cqi_rep_mode = mode;
	}
1774
      }
1775
      
1776
      if (flexran_get_tdd_ack_nack_feedback(mod_id, i) != -1) {
1777
	ue_config[i]->has_tdd_ack_nack_feedback = 1;
1778
	ue_config[i]->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback(mod_id,i);
1779
      }
1780
      
1781
      if(flexran_get_ack_nack_repetition_factor(mod_id, i) != -1) {
1782
	ue_config[i]->has_ack_nack_repetition_factor = 1;
1783
	ue_config[i]->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id,i);
1784
      }
1785
      
1786
      if (flexran_get_extended_bsr_size(mod_id, i) != -1) {
1787
	ue_config[i]->has_extended_bsr_size = 1;
1788
	ue_config[i]->extended_bsr_size = flexran_get_extended_bsr_size(mod_id,i);
1789
      }
1790 1791 1792
      //TODO: Set carrier aggregation support (boolean)
      ue_config[i]->has_ca_support = 0;
      ue_config[i]->ca_support = 0;
1793

1794 1795
      ue_config[i]->has_pcell_carrier_index = 1;
      ue_config[i]->pcell_carrier_index = UE_PCCID(mod_id, i);
1796
      if(ue_config[i]->has_ca_support){
1797
	//TODO: Set cross carrier scheduling support (boolean)
1798
	ue_config[i]->has_cross_carrier_sched_support = 0;
1799 1800 1801 1802
	ue_config[i]->cross_carrier_sched_support = 0;
	//TODO: Set secondary cells configuration
	// We do not set it for now. No carrier aggregation support
	//TODO: Set deactivation timer for secondary cell
1803 1804
	ue_config[i]->has_scell_deactivation_timer = 0;
	ue_config[i]->scell_deactivation_timer = 0;
1805 1806 1807 1808
      }
    }
    ue_config_reply_msg->ue_config = ue_config;
  }
1809
  *msg = malloc(sizeof(Protocol__FlexranMessage));
1810 1811
  if (*msg == NULL)
    goto error;
1812 1813 1814
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG;
  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825
  (*msg)->ue_config_reply_msg = ue_config_reply_msg;
  return 0;

 error:
  // TODO: Need to make proper error handling
  if (header != NULL)
    free(header);
  if (ue_config_reply_msg != NULL)
    free(ue_config_reply_msg);
  if(*msg != NULL)
    free(*msg);
1826
  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
1827 1828 1829 1830
  return -1;
}


MKassem's avatar
MKassem committed
1831 1832 1833 1834 1835 1836
/*
 * ************************************
 * eNB Configuration Request and Reply
 * ************************************
 */

1837
int flexran_agent_enb_config_request(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg) {
MKassem's avatar
MKassem committed
1838

1839
	Protocol__FlexHeader *header;
MKassem's avatar
MKassem committed
1840 1841
	xid_t xid = 1;

1842 1843
	Protocol__FlexEnbConfigRequest *enb_config_request_msg;
	enb_config_request_msg = malloc(sizeof(Protocol__FlexEnbConfigRequest));
MKassem's avatar
MKassem committed
1844
	if(enb_config_request_msg == NULL)
1845
	  goto error;
1846
	protocol__flex_enb_config_request__init(enb_config_request_msg);
1847 1848 1849 1850
	
	if(flexran_create_header(xid,PROTOCOL__FLEX_TYPE__FLPT_GET_ENB_CONFIG_REQUEST, &header) != 0)
	  goto error;

MKassem's avatar
MKassem committed
1851 1852
	enb_config_request_msg->header = header;

1853
	*msg = malloc(sizeof(Protocol__FlexranMessage));
MKassem's avatar
MKassem committed
1854
	if(*msg == NULL)
1855
	  goto error;
MKassem's avatar
MKassem committed
1856

1857 1858 1859
	protocol__flexran_message__init(*msg);
	(*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REQUEST_MSG;
	(*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
MKassem's avatar
MKassem committed
1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874
	(*msg)->enb_config_request_msg = enb_config_request_msg;
	return 0;

	error:
	  // TODO: Need to make proper error handling
	  if (header != NULL)
	    free(header);
	  if (enb_config_request_msg != NULL)
	    free(enb_config_request_msg);
	  if(*msg != NULL)
	    free(*msg);
	  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
	  return -1;
}

1875
int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
MKassem's avatar
MKassem committed
1876

1877
  xid_t xid;
1878 1879
  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
  Protocol__FlexEnbConfigRequest *enb_config_req_msg = input->enb_config_request_msg;
1880 1881
  xid = (enb_config_req_msg->header)->xid;
  
1882
  int i, j;
1883 1884
  int enb_id = mod_id;
  
1885
  Protocol__FlexEnbConfigReply *enb_config_reply_msg;
1886
  enb_config_reply_msg = malloc(sizeof(Protocol__FlexEnbConfigReply));
1887 1888
  if(enb_config_reply_msg == NULL)
    goto error;
1889
  protocol__flex_enb_config_reply__init(enb_config_reply_msg);
1890 1891 1892 1893 1894

  Protocol__FlexHeader *header;
  if(flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_GET_ENB_CONFIG_REPLY, &header) != 0)
    goto error;
  
1895 1896 1897 1898 1899 1900 1901
  enb_config_reply_msg->header = header;
  
  enb_config_reply_msg->enb_id = mod_id;
  
  
  enb_config_reply_msg->n_cell_config = MAX_NUM_CCs;
  
1902
  Protocol__FlexCellConfig **cell_conf;
1903
  if(enb_config_reply_msg->n_cell_config > 0){
1904
    cell_conf = malloc(sizeof(Protocol__FlexCellConfig *) * enb_config_reply_msg->n_cell_config);
1905 1906 1907
    if(cell_conf == NULL)
      goto error;
    for(i = 0; i < enb_config_reply_msg->n_cell_config; i++){
1908 1909
      cell_conf[i] = malloc(sizeof(Protocol__FlexCellConfig));
      protocol__flex_cell_config__init(cell_conf[i]);
1910

1911
      cell_conf[i]->phy_cell_id = 1;
1912
      cell_conf[i]->has_phy_cell_id = flexran_get_cell_id(enb_id,i);
1913

1914
      cell_conf[i]->cell_id = i;
1915
      cell_conf[i]->has_cell_id = 1;
1916

1917
      cell_conf[i]->pusch_hopping_offset = flexran_get_hopping_offset(enb_id,i);
1918
      cell_conf[i]->has_pusch_hopping_offset = 1;
1919

1920 1921 1922
      if (flexran_get_hopping_mode(enb_id,i) == 0) {
	cell_conf[i]->hopping_mode = PROTOCOL__FLEX_HOPPING_MODE__FLHM_INTER;
      } else if(flexran_get_hopping_mode(enb_id,i) == 1) {
1923
	cell_conf[i]->hopping_mode = PROTOCOL__FLEX_HOPPING_MODE__FLHM_INTERINTRA;
1924
      }
1925
      cell_conf[i]->has_hopping_mode = 1;
1926

1927
      cell_conf[i]->n_sb = flexran_get_n_SB(enb_id,i);
1928
      cell_conf[i]->has_n_sb = 1;
1929

1930
      if (flexran_get_phich_resource(enb_id,i) == 0) {
1931
	cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_ONE_SIXTH; //0
1932
      } else if (flexran_get_phich_resource(enb_id,i) == 1) {
1933
	cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_HALF; //1
1934
      } else if (flexran_get_phich_resource(enb_id,i) == 2) {
1935
	cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_ONE; // 2
1936
      } else if (flexran_get_phich_resource(enb_id,i) == 3) {
1937
	cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_TWO;//3
1938
      }
1939
      cell_conf[i]->has_phich_resource = 1;
1940

1941
      if (flexran_get_phich_duration(enb_id,i) == 0) {
1942
    	cell_conf[i]->phich_duration = PROTOCOL__FLEX_PHICH_DURATION__FLPD_NORMAL;
1943
      } else if(flexran_get_phich_duration(enb_id,i) == 1) {
1944
	cell_conf[i]->phich_duration = PROTOCOL__FLEX_PHICH_DURATION__FLPD_EXTENDED;
1945
      }
1946 1947
      cell_conf[i]->has_phich_duration = 1;
      //TODO: Fill in with actual value, See TS 36.211, section 6.9
1948
      cell_conf[i]->init_nr_pdcch_ofdm_sym = flexran_get_num_pdcch_symb(enb_id,i);
1949
      cell_conf[i]->has_init_nr_pdcch_ofdm_sym = 0;
1950
      //TODO: Fill in with actual value
1951 1952
      /* Protocol__FlexSiConfig *si_config; */
      /* si_config = malloc(sizeof(Protocol__FlexSiConfig)); */
1953 1954
      /* if(si_config == NULL) */
      /* 	goto error; */
1955
      /* protocol__flex_si_config__init(si_config); */
1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966
      /* //TODO: Fill in with actual value, Frame number to apply the SI configuration */
      /* si_config->sfn = 1; */
      /* si_config->has_sfn = 1; */
      /* //TODO: Fill in with actual value, the length of SIB1 in bytes */
      /* si_config->sib1_length = get_sib1_length(enb_id,i); */
      /* si_config->has_sib1_length = 1; */
      /* //TODO: Fill in with actual value, Scheduling window for all SIs in SF */
      /* si_config->si_window_length = (uint32_t) get_si_window_length(enb_id,i); */
      /* si_config->has_si_window_length = 1; */
      /* //TODO: Fill in with actual value, the number of SI messages */
      /* si_config->n_si_message=1; */
1967 1968
      /* Protocol__FlexSiMessage **si_message; */
      /* si_message = malloc(sizeof(Protocol__FlexSiMessage *) * si_config->n_si_message); */
1969 1970 1971
      /* if(si_message == NULL) */
      /* 	goto error; */
      /* for(j = 0; j < si_config->n_si_message; j++){ */
1972
      /* 	si_message[j] = malloc(sizeof(Protocol__FlexSiMessage)); */
1973 1974
      /* 	if(si_message[j] == NULL) */
      /* 	  goto error; */
1975
      /* 	protocol__flex_si_message__init(si_message[j]); */
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986
      /* 	//TODO: Fill in with actual value, Periodicity of SI msg in radio frames */
      /* 	si_message[j]->periodicity = 1;				//SIPeriod */
      /* 	si_message[j]->has_periodicity = 1; */
      /* 	//TODO: Fill in with actual value, rhe length of the SI message in bytes */
      /* 	si_message[j]->length = 10; */
      /* 	si_message[j]->has_length = 1; */
      /* } */
      /* if(si_config->n_si_message > 0){ */
      /* 	si_config->si_message = si_message; */
      /* } */
      /* cell_conf[i]->si_config = si_config; */
1987
      
1988
      cell_conf[i]->dl_bandwidth = flexran_get_N_RB_DL(enb_id,i);
1989
      cell_conf[i]->has_dl_bandwidth = 1;
1990

1991
      cell_conf[i]->ul_bandwidth = flexran_get_N_RB_UL(enb_id,i);
1992
      cell_conf[i]->has_ul_bandwidth = 1;
1993

1994 1995 1996
      if (flexran_get_ul_cyclic_prefix_length(enb_id, i) == 0) {
	cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_UL_CYCLIC_PREFIX_LENGTH__FLUCPL_NORMAL;
      } else if(flexran_get_ul_cyclic_prefix_length(enb_id, i) == 1) {
1997
	cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_UL_CYCLIC_PREFIX_LENGTH__FLUCPL_EXTENDED;      
1998
      }
1999
      cell_conf[i]->has_ul_cyclic_prefix_length = 1;
2000

2001 2002 2003 2004
      if (flexran_get_ul_cyclic_prefix_length(enb_id,i) == 0) {
	cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_DL_CYCLIC_PREFIX_LENGTH__FLDCPL_NORMAL;
      } else if (flexran_get_ul_cyclic_prefix_length(enb_id,i) == 1) {
	cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_DL_CYCLIC_PREFIX_LENGTH__FLDCPL_EXTENDED;
2005 2006
      }

2007
      cell_conf[i]->has_dl_cyclic_prefix_length = 1;
2008
      //TODO: Fill in with actual value, number of cell specific antenna ports. Currently single port support
2009 2010
      cell_conf[i]->antenna_ports_count = 1;
      cell_conf[i]->has_antenna_ports_count = 1;
2011

2012
      if (flexran_get_duplex_mode(enb_id,i) == 1) {
2013
	cell_conf[i]->duplex_mode = PROTOCOL__FLEX_DUPLEX_MODE__FLDM_FDD;
2014
      } else if(flexran_get_duplex_mode(enb_id,i) == 0) {
2015
	cell_conf[i]->duplex_mode = PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD;
2016
      }
2017 2018
      cell_conf[i]->has_duplex_mode = 1;
      //TODO: Fill in with actual value, DL/UL subframe assignment. TDD only
2019
      cell_conf[i]->subframe_assignment = flexran_get_subframe_assignment(enb_id, i);
2020
      cell_conf[i]->has_subframe_assignment = 0;
2021
      //TODO: Fill in with actual value, TDD only. See TS 36.211, table 4.2.1
2022
      cell_conf[i]->special_subframe_patterns = flexran_get_special_subframe_assignment(enb_id,i);
2023
      cell_conf[i]->has_special_subframe_patterns = 0;
2024
      //TODO: Fill in with actual value, The MBSFN radio frame period
2025
      cell_conf[i]->n_mbsfn_subframe_config_rfperiod = 0;
2026 2027 2028 2029 2030 2031 2032 2033 2034 2035
      uint32_t *elem_rfperiod;
      elem_rfperiod = (uint32_t *) malloc(sizeof(uint32_t) *cell_conf[i]->n_mbsfn_subframe_config_rfperiod);
      if(elem_rfperiod == NULL)
	goto error;
      for(j = 0; j < cell_conf[i]->n_mbsfn_subframe_config_rfperiod; j++){
	elem_rfperiod[j] = 1;
      }
      cell_conf[i]->mbsfn_subframe_config_rfperiod = elem_rfperiod;
      
      //TODO: Fill in with actual value, The MBSFN radio frame offset
2036
      cell_conf[i]->n_mbsfn_subframe_config_rfoffset = 0;
2037 2038 2039 2040 2041 2042 2043 2044 2045 2046
      uint32_t *elem_rfoffset;
      elem_rfoffset = (uint32_t *) malloc(sizeof(uint32_t) *cell_conf[i]->n_mbsfn_subframe_config_rfoffset);
      if(elem_rfoffset == NULL)
	goto error;
      for(j = 0; j < cell_conf[i]->n_mbsfn_subframe_config_rfoffset; j++){
	elem_rfoffset[j] = 1;
      }
      cell_conf[i]->mbsfn_subframe_config_rfoffset = elem_rfoffset;
      
      //TODO: Fill in with actual value, Bitmap indicating the MBSFN subframes
2047
      cell_conf[i]->n_mbsfn_subframe_config_sfalloc = 0;
2048 2049 2050 2051 2052 2053 2054 2055 2056
      uint32_t *elem_sfalloc;
      elem_sfalloc = (uint32_t *) malloc(sizeof(uint32_t) *cell_conf[i]->n_mbsfn_subframe_config_sfalloc);
      if(elem_sfalloc == NULL)
	goto error;
      for(j = 0; j < cell_conf[i]->n_mbsfn_subframe_config_sfalloc; j++){
	elem_sfalloc[j] = 1;
      }
      cell_conf[i]->mbsfn_subframe_config_sfalloc = elem_sfalloc;
      
2057
      cell_conf[i]->prach_config_index = flexran_get_prach_ConfigIndex(enb_id,i);
2058
      cell_conf[i]->has_prach_config_index = 1;
2059

2060
      cell_conf[i]->prach_freq_offset = flexran_get_prach_FreqOffset(enb_id,i);
2061
      cell_conf[i]->has_prach_freq_offset = 1;
2062

2063
      cell_conf[i]->ra_response_window_size = flexran_get_ra_ResponseWindowSize(enb_id,i);
2064
      cell_conf[i]->has_ra_response_window_size = 1;
2065

2066
      cell_conf[i]->mac_contention_resolution_timer = flexran_get_mac_ContentionResolutionTimer(enb_id,i);
2067
      cell_conf[i]->has_mac_contention_resolution_timer = 1;
2068

2069
      cell_conf[i]->max_harq_msg3tx = flexran_get_maxHARQ_Msg3Tx(enb_id,i);
2070
      cell_conf[i]->has_max_harq_msg3tx = 1;
2071

2072
      cell_conf[i]->n1pucch_an = flexran_get_n1pucch_an(enb_id,i);
2073
      cell_conf[i]->has_n1pucch_an = 1;
2074

2075
      cell_conf[i]->deltapucch_shift = flexran_get_deltaPUCCH_Shift(enb_id,i);
2076
      cell_conf[i]->has_deltapucch_shift = 1;
2077

2078
      cell_conf[i]->nrb_cqi = flexran_get_nRB_CQI(enb_id,i);
2079
      cell_conf[i]->has_nrb_cqi = 1;
2080

2081
      cell_conf[i]->srs_subframe_config = flexran_get_srs_SubframeConfig(enb_id,i);
2082
      cell_conf[i]->has_srs_subframe_config = 1;
2083

2084
      cell_conf[i]->srs_bw_config = flexran_get_srs_BandwidthConfig(enb_id,i);
2085
      cell_conf[i]->has_srs_bw_config = 1;
2086

2087
      cell_conf[i]->srs_mac_up_pts = flexran_get_srs_MaxUpPts(enb_id,i);
2088
      cell_conf[i]->has_srs_mac_up_pts = 1;
2089

2090
      if (flexran_get_enable64QAM(enb_id,i) == 0) {
2091
	cell_conf[i]->enable_64qam = PROTOCOL__FLEX_QAM__FLEQ_MOD_16QAM;
2092
      } else if(flexran_get_enable64QAM(enb_id,i) == 1) {
2093
	cell_conf[i]->enable_64qam = PROTOCOL__FLEX_QAM__FLEQ_MOD_64QAM;
2094
      }
2095
      cell_conf[i]->has_enable_64qam = 1;
2096
      
2097 2098 2099 2100 2101
      cell_conf[i]->carrier_index = i;
      cell_conf[i]->has_carrier_index = 1;
    }
    enb_config_reply_msg->cell_config=cell_conf;
  }
2102
  *msg = malloc(sizeof(Protocol__FlexranMessage));
2103 2104
  if(*msg == NULL)
    goto error;
2105 2106 2107
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG;
  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119
  (*msg)->enb_config_reply_msg = enb_config_reply_msg;
  
  return 0;
  
 error:
  // TODO: Need to make proper error handling
  if (header != NULL)
    free(header);
  if (enb_config_reply_msg != NULL)
    free(enb_config_reply_msg);
  if(*msg != NULL)
    free(*msg);
2120
  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
2121
  return -1;
MKassem's avatar
MKassem committed
2122 2123
}

2124

2125 2126 2127 2128 2129

/*
 * timer primitives
 */

2130 2131
//struct flexran_agent_map agent_map;
flexran_agent_timer_instance_t timer_instance;
2132
int agent_timer_init = 0;
2133
err_code_t flexran_agent_init_timer(void){
2134
  
2135
  LOG_I(FLEXRAN_AGENT, "init RB tree\n");
2136
  if (!agent_timer_init) {
2137
    RB_INIT(&timer_instance.flexran_agent_head);
2138 2139
    agent_timer_init = 1;
  }
2140
 
2141
 return PROTOCOL__FLEXRAN_ERR__NO_ERR;
2142 2143
}

2144
RB_GENERATE(flexran_agent_map, flexran_agent_timer_element_s, entry, flexran_agent_compare_timer);
2145 2146

/* The timer_id might not be the best choice for the comparison */
2147
int flexran_agent_compare_timer(struct flexran_agent_timer_element_s *a, struct flexran_agent_timer_element_s *b){
2148 2149 2150 2151 2152 2153 2154 2155

  if (a->timer_id < b->timer_id) return -1;
  if (a->timer_id > b->timer_id) return 1;

  // equal timers
  return 0;
}

2156 2157 2158 2159 2160 2161 2162 2163 2164
err_code_t flexran_agent_create_timer(uint32_t interval_sec,
				      uint32_t interval_usec,
				      agent_id_t     agent_id,
				      instance_t     instance,
				      uint32_t timer_type,
				      xid_t xid,
				      flexran_agent_timer_callback_t cb,
				      void*    timer_args,
				      long *timer_id){
2165
  
2166
  struct flexran_agent_timer_element_s *e = calloc(1, sizeof(*e));
2167 2168
  DevAssert(e != NULL);
  
2169 2170 2171 2172 2173 2174
//uint32_t timer_id;
  int ret=-1;
  
  if ((interval_sec == 0) && (interval_usec == 0 ))
    return TIMER_NULL;
  
2175
  if (timer_type >= FLEXRAN_AGENT_TIMER_TYPE_MAX)
2176 2177
    return TIMER_TYPE_INVALIDE;
  
2178
  if (timer_type  ==   FLEXRAN_AGENT_TIMER_TYPE_ONESHOT){ 
2179 2180
    ret = timer_setup(interval_sec, 
		      interval_usec, 
2181
		      TASK_FLEXRAN_AGENT, 
2182 2183 2184 2185 2186
		      instance, 
		      TIMER_ONE_SHOT,
		      timer_args,
		      timer_id);
    
2187
    e->type = TIMER_ONE_SHOT;
2188
  }
2189
  else if (timer_type  ==   FLEXRAN_AGENT_TIMER_TYPE_PERIODIC ){
2190 2191
    ret = timer_setup(interval_sec, 
		      interval_usec, 
2192
		      TASK_FLEXRAN_AGENT, 
2193 2194 2195 2196 2197
		      instance, 
		      TIMER_PERIODIC,
		      timer_args,
		      timer_id);
    
2198
    e->type = TIMER_PERIODIC;
2199 2200 2201 2202 2203 2204
  }
  
  if (ret < 0 ) {
    return TIMER_SETUP_FAILED; 
  }

2205 2206
  e->agent_id = agent_id;
  e->instance = instance;
2207
  e->state = FLEXRAN_AGENT_TIMER_STATE_ACTIVE;
2208
  e->timer_id = *timer_id;
2209 2210
  e->xid = xid;
  e->timer_args = timer_args; 
2211 2212
  e->cb = cb;
  /*element should be a real pointer*/
2213
  RB_INSERT(flexran_agent_map, &timer_instance.flexran_agent_head, e); 
2214
  
2215
  LOG_I(FLEXRAN_AGENT,"Created a new timer with id 0x%lx for agent %d, instance %d \n",
2216
	e->timer_id, e->agent_id, e->instance);
2217
  
2218 2219 2220
  return 0; 
}

2221
err_code_t flexran_agent_destroy_timer(long timer_id){
2222
  
2223
  struct flexran_agent_timer_element_s *e = get_timer_entry(timer_id);
2224 2225

  if (e != NULL ) {
2226 2227
    RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
    flexran_agent_destroy_flexran_message(e->timer_args->msg);
2228 2229 2230 2231 2232 2233 2234 2235 2236
    free(e);
  }
  
  if (timer_remove(timer_id) < 0 ) 
    goto error;
  
  return 0;

 error:
2237
  LOG_E(FLEXRAN_AGENT, "timer can't be removed\n");
2238 2239 2240
  return TIMER_REMOVED_FAILED ;
}

2241 2242
err_code_t flexran_agent_destroy_timer_by_task_id(xid_t xid) {
  struct flexran_agent_timer_element_s *e = NULL;
2243
  long timer_id;
2244
  RB_FOREACH(e, flexran_agent_map, &timer_instance.flexran_agent_head) {
2245 2246
    if (e->xid == xid) {
      timer_id = e->timer_id;
2247 2248
      RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
      flexran_agent_destroy_flexran_message(e->timer_args->msg);
2249 2250 2251 2252 2253 2254 2255 2256 2257
      free(e);
      if (timer_remove(timer_id) < 0 ) { 
	goto error;
      }
    }
  }
  return 0;

 error:
2258
  LOG_E(FLEXRAN_AGENT, "timer can't be removed\n");
2259 2260 2261
  return TIMER_REMOVED_FAILED ;
}

2262
err_code_t flexran_agent_destroy_timers(void){
2263
  
2264
  struct flexran_agent_timer_element_s *e = NULL;
2265
  
2266 2267
  RB_FOREACH(e, flexran_agent_map, &timer_instance.flexran_agent_head) {
    RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
2268
    timer_remove(e->timer_id);
2269
    flexran_agent_destroy_flexran_message(e->timer_args->msg);
2270 2271 2272 2273 2274 2275 2276
    free(e);
  }  

  return 0;

}

2277
void flexran_agent_sleep_until(struct timespec *ts, int delay) {
2278 2279 2280 2281 2282 2283 2284 2285
  ts->tv_nsec += delay;
  if(ts->tv_nsec >= 1000*1000*1000){
    ts->tv_nsec -= 1000*1000*1000;
    ts->tv_sec++;
  }
  clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts,  NULL);
}

2286

2287
err_code_t flexran_agent_stop_timer(long timer_id){
2288
  
2289 2290 2291
  struct flexran_agent_timer_element_s *e=NULL;
  struct flexran_agent_timer_element_s search;
  memset(&search, 0, sizeof(struct flexran_agent_timer_element_s));
2292 2293
  search.timer_id = timer_id;

2294
  e = RB_FIND(flexran_agent_map, &timer_instance.flexran_agent_head, &search);
2295 2296

  if (e != NULL ) {
2297
    e->state =  FLEXRAN_AGENT_TIMER_STATE_STOPPED;
2298 2299 2300 2301 2302
  }
  
  timer_remove(timer_id);
  
  return 0;
2303 2304
}

2305
struct flexran_agent_timer_element_s * get_timer_entry(long timer_id) {
2306
  
2307 2308
  struct flexran_agent_timer_element_s search;
  memset(&search, 0, sizeof(struct flexran_agent_timer_element_s));
2309
  search.timer_id = timer_id;
2310

2311
  return  RB_FIND(flexran_agent_map, &timer_instance.flexran_agent_head, &search); 
2312
}