flexran_agent_ran_api.c 113 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
 * 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
20
 */
21 22

/*! \file flexran_agent_ran_api.c
23
 * \brief FlexRAN RAN API abstraction
Robert Schmidt's avatar
Robert Schmidt committed
24
 * \author N. Nikaein, X. Foukas, S. SHARIAT BAGHERI and R. Schmidt
25 26 27 28
 * \date 2017
 * \version 0.1
 */

29
#include <dlfcn.h>
30
#include "flexran_agent_ran_api.h"
31 32
#include "s1ap_eNB_ue_context.h"
#include "s1ap_eNB_management_procedures.h"
33
#include "openair2/LAYER2/MAC/slicing/slicing.h"
34

35
static inline int phy_is_present(mid_t mod_id, uint8_t cc_id) {
36 37
  return RC.eNB && RC.eNB[mod_id] && RC.eNB[mod_id][cc_id];
}
38

39
static inline int mac_is_present(mid_t mod_id) {
40 41 42
  return RC.mac && RC.mac[mod_id];
}

43
static inline int rrc_is_present(mid_t mod_id) {
44
  return RC.rrc && RC.rrc[mod_id];
45
}
46

47
uint32_t flexran_get_current_time_ms(mid_t mod_id, int subframe_flag) {
48
  if (!mac_is_present(mod_id)) return 0;
49

Robert Schmidt's avatar
Robert Schmidt committed
50
  if (subframe_flag == 1)
51
    return RC.mac[mod_id]->frame*10 + RC.mac[mod_id]->subframe;
Robert Schmidt's avatar
Robert Schmidt committed
52
  else
53
    return RC.mac[mod_id]->frame*10;
54 55
}

56
frame_t flexran_get_current_frame(mid_t mod_id) {
57
  if (!mac_is_present(mod_id)) return 0;
58

59
  //  #warning "SFN will not be in [0-1023] when oaisim is used"
60
  return RC.mac[mod_id]->frame;
61 62
}

63
frame_t flexran_get_current_system_frame_num(mid_t mod_id) {
Robert Schmidt's avatar
Robert Schmidt committed
64
  return flexran_get_current_frame(mod_id) % 1024;
65 66
}

67
sub_frame_t flexran_get_current_subframe(mid_t mod_id) {
68
  if (!mac_is_present(mod_id)) return 0;
69

70
  return RC.mac[mod_id]->subframe;
71 72
}

73
uint32_t flexran_get_sfn_sf(mid_t mod_id) {
74
  if (!mac_is_present(mod_id)) return 0;
75

76
  return flexran_get_current_frame(mod_id) * 10 + flexran_get_current_subframe(mod_id);
77 78
}

79
uint16_t flexran_get_future_sfn_sf(mid_t mod_id, int ahead_of_time) {
80
  if (!mac_is_present(mod_id)) return 0;
81

Robert Schmidt's avatar
Robert Schmidt committed
82 83
  frame_t frame = flexran_get_current_system_frame_num(mod_id);
  sub_frame_t subframe = flexran_get_current_subframe(mod_id);
84
  uint16_t sfn_sf, frame_mask, sf_mask;
Robert Schmidt's avatar
Robert Schmidt committed
85 86 87 88
  int additional_frames;
  subframe = (subframe + ahead_of_time) % 10;

  if (subframe < flexran_get_current_subframe(mod_id))
89
    frame = (frame + 1) % 1024;
Robert Schmidt's avatar
Robert Schmidt committed
90 91

  additional_frames = ahead_of_time / 10;
92
  frame = (frame + additional_frames) % 1024;
Robert Schmidt's avatar
Robert Schmidt committed
93 94
  frame_mask = (1 << 12) - 1;
  sf_mask = (1 << 4) - 1;
95 96 97 98
  sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4);
  return sfn_sf;
}

99
int flexran_get_mac_num_ues(mid_t mod_id) {
100
  if (!mac_is_present(mod_id)) return 0;
101

102
  return RC.mac[mod_id]->UE_info.num_UEs;
103 104
}

105
int flexran_get_num_ue_lcs(mid_t mod_id, mid_t ue_id) {
106
  if (!mac_is_present(mod_id)) return 0;
107

108
  // Not sure whether this is needed: if (!rrc_is_present(mod_id)) return 0;
109
  const rnti_t rnti = flexran_get_mac_ue_crnti(mod_id, ue_id);
110
  const int s = mac_eNB_get_rrc_status(mod_id, rnti);
111

112 113 114 115 116 117 118 119
  if (s < RRC_CONNECTED)
    return 0;
  else if (s == RRC_CONNECTED)
    return 1;
  else
    return 3;
}

120
int flexran_get_mac_ue_id_rnti(mid_t mod_id, rnti_t rnti) {
121
  int n;
122

123
  if (!mac_is_present(mod_id)) return 0;
124

125 126
  /* get the (active) UE with RNTI i */
  for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) {
127
    if (RC.mac[mod_id]->UE_info.active[n] == TRUE
128 129 130 131 132
        && rnti == UE_RNTI(mod_id, n)) {
      return n;
    }
  }

133
  return 0;
134 135
}

136
int flexran_get_mac_ue_id(mid_t mod_id, int i) {
137
  int n;
138

139
  if (!mac_is_present(mod_id)) return 0;
140

141 142
  /* get the (i+1)'th active UE */
  for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) {
143
    if (RC.mac[mod_id]->UE_info.active[n] == TRUE) {
144 145
      if (i == 0)
        return n;
146

147 148 149
      --i;
    }
  }
150

151 152 153
  return 0;
}

154
rnti_t flexran_get_mac_ue_crnti(mid_t mod_id, mid_t ue_id) {
155
  if (!mac_is_present(mod_id)) return 0;
156

Robert Schmidt's avatar
Robert Schmidt committed
157
  return UE_RNTI(mod_id, ue_id);
158 159
}

160
int flexran_get_ue_bsr_ul_buffer_info(mid_t mod_id, mid_t ue_id, lcid_t lcid) {
161
  if (!mac_is_present(mod_id)) return -1;
162

163
  return RC.mac[mod_id]->UE_info.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].ul_buffer_info[lcid];
164 165
}

166
int8_t flexran_get_ue_phr(mid_t mod_id, mid_t ue_id) {
167
  if (!mac_is_present(mod_id)) return 0;
168

169
  return RC.mac[mod_id]->UE_info.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].phr_info;
170 171
}

172
uint8_t flexran_get_ue_wcqi(mid_t mod_id, mid_t ue_id) {
173
  if (!mac_is_present(mod_id)) return 0;
174

175
  return RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].dl_cqi[0];
176 177
}

178
rlc_buffer_occupancy_t flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
179
  if (!mac_is_present(mod_id)) return 0;
180

181
  rnti_t rnti = flexran_get_mac_ue_crnti(mod_id, ue_id);
Robert Schmidt's avatar
Robert Schmidt committed
182 183
  frame_t frame = flexran_get_current_frame(mod_id);
  sub_frame_t subframe = flexran_get_current_subframe(mod_id);
184
  mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0, 0
185
                                                       );
186
  return rlc_status.bytes_in_buffer;
187 188
}

189
rlc_buffer_occupancy_t flexran_get_num_pdus_buffer(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
190
  if (!mac_is_present(mod_id)) return 0;
191

192
  rnti_t rnti = flexran_get_mac_ue_crnti(mod_id,ue_id);
Robert Schmidt's avatar
Robert Schmidt committed
193 194
  frame_t frame = flexran_get_current_frame(mod_id);
  sub_frame_t subframe = flexran_get_current_subframe(mod_id);
195
  mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0, 0
196
                                                       );
197 198 199
  return rlc_status.pdus_in_buffer;
}

200
frame_t flexran_get_hol_delay(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
201
  if (!mac_is_present(mod_id)) return 0;
202

203
  rnti_t rnti = flexran_get_mac_ue_crnti(mod_id,ue_id);
Robert Schmidt's avatar
Robert Schmidt committed
204 205
  frame_t frame = flexran_get_current_frame(mod_id);
  sub_frame_t subframe = flexran_get_current_subframe(mod_id);
206
  mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0, 0
207
                                                       );
208 209 210
  return rlc_status.head_sdu_creation_time;
}

211
int32_t flexran_get_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id) {
212
  if (!phy_is_present(mod_id, cc_id)) return 0;
213

214
  int32_t tau = RC.eNB[mod_id][cc_id]->UE_stats[ue_id].timing_advance_update;
215

Robert Schmidt's avatar
Robert Schmidt committed
216
  switch (flexran_get_N_RB_DL(mod_id, cc_id)) {
217 218 219 220 221 222 223 224 225 226 227 228 229
    case 6:
      return tau;

    case 15:
      return tau / 2;

    case 25:
      return tau / 4;

    case 50:
      return tau / 8;

    case 75:
Robert Schmidt's avatar
Robert Schmidt committed
230
      return tau / 12;
231 232 233 234 235 236 237 238 239

    case 100:
      if (flexran_get_threequarter_fs(mod_id, cc_id) == 0)
        return tau / 16;
      else
        return tau / 12;

    default:
      return 0;
240 241 242
  }
}

243
uint32_t flexran_get_total_size_dl_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id) {
244
  if (!mac_is_present(mod_id)) return 0;
245

246
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_sdu_bytes;
247 248
}

249
uint32_t flexran_get_total_size_ul_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id) {
250
  if (!mac_is_present(mod_id)) return 0;
251

252
  uint64_t bytes = 0;
253

254
  for (int i = 0; i < NB_RB_MAX; ++i) {
255
    bytes += RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].num_bytes_rx[i];
256
  }
257

258
  return bytes;
259 260
}

261
uint32_t flexran_get_TBS_dl(mid_t mod_id, mid_t ue_id, int cc_id) {
262
  if (!mac_is_present(mod_id)) return 0;
263

264
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].TBS;
265 266
}

267
uint32_t flexran_get_TBS_ul(mid_t mod_id, mid_t ue_id, int cc_id) {
268
  if (!mac_is_present(mod_id)) return 0;
269

270
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].ulsch_TBS;
271 272
}

273
uint16_t flexran_get_num_prb_retx_dl_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) {
274
  if (!mac_is_present(mod_id)) return 0;
275

276
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used_retx;
277 278
}

279
uint32_t flexran_get_num_prb_retx_ul_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) {
280
  if (!mac_is_present(mod_id)) return 0;
281

282
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used_retx_rx;
283 284
}

285
uint16_t flexran_get_num_prb_dl_tx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) {
286
  if (!mac_is_present(mod_id)) return 0;
287

288
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used;
289 290
}

291
uint16_t flexran_get_num_prb_ul_rx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) {
292
  if (!mac_is_present(mod_id)) return 0;
293

294
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used_rx;
295 296
}

297
uint8_t flexran_get_ue_wpmi(mid_t mod_id, mid_t ue_id, uint8_t cc_id) {
298
  if (!mac_is_present(mod_id)) return 0;
299

300
  return RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].periodic_wideband_pmi[cc_id];
301 302
}

303
uint8_t flexran_get_mcs1_dl(mid_t mod_id, mid_t ue_id, int cc_id) {
304
  if (!mac_is_present(mod_id)) return 0;
305

306
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].dlsch_mcs1;
307 308
}

309
uint8_t flexran_get_mcs2_dl(mid_t mod_id, mid_t ue_id, int cc_id) {
310
  if (!mac_is_present(mod_id)) return 0;
311

312
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].dlsch_mcs2;
313 314
}

315
uint8_t flexran_get_mcs1_ul(mid_t mod_id, mid_t ue_id, int cc_id) {
316
  if (!mac_is_present(mod_id)) return 0;
317

318
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].ulsch_mcs1;
319 320
}

321
uint8_t flexran_get_mcs2_ul(mid_t mod_id, mid_t ue_id, int cc_id) {
322
  if (!mac_is_present(mod_id)) return 0;
323

324
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].ulsch_mcs2;
325 326
}

327
uint32_t flexran_get_total_prb_dl_tx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) {
328
  if (!mac_is_present(mod_id)) return 0;
329

330
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_rbs_used;
331 332
}

333
uint32_t flexran_get_total_prb_ul_rx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) {
334
  if (!mac_is_present(mod_id)) return 0;
335

336
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_rbs_used_rx;
337 338
}

339
uint32_t flexran_get_total_num_pdu_dl(mid_t mod_id, mid_t ue_id, int cc_id) {
340
  if (!mac_is_present(mod_id)) return 0;
341

342
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_num_pdus;
343 344
}

345
uint32_t flexran_get_total_num_pdu_ul(mid_t mod_id, mid_t ue_id, int cc_id) {
346
  if (!mac_is_present(mod_id)) return 0;
347

348
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_num_pdus_rx;
349 350
}

351
uint64_t flexran_get_total_TBS_dl(mid_t mod_id, mid_t ue_id, int cc_id) {
352
  if (!mac_is_present(mod_id)) return 0;
353

354
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_pdu_bytes;
355 356
}

357
uint64_t flexran_get_total_TBS_ul(mid_t mod_id, mid_t ue_id, int cc_id) {
358
  if (!mac_is_present(mod_id)) return 0;
359

360
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_ulsch_TBS;
361 362
}

363
int flexran_get_harq_round(mid_t mod_id, uint8_t cc_id, mid_t ue_id) {
364
  if (!mac_is_present(mod_id)) return 0;
365

366
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].harq_round;
367 368
}

369
uint32_t flexran_get_num_mac_sdu_tx(mid_t mod_id, mid_t ue_id, int cc_id) {
370
  if (!mac_is_present(mod_id)) return 0;
371

372
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].num_mac_sdu_tx;
373 374
}

375
unsigned char flexran_get_mac_sdu_lcid_index(mid_t mod_id, mid_t ue_id, int cc_id, int index) {
376
  if (!mac_is_present(mod_id)) return 0;
377

378
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].lcid_sdu[index];
379 380
}

381
uint32_t flexran_get_mac_sdu_size(mid_t mod_id, mid_t ue_id, int cc_id, int lcid) {
382
  if (!mac_is_present(mod_id)) return 0;
383

384
  return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].sdu_length_tx[lcid];
385 386 387
}


Robert Schmidt's avatar
Robert Schmidt committed
388
/* TODO needs to be revised */
389 390
void flexran_update_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id) {
  /*
391 392
    UE_info_t *UE_info=&eNB_mac_inst[mod_id].UE_info;
    UE_sched_ctrl *ue_sched_ctl = &UE_info->UE_sched_ctrl[ue_id];
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408

    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
      ue_sched_ctl->ta_update = flexran_get_TA(mod_id, ue_id, CC_id);

      // 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
    }
  #warning "Implement flexran_update_TA() in RAN API"
  */
409 410
}

Robert Schmidt's avatar
Robert Schmidt committed
411
/* TODO needs to be revised, looks suspicious: why do we need UE stats? */
412 413 414 415
int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id) {
  /*
  #warning "Implement flexran_get_MAC_CE_bitmap_TA() in RAN API"
  */
416
  if (!phy_is_present(mod_id, cc_id)) return 0;
417

Robert Schmidt's avatar
Robert Schmidt committed
418
  /* UE_stats can not be null, they are an array in RC
419
  LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
420

421 422 423
  if (eNB_UE_stats == NULL) {
    return 0;
  }
Robert Schmidt's avatar
Robert Schmidt committed
424
  */
425

Robert Schmidt's avatar
Robert Schmidt committed
426
  if (flexran_get_TA(mod_id, ue_id, cc_id) != 0) {
427 428 429 430 431 432
    return PROTOCOL__FLEX_CE_TYPE__FLPCET_TA;
  } else {
    return 0;
  }
}

433
int flexran_get_active_CC(mid_t mod_id, mid_t ue_id) {
434
  if (!mac_is_present(mod_id)) return 0;
435

436
  return RC.mac[mod_id]->UE_info.numactiveCCs[ue_id];
437 438
}

439
uint8_t flexran_get_current_RI(mid_t mod_id, mid_t ue_id, uint8_t cc_id) {
440
  if (!phy_is_present(mod_id, cc_id)) return 0;
441

442
  return RC.eNB[mod_id][cc_id]->UE_stats[ue_id].rank;
443 444
}

445
int flexran_get_tpc(mid_t mod_id, mid_t ue_id, uint8_t cc_id) {
446
  if (!phy_is_present(mod_id, cc_id)) return 0;
Robert Schmidt's avatar
Robert Schmidt committed
447 448 449 450

  /* before: tested that UL_rssi != NULL and set parameter ([0]), but it is a
   * static array -> target_rx_power is useless in old ifs?! */
  int pCCid = UE_PCCID(mod_id,ue_id);
451 452
  int32_t target_rx_power = RC.eNB[mod_id][pCCid]->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
  int32_t normalized_rx_power = RC.eNB[mod_id][cc_id]->UE_stats[ue_id].UL_rssi[0];
Robert Schmidt's avatar
Robert Schmidt committed
453
  int tpc;
454

Robert Schmidt's avatar
Robert Schmidt committed
455
  if (normalized_rx_power > target_rx_power + 1)
456
    tpc = 0;  //-1
Robert Schmidt's avatar
Robert Schmidt committed
457
  else if (normalized_rx_power < target_rx_power - 1)
458
    tpc = 2;  //+1
Robert Schmidt's avatar
Robert Schmidt committed
459
  else
460 461
    tpc = 1;  //0

Robert Schmidt's avatar
Robert Schmidt committed
462 463 464 465 466 467 468 469 470 471
  return tpc;
}

int flexran_get_harq(mid_t       mod_id,
                     uint8_t     cc_id,
                     mid_t       ue_id,
                     frame_t     frame,
                     sub_frame_t subframe,
                     uint8_t    *pid,
                     uint8_t    *round,
472
                     uint8_t     harq_flag) {
Robert Schmidt's avatar
Robert Schmidt committed
473 474 475 476 477 478
  /* 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];*/
  /* TODO IMPLEMENT */
  /*
479 480
  uint8_t harq_pid;
  uint8_t harq_round;
481

482
  if (mac_xface_not_ready()) return 0 ;
483

484
  uint16_t rnti = flexran_get_mac_ue_crnti(mod_id,ue_id);
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
485
  if (harq_flag == openair_harq_DL){
486

shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
487
      mac_xface->get_ue_active_harq_pid(mod_id,CC_id,rnti,frame,subframe,&harq_pid,&harq_round,openair_harq_DL);
488

shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
489 490
   } else if (harq_flag == openair_harq_UL){

491
     mac_xface->get_ue_active_harq_pid(mod_id,CC_id,rnti,frame,subframe,&harq_pid,round,openair_harq_UL);
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
492 493 494 495 496 497 498 499
   }
   else {

      LOG_W(FLEXRAN_AGENT,"harq_flag is not recongnized");
   }


  *pid = harq_pid;
Robert Schmidt's avatar
Robert Schmidt committed
500
  *round = harq_round;*/
501 502 503 504 505
  /* if (round > 0) { */
  /*   *status = 1; */
  /* } else { */
  /*   *status = 0; */
  /* } */
Robert Schmidt's avatar
Robert Schmidt committed
506
  /*return *round;*/
507 508 509
  /*
  #warning "Implement flexran_get_harq() in RAN API"
  */
Robert Schmidt's avatar
Robert Schmidt committed
510
  return 0;
511 512
}

513
int32_t flexran_get_p0_pucch_dbm(mid_t mod_id, mid_t ue_id, uint8_t cc_id) {
514
  if (!phy_is_present(mod_id, cc_id)) return 0;
515

516
  return RC.eNB[mod_id][cc_id]->UE_stats[ue_id].Po_PUCCH_dBm;
517 518
}

519
int8_t flexran_get_p0_nominal_pucch(mid_t mod_id, uint8_t cc_id) {
520
  if (!phy_is_present(mod_id, cc_id)) return 0;
521

522
  return RC.eNB[mod_id][cc_id]->frame_parms.ul_power_control_config_common.p0_NominalPUCCH;
523 524
}

525
int32_t flexran_get_p0_pucch_status(mid_t mod_id, mid_t ue_id, uint8_t cc_id) {
526
  if (!phy_is_present(mod_id, cc_id)) return 0;
527

528
  return RC.eNB[mod_id][cc_id]->UE_stats[ue_id].Po_PUCCH_update;
529 530
}

531
int flexran_update_p0_pucch(mid_t mod_id, mid_t ue_id, uint8_t cc_id) {
532
  if (!phy_is_present(mod_id, cc_id)) return 0;
533

534
  RC.eNB[mod_id][cc_id]->UE_stats[ue_id].Po_PUCCH_update = 0;
535 536 537 538 539 540 541 542 543
  return 0;
}


/*
 * ************************************
 * Get Messages for eNB Configuration Reply
 * ************************************
 */
544
uint8_t flexran_get_threequarter_fs(mid_t mod_id, uint8_t cc_id) {
545
  if (!phy_is_present(mod_id, cc_id)) return 0;
546

547
  return RC.eNB[mod_id][cc_id]->frame_parms.threequarter_fs;
548 549
}

550

551
uint8_t flexran_get_hopping_offset(mid_t mod_id, uint8_t cc_id) {
552
  if (!phy_is_present(mod_id, cc_id)) return 0;
553

554
  return RC.eNB[mod_id][cc_id]->frame_parms.pusch_config_common.pusch_HoppingOffset;
555 556
}

557
Protocol__FlexHoppingMode flexran_get_hopping_mode(mid_t mod_id, uint8_t cc_id) {
558
  if (!phy_is_present(mod_id, cc_id)) return -1;
559

560
  switch (RC.eNB[mod_id][cc_id]->frame_parms.pusch_config_common.hoppingMode) {
561 562 563 564 565
    case interSubFrame:
      return PROTOCOL__FLEX_HOPPING_MODE__FLHM_INTER;

    case intraAndInterSubFrame:
      return PROTOCOL__FLEX_HOPPING_MODE__FLHM_INTERINTRA;
566
  }
567

568
  return -1;
569 570
}

571
uint8_t flexran_get_n_SB(mid_t mod_id, uint8_t cc_id) {
572
  if (!phy_is_present(mod_id, cc_id)) return 0;
573

574
  return RC.eNB[mod_id][cc_id]->frame_parms.pusch_config_common.n_SB;
575 576
}

577
Protocol__FlexQam flexran_get_enable64QAM(mid_t mod_id, uint8_t cc_id) {
578
  if (!phy_is_present(mod_id, cc_id)) return 0;
579

580 581 582 583
  if (RC.eNB[mod_id][cc_id]->frame_parms.pusch_config_common.enable64QAM == TRUE)
    return PROTOCOL__FLEX_QAM__FLEQ_MOD_64QAM;
  else
    return PROTOCOL__FLEX_QAM__FLEQ_MOD_16QAM;
584 585
}

586
Protocol__FlexPhichDuration flexran_get_phich_duration(mid_t mod_id, uint8_t cc_id) {
587
  if (!phy_is_present(mod_id, cc_id)) return -1;
588

589
  switch (RC.eNB[mod_id][cc_id]->frame_parms.phich_config_common.phich_duration) {
590 591 592 593 594
    case normal:
      return PROTOCOL__FLEX_PHICH_DURATION__FLPD_NORMAL;

    case extended:
      return PROTOCOL__FLEX_PHICH_DURATION__FLPD_EXTENDED;
595
  }
596

597
  return -1;
598 599
}

600
Protocol__FlexPhichResource flexran_get_phich_resource(mid_t mod_id, uint8_t cc_id) {
601
  if (!phy_is_present(mod_id, cc_id)) return -1;
602

603
  switch (RC.eNB[mod_id][cc_id]->frame_parms.phich_config_common.phich_resource) {
604 605 606 607 608 609 610 611 612 613 614
    case oneSixth:
      return PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_ONE_SIXTH;

    case half:
      return PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_HALF;

    case one:
      return PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_ONE;

    case two:
      return PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_TWO;
Robert Schmidt's avatar
Robert Schmidt committed
615
  }
616

617
  return -1;
618 619
}

620
uint16_t flexran_get_n1pucch_an(mid_t mod_id, uint8_t cc_id) {
621
  if (!phy_is_present(mod_id, cc_id)) return 0;
622

623
  return RC.eNB[mod_id][cc_id]->frame_parms.pucch_config_common.n1PUCCH_AN;
624 625
}

626
uint8_t flexran_get_nRB_CQI(mid_t mod_id, uint8_t cc_id) {
627
  if (!phy_is_present(mod_id, cc_id)) return 0;
628

629
  return RC.eNB[mod_id][cc_id]->frame_parms.pucch_config_common.nRB_CQI;
630 631
}

632
uint8_t flexran_get_deltaPUCCH_Shift(mid_t mod_id, uint8_t cc_id) {
633
  if (!phy_is_present(mod_id, cc_id)) return 0;
634

635
  return RC.eNB[mod_id][cc_id]->frame_parms.pucch_config_common.deltaPUCCH_Shift;
636 637
}

638
uint8_t flexran_get_prach_ConfigIndex(mid_t mod_id, uint8_t cc_id) {
639
  if (!phy_is_present(mod_id, cc_id)) return 0;
640

641
  return RC.eNB[mod_id][cc_id]->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex;
642 643
}

644
uint8_t flexran_get_prach_FreqOffset(mid_t mod_id, uint8_t cc_id) {
645
  if (!phy_is_present(mod_id, cc_id)) return 0;
646

647
  return RC.eNB[mod_id][cc_id]->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset;
648 649
}

650
uint8_t flexran_get_maxHARQ_Msg3Tx(mid_t mod_id, uint8_t cc_id) {
651
  if (!phy_is_present(mod_id, cc_id)) return 0;
652

653
  return RC.eNB[mod_id][cc_id]->frame_parms.maxHARQ_Msg3Tx;
654 655
}

656
Protocol__FlexUlCyclicPrefixLength flexran_get_ul_cyclic_prefix_length(mid_t mod_id, uint8_t cc_id) {
657
  if (!phy_is_present(mod_id, cc_id)) return -1;
658

659
  switch (RC.eNB[mod_id][cc_id]->frame_parms.Ncp_UL) {
660 661 662 663 664
    case EXTENDED:
      return PROTOCOL__FLEX_UL_CYCLIC_PREFIX_LENGTH__FLUCPL_EXTENDED;

    case NORMAL:
      return PROTOCOL__FLEX_UL_CYCLIC_PREFIX_LENGTH__FLUCPL_NORMAL;
665
  }
666

667
  return -1;
668 669
}

670
Protocol__FlexDlCyclicPrefixLength flexran_get_dl_cyclic_prefix_length(mid_t mod_id, uint8_t cc_id) {
671
  if (!phy_is_present(mod_id, cc_id)) return -1;
672

673
  switch (RC.eNB[mod_id][cc_id]->frame_parms.Ncp) {
674 675 676 677 678
    case EXTENDED:
      return PROTOCOL__FLEX_DL_CYCLIC_PREFIX_LENGTH__FLDCPL_EXTENDED;

    case NORMAL:
      return PROTOCOL__FLEX_DL_CYCLIC_PREFIX_LENGTH__FLDCPL_NORMAL;
679
  }
680

681
  return -1;
682 683
}

684
uint16_t flexran_get_cell_id(mid_t mod_id, uint8_t cc_id) {
685
  if (!phy_is_present(mod_id, cc_id)) return 0;
686

687
  return RC.eNB[mod_id][cc_id]->frame_parms.Nid_cell;
688 689
}

690
uint8_t flexran_get_srs_BandwidthConfig(mid_t mod_id, uint8_t cc_id) {
691
  if (!phy_is_present(mod_id, cc_id)) return 0;
692

693
  return RC.eNB[mod_id][cc_id]->frame_parms.soundingrs_ul_config_common.srs_BandwidthConfig;
694 695
}

696
uint8_t flexran_get_srs_SubframeConfig(mid_t mod_id, uint8_t cc_id) {
697
  if (!phy_is_present(mod_id, cc_id)) return 0;
698

699
  return RC.eNB[mod_id][cc_id]->frame_parms.soundingrs_ul_config_common.srs_SubframeConfig;
700 701
}

702
uint8_t flexran_get_srs_MaxUpPts(mid_t mod_id, uint8_t cc_id) {
703
  if (!phy_is_present(mod_id, cc_id)) return 0;
704

705
  return RC.eNB[mod_id][cc_id]->frame_parms.soundingrs_ul_config_common.srs_MaxUpPts;
706 707
}

708
uint8_t flexran_get_N_RB_DL(mid_t mod_id, uint8_t cc_id) {
709
  if (!phy_is_present(mod_id, cc_id)) return 0;
710

711
  return RC.eNB[mod_id][cc_id]->frame_parms.N_RB_DL;
712 713
}

714
uint8_t flexran_get_N_RB_UL(mid_t mod_id, uint8_t cc_id) {
715
  if (!phy_is_present(mod_id, cc_id)) return 0;
716

717
  return RC.eNB[mod_id][cc_id]->frame_parms.N_RB_UL;
718 719
}

720
uint8_t flexran_get_N_RBG(mid_t mod_id, uint8_t cc_id) {
721
  if (!phy_is_present(mod_id, cc_id)) return 0;
722

723
  return RC.eNB[mod_id][cc_id]->frame_parms.N_RBG;
724 725
}

726
uint8_t flexran_get_subframe_assignment(mid_t mod_id, uint8_t cc_id) {
727
  if (!phy_is_present(mod_id, cc_id)) return 0;
728

729
  return RC.eNB[mod_id][cc_id]->frame_parms.tdd_config;
730 731
}

732
uint8_t flexran_get_special_subframe_assignment(mid_t mod_id, uint8_t cc_id) {
733
  if (!phy_is_present(mod_id, cc_id)) return 0;
734

735
  return RC.eNB[mod_id][cc_id]->frame_parms.tdd_config_S;
736 737
}

738
long flexran_get_ra_ResponseWindowSize(mid_t mod_id, uint8_t cc_id) {
739
  if (!rrc_is_present(mod_id)) return 0;
740

741
  return RC.rrc[mod_id]->configuration.radioresourceconfig[cc_id].rach_raResponseWindowSize;
742 743
}

744
long flexran_get_mac_ContentionResolutionTimer(mid_t mod_id, uint8_t cc_id) {
745
  if (!rrc_is_present(mod_id)) return 0;
746

747
  return RC.rrc[mod_id]->configuration.radioresourceconfig[cc_id].rach_macContentionResolutionTimer;
748 749
}

750
Protocol__FlexDuplexMode flexran_get_duplex_mode(mid_t mod_id, uint8_t cc_id) {
751
  if (!phy_is_present(mod_id, cc_id)) return 0;
752

753
  switch (RC.eNB[mod_id][cc_id]->frame_parms.frame_type) {
754 755 756 757 758 759 760 761
    case TDD:
      return PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD;

    case FDD:
      return PROTOCOL__FLEX_DUPLEX_MODE__FLDM_FDD;

    default:
      return -1;
Robert Schmidt's avatar
Robert Schmidt committed
762
  }
763 764
}

765
long flexran_get_si_window_length(mid_t mod_id, uint8_t cc_id) {
766
  if (!rrc_is_present(mod_id) || !RC.rrc[mod_id]->carrier[cc_id].sib1) return 0;
767

768
  return RC.rrc[mod_id]->carrier[cc_id].sib1->si_WindowLength;
769 770
}

771
uint8_t flexran_get_sib1_length(mid_t mod_id, uint8_t cc_id) {
772
  if (!rrc_is_present(mod_id)) return 0;
773

774
  return RC.rrc[mod_id]->carrier[cc_id].sizeof_SIB1;
775 776
}

777
uint8_t flexran_get_num_pdcch_symb(mid_t mod_id, uint8_t cc_id) {
778
  if (!phy_is_present(mod_id, cc_id)) return 0;
779

780
  return RC.eNB[mod_id][cc_id]->pdcch_vars[0].num_pdcch_symbols;
781 782 783 784 785 786 787 788 789
}



/*
 * ************************************
 * Get Messages for UE Configuration Reply
 * ************************************
 */
790
int flexran_get_rrc_num_ues(mid_t mod_id) {
791
  if (!rrc_is_present(mod_id)) return 0;
792

793 794
  return RC.rrc[mod_id]->Nb_ue;
}
795

796
rnti_t flexran_get_rrc_rnti_nth_ue(mid_t mod_id, int index) {
797
  if (!rrc_is_present(mod_id)) return 0;
798 799

  struct rrc_eNB_ue_context_s *ue_context_p = NULL;
800 801
  RB_FOREACH(ue_context_p, rrc_ue_tree_s, &RC.rrc[mod_id]->rrc_ue_head) {
    if (index == 0) return ue_context_p->ue_context.rnti;
802

803 804 805 806 807
    --index;
  }
  return 0;
}

808
int flexran_get_rrc_rnti_list(mid_t mod_id, rnti_t *list, int max_list) {
809
  if (!rrc_is_present(mod_id)) return 0;
810

811
  int n = 0;
812
  struct rrc_eNB_ue_context_s *ue_context_p = NULL;
813 814
  RB_FOREACH(ue_context_p, rrc_ue_tree_s, &RC.rrc[mod_id]->rrc_ue_head) {
    if (n >= max_list) break;
815

816 817 818 819 820
    list[n] = ue_context_p->ue_context.rnti;
    ++n;
  }
  return n;
}
821

822
LTE_TimeAlignmentTimer_t  flexran_get_time_alignment_timer(mid_t mod_id, rnti_t rnti) {
823
  if (!rrc_is_present(mod_id)) return -1;
824 825 826

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
827
  if (!ue_context_p) return -1;
828

Robert Schmidt's avatar
Robert Schmidt committed
829
  if (!ue_context_p->ue_context.mac_MainConfig) return -1;
830

Robert Schmidt's avatar
Robert Schmidt committed
831
  return ue_context_p->ue_context.mac_MainConfig->timeAlignmentTimerDedicated;
832 833
}

834
Protocol__FlexMeasGapConfigPattern flexran_get_meas_gap_config(mid_t mod_id, rnti_t rnti) {
835
  if (!rrc_is_present(mod_id)) return -1;
836 837 838

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
839
  if (!ue_context_p) return -1;
840

Robert Schmidt's avatar
Robert Schmidt committed
841
  if (!ue_context_p->ue_context.measGapConfig) return -1;
842

843
  if (ue_context_p->ue_context.measGapConfig->present != LTE_MeasGapConfig_PR_setup) return -1;
844

Robert Schmidt's avatar
Robert Schmidt committed
845
  switch (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present) {
846 847 848 849 850 851 852 853
    case LTE_MeasGapConfig__setup__gapOffset_PR_gp0:
      return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_GP1;

    case LTE_MeasGapConfig__setup__gapOffset_PR_gp1:
      return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_GP2;

    default:
      return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF;
854 855 856
  }
}

shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
857

858
long flexran_get_meas_gap_config_offset(mid_t mod_id, rnti_t rnti) {
859
  if (!rrc_is_present(mod_id)) return -1;
860 861 862

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
863
  if (!ue_context_p) return -1;
864

Robert Schmidt's avatar
Robert Schmidt committed
865
  if (!ue_context_p->ue_context.measGapConfig) return -1;
866

867
  if (ue_context_p->ue_context.measGapConfig->present != LTE_MeasGapConfig_PR_setup) return -1;
868

Robert Schmidt's avatar
Robert Schmidt committed
869
  switch (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present) {
870 871 872 873 874 875 876 877
    case LTE_MeasGapConfig__setup__gapOffset_PR_gp0:
      return ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.choice.gp0;

    case LTE_MeasGapConfig__setup__gapOffset_PR_gp1:
      return ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.choice.gp1;

    default:
      return -1;
Robert Schmidt's avatar
Robert Schmidt committed
878 879
  }
}
880

881
uint8_t flexran_get_rrc_status(mid_t mod_id, rnti_t rnti) {
882
  if (!rrc_is_present(mod_id)) return 0;
883 884 885

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
886
  if (!ue_context_p) return RRC_INACTIVE;
887

Robert Schmidt's avatar
Robert Schmidt committed
888
  return ue_context_p->ue_context.Status;
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
889 890
}

891
uint64_t flexran_get_ue_aggregated_max_bitrate_dl(mid_t mod_id, mid_t ue_id) {
892
  if (!mac_is_present(mod_id)) return 0;
893

894
  return 0; //RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL;
895 896
}

897
uint64_t flexran_get_ue_aggregated_max_bitrate_ul(mid_t mod_id, mid_t ue_id) {
898
  if (!mac_is_present(mod_id)) return 0;
899

900
  return 0; //RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateUL;
901 902
}

903
int flexran_get_half_duplex(mid_t mod_id, rnti_t rnti) {
904
  if (!rrc_is_present(mod_id)) return -1;
905 906 907

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

908
  if (!ue_context_p) return -1;
909

910
  if (!ue_context_p->ue_context.UE_Capability) return -1;
911

912
  LTE_SupportedBandListEUTRA_t *bands = &ue_context_p->ue_context.UE_Capability->rf_Parameters.supportedBandListEUTRA;
913

914 915 916
  for (int i = 0; i < bands->list.count; i++) {
    if (bands->list.array[i]->halfDuplex > 0) return 1;
  }
917

918 919 920
  return 0;
}

921
int flexran_get_intra_sf_hopping(mid_t mod_id, rnti_t rnti) {
922
  if (!rrc_is_present(mod_id)) return -1;
923 924 925

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

926
  if (!ue_context_p) return -1;
927

928
  if (!ue_context_p->ue_context.UE_Capability) return -1;
929

930
  if (!ue_context_p->ue_context.UE_Capability->featureGroupIndicators) return -1;
931

932 933 934 935 936 937
  /* According to TS 36.331 Annex B.1, Intra SF Hopping is bit 1 (leftmost bit)
   * in this bitmap, i.e. the eighth bit (from right) in the first bye (from
   * left) */
  BIT_STRING_t *fgi = ue_context_p->ue_context.UE_Capability->featureGroupIndicators;
  uint8_t buf = fgi->buf[0];
  return (buf >> 7) & 1;
938 939
}

940
int flexran_get_type2_sb_1(mid_t mod_id, rnti_t rnti) {
941
  if (!rrc_is_present(mod_id)) return -1;
942 943 944

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

945
  if (!ue_context_p) return -1;
946

947
  if (!ue_context_p->ue_context.UE_Capability) return -1;
948

949
  if (!ue_context_p->ue_context.UE_Capability->featureGroupIndicators) return -1;
950

951 952 953 954 955 956 957
  /* According to TS 36.331 Annex B.1, Predefined intra- and inter-sf or
   * predfined inter-sf frequency hopping for PUSCH with N_sb>1 is bit 21 (bit
   * 1 is leftmost bit) in this bitmap, i.e. the fourth bit (from right) in the
   * third byte (from left) */
  BIT_STRING_t *fgi = ue_context_p->ue_context.UE_Capability->featureGroupIndicators;
  uint8_t buf = fgi->buf[2];
  return (buf >> 3) & 1;
958 959
}

960
long flexran_get_ue_category(mid_t mod_id, rnti_t rnti) {
961
  if (!rrc_is_present(mod_id)) return -1;
962 963 964

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

965
  if (!ue_context_p) return -1;
966

967
  if (!ue_context_p->ue_context.UE_Capability) return -1;
968

969
  return ue_context_p->ue_context.UE_Capability->ue_Category;
970 971
}

972
int flexran_get_res_alloc_type1(mid_t mod_id, rnti_t rnti) {
973
  if (!rrc_is_present(mod_id)) return -1;
974 975 976

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

977
  if (!ue_context_p) return -1;
978

979
  if (!ue_context_p->ue_context.UE_Capability) return -1;
980

981
  if (!ue_context_p->ue_context.UE_Capability->featureGroupIndicators) return -1;
982

983 984 985 986 987 988
  /* According to TS 36.331 Annex B.1, Resource allocation type 1 for PDSCH is
   * bit 2 (bit 1 is leftmost bit) in this bitmap, i.e. the seventh bit (from
   * right) in the first byte (from left) */
  BIT_STRING_t *fgi = ue_context_p->ue_context.UE_Capability->featureGroupIndicators;
  uint8_t buf = fgi->buf[0];
  return (buf >> 6) & 1;
989 990
}

991
long flexran_get_ue_transmission_mode(mid_t mod_id, rnti_t rnti) {
992
  if (!rrc_is_present(mod_id)) return -1;
993 994 995

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
996
  if (!ue_context_p) return -1;
997

Robert Schmidt's avatar
Robert Schmidt committed
998
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
999

Robert Schmidt's avatar
Robert Schmidt committed
1000
  if (!ue_context_p->ue_context.physicalConfigDedicated->antennaInfo) return -1;
1001

Robert Schmidt's avatar
Robert Schmidt committed
1002
  return ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode;
1003 1004
}

1005
BOOLEAN_t flexran_get_tti_bundling(mid_t mod_id, rnti_t rnti) {
1006
  if (!rrc_is_present(mod_id)) return -1;
1007 1008 1009

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1010
  if (!ue_context_p) return -1;
1011

Robert Schmidt's avatar
Robert Schmidt committed
1012
  if (!ue_context_p->ue_context.mac_MainConfig) return -1;
1013

Robert Schmidt's avatar
Robert Schmidt committed
1014
  if (!ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config) return -1;
1015

Robert Schmidt's avatar
Robert Schmidt committed
1016
  return ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config->ttiBundling;
1017 1018
}

1019
long flexran_get_maxHARQ_TX(mid_t mod_id, rnti_t rnti) {
1020
  if (!rrc_is_present(mod_id)) return -1;
1021 1022 1023

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1024
  if (!ue_context_p) return -1;
1025

Robert Schmidt's avatar
Robert Schmidt committed
1026
  if (!ue_context_p->ue_context.mac_MainConfig) return -1;
1027

Robert Schmidt's avatar
Robert Schmidt committed
1028
  if (!ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config) return -1;
1029

Robert Schmidt's avatar
Robert Schmidt committed
1030
  return *(ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config->maxHARQ_Tx);
1031 1032
}

1033
long flexran_get_beta_offset_ack_index(mid_t mod_id, rnti_t rnti) {
1034
  if (!rrc_is_present(mod_id)) return -1;
1035 1036 1037

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1038
  if (!ue_context_p) return -1;
1039

Robert Schmidt's avatar
Robert Schmidt committed
1040
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
1041

Robert Schmidt's avatar
Robert Schmidt committed
1042
  if (!ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated) return -1;
1043

Robert Schmidt's avatar
Robert Schmidt committed
1044
  return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_ACK_Index;
1045 1046
}

1047
long flexran_get_beta_offset_ri_index(mid_t mod_id, rnti_t rnti) {
1048
  if (!rrc_is_present(mod_id)) return -1;
1049 1050 1051

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1052
  if (!ue_context_p) return -1;
1053

Robert Schmidt's avatar
Robert Schmidt committed
1054
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
1055

Robert Schmidt's avatar
Robert Schmidt committed
1056
  if (!ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated) return -1;
1057

Robert Schmidt's avatar
Robert Schmidt committed
1058
  return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index;
1059 1060
}

1061
long flexran_get_beta_offset_cqi_index(mid_t mod_id, rnti_t rnti) {
1062
  if (!rrc_is_present(mod_id)) return -1;
1063 1064 1065

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1066
  if (!ue_context_p) return -1;
1067

Robert Schmidt's avatar
Robert Schmidt committed
1068
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
1069

Robert Schmidt's avatar
Robert Schmidt committed
1070
  if (!ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated) return -1;
1071

Robert Schmidt's avatar
Robert Schmidt committed
1072
  return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index;
1073 1074
}

1075
BOOLEAN_t flexran_get_simultaneous_ack_nack_cqi(mid_t mod_id, rnti_t rnti) {
1076
  if (!rrc_is_present(mod_id)) return -1;
1077 1078 1079

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1080
  if (!ue_context_p) return -1;
1081

Robert Schmidt's avatar
Robert Schmidt committed
1082
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
1083

Robert Schmidt's avatar
Robert Schmidt committed
1084
  if (!ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig) return -1;
1085

Robert Schmidt's avatar
Robert Schmidt committed
1086
  if (!ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic) return -1;
1087

Robert Schmidt's avatar
Robert Schmidt committed
1088
  return ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.simultaneousAckNackAndCQI;
1089 1090
}

1091
BOOLEAN_t flexran_get_ack_nack_simultaneous_trans(mid_t mod_id, uint8_t cc_id) {
1092
  if (!rrc_is_present(mod_id)) return -1;
1093

1094
  if (!RC.rrc[mod_id]->carrier[cc_id].sib2) return -1;
1095

1096
  return RC.rrc[mod_id]->carrier[cc_id].sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission;
Robert Schmidt's avatar
Robert Schmidt committed
1097
}
1098

1099
Protocol__FlexAperiodicCqiReportMode flexran_get_aperiodic_cqi_rep_mode(mid_t mod_id, rnti_t rnti) {
1100
  if (!rrc_is_present(mod_id)) return -1;
1101 1102 1103

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1104
  if (!ue_context_p) return -1;
1105

Robert Schmidt's avatar
Robert Schmidt committed
1106
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
1107

Robert Schmidt's avatar
Robert Schmidt committed
1108
  if (!ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig) return -1;
1109

1110
  switch (*ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic) {
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
    case LTE_CQI_ReportModeAperiodic_rm12:
      return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM12;

    case LTE_CQI_ReportModeAperiodic_rm20:
      return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM20;

    case LTE_CQI_ReportModeAperiodic_rm22:
      return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM22;

    case LTE_CQI_ReportModeAperiodic_rm30:
      return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM30;

    case LTE_CQI_ReportModeAperiodic_rm31:
      return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM31;

    case LTE_CQI_ReportModeAperiodic_rm32_v1250:
      return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM32_v1250;

    case LTE_CQI_ReportModeAperiodic_rm10_v1310:
      return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM10_v1310;

    case LTE_CQI_ReportModeAperiodic_rm11_v1310:
      return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM11_v1310;

    default:
      return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
1137
  }
1138 1139
}

1140
long flexran_get_tdd_ack_nack_feedback_mode(mid_t mod_id, rnti_t rnti) {
1141
  if (!rrc_is_present(mod_id)) return -1;
1142 1143 1144

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1145
  if (!ue_context_p) return -1;
1146

Robert Schmidt's avatar
Robert Schmidt committed
1147
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
1148

Robert Schmidt's avatar
Robert Schmidt committed
1149
  if (!ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated) return -1;
1150

Robert Schmidt's avatar
Robert Schmidt committed
1151
  if (!ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode) return -1;
1152

Robert Schmidt's avatar
Robert Schmidt committed
1153
  return *(ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode);
1154 1155
}

1156
long flexran_get_ack_nack_repetition_factor(mid_t mod_id, rnti_t rnti) {
1157
  if (!rrc_is_present(mod_id)) return -1;
1158 1159 1160

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1161
  if (!ue_context_p) return -1;
1162

Robert Schmidt's avatar
Robert Schmidt committed
1163
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
1164

Robert Schmidt's avatar
Robert Schmidt committed
1165
  if (!ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated) return -1;
1166

Robert Schmidt's avatar
Robert Schmidt committed
1167
  return ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->ackNackRepetition.choice.setup.repetitionFactor;
1168 1169
}

1170
long flexran_get_extended_bsr_size(mid_t mod_id, rnti_t rnti) {
1171
  if (!rrc_is_present(mod_id)) return -1;
1172 1173 1174

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1175
  if (!ue_context_p) return -1;
1176

Robert Schmidt's avatar
Robert Schmidt committed
1177
  if (!ue_context_p->ue_context.mac_MainConfig) return -1;
1178

Robert Schmidt's avatar
Robert Schmidt committed
1179
  if (!ue_context_p->ue_context.mac_MainConfig->ext2) return -1;
1180

Robert Schmidt's avatar
Robert Schmidt committed
1181
  if (!ue_context_p->ue_context.mac_MainConfig->ext2->mac_MainConfig_v1020) return -1;
1182

Robert Schmidt's avatar
Robert Schmidt committed
1183
  return *(ue_context_p->ue_context.mac_MainConfig->ext2->mac_MainConfig_v1020->extendedBSR_Sizes_r10);
1184 1185
}

1186
int flexran_get_ue_transmission_antenna(mid_t mod_id, rnti_t rnti) {
1187
  if (!rrc_is_present(mod_id)) return -1;
1188 1189 1190

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1191
  if (!ue_context_p) return -1;
1192

Robert Schmidt's avatar
Robert Schmidt committed
1193
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
1194

Robert Schmidt's avatar
Robert Schmidt committed
1195
  if (!ue_context_p->ue_context.physicalConfigDedicated->antennaInfo) return -1;
1196

Robert Schmidt's avatar
Robert Schmidt committed
1197
  switch (ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.choice.setup) {
1198 1199 1200 1201 1202 1203 1204 1205
    case LTE_AntennaInfoDedicated__ue_TransmitAntennaSelection__setup_closedLoop:
      return 2;

    case LTE_AntennaInfoDedicated__ue_TransmitAntennaSelection__setup_openLoop:
      return 1;

    default:
      return 0;
1206 1207 1208
  }
}

1209
uint64_t flexran_get_ue_imsi(mid_t mod_id, rnti_t rnti) {
1210
  uint64_t imsi;
1211

1212
  if (!rrc_is_present(mod_id)) return 0;
1213 1214 1215

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

1216
  if (!ue_context_p) return 0;
1217

1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233
  imsi  = ue_context_p->ue_context.imsi.digit15;
  imsi += ue_context_p->ue_context.imsi.digit14 * 10;              // pow(10, 1)
  imsi += ue_context_p->ue_context.imsi.digit13 * 100;             // pow(10, 2)
  imsi += ue_context_p->ue_context.imsi.digit12 * 1000;            // pow(10, 3)
  imsi += ue_context_p->ue_context.imsi.digit11 * 10000;           // pow(10, 4)
  imsi += ue_context_p->ue_context.imsi.digit10 * 100000;          // pow(10, 5)
  imsi += ue_context_p->ue_context.imsi.digit9  * 1000000;         // pow(10, 6)
  imsi += ue_context_p->ue_context.imsi.digit8  * 10000000;        // pow(10, 7)
  imsi += ue_context_p->ue_context.imsi.digit7  * 100000000;       // pow(10, 8)
  imsi += ue_context_p->ue_context.imsi.digit6  * 1000000000;      // pow(10, 9)
  imsi += ue_context_p->ue_context.imsi.digit5  * 10000000000;     // pow(10, 10)
  imsi += ue_context_p->ue_context.imsi.digit4  * 100000000000;    // pow(10, 11)
  imsi += ue_context_p->ue_context.imsi.digit3  * 1000000000000;   // pow(10, 12)
  imsi += ue_context_p->ue_context.imsi.digit2  * 10000000000000;  // pow(10, 13)
  imsi += ue_context_p->ue_context.imsi.digit1  * 100000000000000; // pow(10, 14)
  return imsi;
1234 1235
}

1236
long flexran_get_lcg(mid_t mod_id, mid_t ue_id, mid_t lc_id) {
1237
  if (!mac_is_present(mod_id)) return 0;
1238

1239
  return RC.mac[mod_id]->UE_info.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].lcgidmap[lc_id];
1240 1241
}

Robert Schmidt's avatar
Robert Schmidt committed
1242
/* TODO Navid: needs to be revised */
1243
int flexran_get_direction(mid_t ue_id, mid_t lc_id) {
Robert Schmidt's avatar
Robert Schmidt committed
1244
  switch (lc_id) {
1245 1246 1247 1248 1249 1250 1251 1252 1253
    case DCCH:
    case DCCH1:
      return 2;

    case DTCH:
      return 1;

    default:
      return -1;
1254 1255 1256
  }
}

1257
uint8_t flexran_get_antenna_ports(mid_t mod_id, uint8_t cc_id) {
1258
  if (!phy_is_present(mod_id, cc_id)) return 0;
1259

1260
  return RC.eNB[mod_id][cc_id]->frame_parms.nb_antenna_ports_eNB;
1261
}
1262

1263
uint32_t flexran_agent_get_operating_dl_freq(mid_t mod_id, uint8_t cc_id) {
1264
  if (!phy_is_present(mod_id, cc_id)) return 0;
1265

1266
  return RC.eNB[mod_id][cc_id]->frame_parms.dl_CarrierFreq / 1000000;
1267 1268
}

1269
uint32_t flexran_agent_get_operating_ul_freq(mid_t mod_id, uint8_t cc_id) {
1270
  if (!phy_is_present(mod_id, cc_id)) return 0;
1271

1272
  return RC.eNB[mod_id][cc_id]->frame_parms.ul_CarrierFreq / 1000000;
1273 1274
}

1275
uint8_t flexran_agent_get_operating_eutra_band(mid_t mod_id, uint8_t cc_id) {
1276
  if (!phy_is_present(mod_id, cc_id)) return 0;
1277

1278
  return RC.eNB[mod_id][cc_id]->frame_parms.eutra_band;
1279
}
Robert Schmidt's avatar
Robert Schmidt committed
1280

1281
int8_t flexran_agent_get_operating_pdsch_refpower(mid_t mod_id, uint8_t cc_id) {
1282
  if (!phy_is_present(mod_id, cc_id)) return 0;
1283

1284
  return RC.eNB[mod_id][cc_id]->frame_parms.pdsch_config_common.referenceSignalPower;
1285 1286
}

1287
long flexran_agent_get_operating_pusch_p0(mid_t mod_id, uint8_t cc_id) {
1288
  if (!rrc_is_present(mod_id)) return 0;
1289

1290
  return RC.rrc[mod_id]->configuration.radioresourceconfig[cc_id].pusch_p0_Nominal;
Robert Schmidt's avatar
Robert Schmidt committed
1291
}
1292

1293
void flexran_agent_set_operating_dl_freq(mid_t mod_id, uint8_t cc_id, uint32_t dl_freq_mhz) {
1294 1295 1296 1297
  if (phy_is_present(mod_id, cc_id)) {
    RC.eNB[mod_id][cc_id]->frame_parms.dl_CarrierFreq = dl_freq_mhz * 1000000;
  } else {
    LOG_E(FLEXRAN_AGENT, "can not set dl_CarrierFreq to %d MHz in PHY: PHY is not present\n", dl_freq_mhz);
Robert Schmidt's avatar
Robert Schmidt committed
1298
  }
1299

1300 1301 1302 1303
  if (rrc_is_present(mod_id)) {
    RC.rrc[mod_id]->configuration.downlink_frequency[cc_id] = dl_freq_mhz * 1000000;
  } else {
    LOG_E(FLEXRAN_AGENT, "can not set downlink_frequency to %d MHz in RRC: RRC is not present\n", dl_freq_mhz);
Robert Schmidt's avatar
Robert Schmidt committed
1304
  }
1305 1306
}

1307
void flexran_agent_set_operating_ul_freq(mid_t mod_id, uint8_t cc_id, int32_t ul_freq_mhz_offset) {
1308
  if (phy_is_present(mod_id, cc_id)) {
Robert Schmidt's avatar
Robert Schmidt committed
1309
    uint32_t new_ul_freq_mhz = flexran_agent_get_operating_dl_freq(mod_id, cc_id) + ul_freq_mhz_offset;
1310 1311 1312
    RC.eNB[mod_id][cc_id]->frame_parms.ul_CarrierFreq = new_ul_freq_mhz * 1000000;
  } else {
    LOG_E(FLEXRAN_AGENT, "can not set ul_CarrierFreq using offset %d MHz in PHY: PHY is not present\n", ul_freq_mhz_offset);
Robert Schmidt's avatar
Robert Schmidt committed
1313
  }
1314

1315 1316 1317 1318
  if (rrc_is_present(mod_id)) {
    RC.rrc[mod_id]->configuration.uplink_frequency_offset[cc_id] = ul_freq_mhz_offset;
  } else {
    LOG_E(FLEXRAN_AGENT, "can not set uplink_frequency_offset to %d MHz in RRC: RRC is not present\n", ul_freq_mhz_offset);
Robert Schmidt's avatar
Robert Schmidt committed
1319
  }
1320
}
Robert Schmidt's avatar
Robert Schmidt committed
1321

1322
void flexran_agent_set_operating_eutra_band(mid_t mod_id, uint8_t cc_id, uint8_t eutra_band) {
1323 1324 1325 1326
  if (phy_is_present(mod_id, cc_id)) {
    RC.eNB[mod_id][cc_id]->frame_parms.eutra_band = eutra_band;
  } else {
    LOG_E(FLEXRAN_AGENT, "can not set eutra_band to %d in PHY: PHY is not present\n", eutra_band);
Robert Schmidt's avatar
Robert Schmidt committed
1327
  }
1328

1329 1330 1331 1332
  if (rrc_is_present(mod_id)) {
    RC.rrc[mod_id]->configuration.eutra_band[cc_id] = eutra_band;
  } else {
    LOG_E(FLEXRAN_AGENT, "can not set eutra_band to %d in RRC: RRC is not present\n", eutra_band);
Robert Schmidt's avatar
Robert Schmidt committed
1333
  }
1334 1335
}

Robert Schmidt's avatar
Robert Schmidt committed
1336
/* Sets both DL/UL */
1337
void flexran_agent_set_operating_bandwidth(mid_t mod_id, uint8_t cc_id, uint8_t N_RB) {
1338 1339 1340 1341 1342
  if (phy_is_present(mod_id, cc_id)) {
    RC.eNB[mod_id][cc_id]->frame_parms.N_RB_DL = N_RB;
    RC.eNB[mod_id][cc_id]->frame_parms.N_RB_UL = N_RB;
  } else {
    LOG_E(FLEXRAN_AGENT, "can not set N_RB_DL and N_RB_UL to %d in PHY: PHY is not present\n", N_RB);
Robert Schmidt's avatar
Robert Schmidt committed
1343
  }
1344

1345 1346 1347 1348
  if (rrc_is_present(mod_id)) {
    RC.rrc[mod_id]->configuration.N_RB_DL[cc_id] = N_RB;
  } else {
    LOG_E(FLEXRAN_AGENT, "can not set N_RB_DL to %d in RRC: RRC is not present\n", N_RB);
Robert Schmidt's avatar
Robert Schmidt committed
1349
  }
1350 1351
}

1352
void flexran_agent_set_operating_frame_type(mid_t mod_id, uint8_t cc_id, lte_frame_type_t frame_type) {
1353 1354 1355 1356
  if (phy_is_present(mod_id, cc_id)) {
    RC.eNB[mod_id][cc_id]->frame_parms.frame_type = frame_type;
  } else {
    LOG_E(FLEXRAN_AGENT, "can not set frame_type to %d in PHY: PHY is not present\n", frame_type);
Robert Schmidt's avatar
Robert Schmidt committed
1357
  }
1358

1359 1360 1361 1362
  if (rrc_is_present(mod_id)) {
    RC.rrc[mod_id]->configuration.frame_type[cc_id] = frame_type;
  } else {
    LOG_E(FLEXRAN_AGENT, "can not set frame_type to %d in RRC: RRC is not present\n", frame_type);
Robert Schmidt's avatar
Robert Schmidt committed
1363
  }
1364 1365
}

1366
/*********** PDCP  *************/
1367

1368
uint16_t flexran_get_pdcp_uid_from_rnti(mid_t mod_id, rnti_t rnti) {
1369
  if (rnti == NOT_A_RNTI) return 0;
1370

1371 1372
  if (mod_id < 0 || mod_id >= RC.nb_inst)
    return 0;
1373 1374 1375 1376 1377

  for (uint16_t pdcp_uid = 0; pdcp_uid < MAX_MOBILES_PER_ENB; ++pdcp_uid) {
    if (pdcp_enb[mod_id].rnti[pdcp_uid] == rnti)
      return pdcp_uid;
  }
1378

1379 1380 1381
  return 0;
}

1382
/*PDCP super frame counter flexRAN*/
1383
uint32_t flexran_get_pdcp_sfn(mid_t mod_id) {
1384 1385
  if (mod_id < 0 || mod_id >= RC.nb_inst)
    return 0;
1386

1387
  return pdcp_enb[mod_id].sfn;
1388
}
1389

1390
/*PDCP super frame counter flexRAN*/
1391
void flexran_set_pdcp_tx_stat_window(mid_t mod_id, uint16_t uid, uint16_t obs_window) {
1392 1393 1394
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB)
    return;
1395

1396
  Pdcp_stats_tx_window_ms[mod_id][uid] = obs_window > 0 ? obs_window : 1000;
1397 1398 1399
}

/*PDCP super frame counter flexRAN*/
1400
void flexran_set_pdcp_rx_stat_window(mid_t mod_id, uint16_t uid, uint16_t obs_window) {
1401 1402 1403
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB)
    return;
1404

1405
  Pdcp_stats_rx_window_ms[mod_id][uid] = obs_window > 0 ? obs_window : 1000;
1406 1407
}

1408
/*PDCP num tx pdu status flexRAN*/
1409
uint32_t flexran_get_pdcp_tx(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1410 1411 1412
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1413

1414
  return Pdcp_stats_tx[mod_id][uid][lcid];
1415 1416 1417
}

/*PDCP num tx bytes status flexRAN*/
1418
uint32_t flexran_get_pdcp_tx_bytes(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1419 1420 1421
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1422

1423
  return Pdcp_stats_tx_bytes[mod_id][uid][lcid];
1424 1425 1426
}

/*PDCP number of transmit packet / second status flexRAN*/
1427
uint32_t flexran_get_pdcp_tx_w(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1428 1429 1430
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1431

1432
  return Pdcp_stats_tx_w[mod_id][uid][lcid];
1433 1434 1435
}

/*PDCP throughput (bit/s) status flexRAN*/
1436
uint32_t flexran_get_pdcp_tx_bytes_w(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1437 1438 1439
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1440

1441
  return Pdcp_stats_tx_bytes_w[mod_id][uid][lcid];
1442 1443 1444
}

/*PDCP tx sequence number flexRAN*/
1445
uint32_t flexran_get_pdcp_tx_sn(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1446 1447 1448
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1449

1450
  return Pdcp_stats_tx_sn[mod_id][uid][lcid];
1451 1452 1453
}

/*PDCP tx aggregated packet arrival  flexRAN*/
1454
uint32_t flexran_get_pdcp_tx_aiat(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1455 1456 1457
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1458

1459
  return Pdcp_stats_tx_aiat[mod_id][uid][lcid];
1460 1461 1462
}

/*PDCP tx aggregated packet arrival  flexRAN*/
1463
uint32_t flexran_get_pdcp_tx_aiat_w(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1464 1465 1466
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1467

1468
  return Pdcp_stats_tx_aiat_w[mod_id][uid][lcid];
1469 1470 1471
}

/*PDCP num rx pdu status flexRAN*/
1472
uint32_t flexran_get_pdcp_rx(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1473 1474 1475
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1476

1477
  return Pdcp_stats_rx[mod_id][uid][lcid];
1478 1479 1480
}

/*PDCP num rx bytes status flexRAN*/
1481
uint32_t flexran_get_pdcp_rx_bytes(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1482 1483 1484
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1485

1486
  return Pdcp_stats_rx_bytes[mod_id][uid][lcid];
1487 1488 1489
}

/*PDCP number of received packet / second  flexRAN*/
1490
uint32_t flexran_get_pdcp_rx_w(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1491 1492 1493
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1494

1495
  return Pdcp_stats_rx_w[mod_id][uid][lcid];
1496 1497 1498
}

/*PDCP gootput (bit/s) status flexRAN*/
1499
uint32_t flexran_get_pdcp_rx_bytes_w(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1500 1501 1502
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1503

1504
  return Pdcp_stats_rx_bytes_w[mod_id][uid][lcid];
1505 1506 1507
}

/*PDCP rx sequence number flexRAN*/
1508
uint32_t flexran_get_pdcp_rx_sn(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1509 1510 1511
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1512

1513
  return Pdcp_stats_rx_sn[mod_id][uid][lcid];
1514 1515 1516
}

/*PDCP rx aggregated packet arrival  flexRAN*/
1517
uint32_t flexran_get_pdcp_rx_aiat(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1518 1519 1520
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1521

1522
  return Pdcp_stats_rx_aiat[mod_id][uid][lcid];
1523 1524 1525
}

/*PDCP rx aggregated packet arrival  flexRAN*/
1526
uint32_t flexran_get_pdcp_rx_aiat_w(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1527 1528 1529
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1530

1531
  return Pdcp_stats_rx_aiat_w[mod_id][uid][lcid];
1532 1533 1534
}

/*PDCP num of received outoforder pdu status flexRAN*/
1535
uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, uint16_t uid, lcid_t lcid) {
1536 1537 1538
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1539

1540
  return Pdcp_stats_rx_outoforder[mod_id][uid][lcid];
1541
}
1542

1543
/******************** RRC *****************************/
1544 1545 1546
/* RRC Wrappers */
int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return -1;
1547

1548 1549
  protocol_ctxt_t  ctxt;
  memset(&ctxt, 0, sizeof(ctxt));
1550 1551
  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

1552
  if (!ue_context_p) return -1;
1553

1554 1555 1556 1557 1558
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, mod_id, ENB_FLAG_YES, ue_context_p->ue_context.rnti, flexran_get_current_frame(mod_id), flexran_get_current_subframe (mod_id), mod_id);
  flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(&ctxt, ue_context_p, 0);
  return 0;
}

1559 1560
int flexran_call_rrc_trigger_handover (mid_t mod_id, rnti_t rnti, int target_cell_id) {
  if (!rrc_is_present(mod_id)) return -1;
1561

1562 1563
  protocol_ctxt_t  ctxt;
  memset(&ctxt, 0, sizeof(ctxt));
1564 1565
  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

1566
  if (!ue_context_p) return -1;
1567

1568 1569 1570 1571
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, mod_id, ENB_FLAG_YES, ue_context_p->ue_context.rnti, flexran_get_current_frame(mod_id), flexran_get_current_subframe (mod_id), mod_id);
  return flexran_rrc_eNB_trigger_handover(mod_id, &ctxt, ue_context_p, target_cell_id);
}

1572
/* RRC Getters */
1573

1574
LTE_MeasId_t  flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti) {
1575
  if (!rrc_is_present(mod_id)) return -1;
1576 1577 1578

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1579
  if (!ue_context_p) return -1;
1580

Robert Schmidt's avatar
Robert Schmidt committed
1581
  if (!ue_context_p->ue_context.measResults) return -1;
1582

Robert Schmidt's avatar
Robert Schmidt committed
1583
  return ue_context_p->ue_context.measResults->measId;
1584
}
1585

1586
float flexran_get_rrc_pcell_rsrp(mid_t mod_id, rnti_t rnti) {
1587
  if (!rrc_is_present(mod_id)) return -1;
1588 1589 1590

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1591
  if (!ue_context_p) return -1;
1592

Robert Schmidt's avatar
Robert Schmidt committed
1593
  if (!ue_context_p->ue_context.measResults) return -1;
1594 1595

  return RSRP_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrpResult];
1596 1597
}

1598
float flexran_get_rrc_pcell_rsrq(mid_t mod_id, rnti_t rnti) {
1599
  if (!rrc_is_present(mod_id)) return -1;
1600 1601 1602

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1603
  if (!ue_context_p) return -1;
1604

Robert Schmidt's avatar
Robert Schmidt committed
1605
  if (!ue_context_p->ue_context.measResults) return -1;
1606 1607

  return RSRQ_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrqResult];
1608 1609
}

Robert Schmidt's avatar
Robert Schmidt committed
1610
/*Number of neighbouring cells for specific UE*/
1611
int flexran_get_rrc_num_ncell(mid_t mod_id, rnti_t rnti) {
1612
  if (!rrc_is_present(mod_id)) return 0;
1613 1614 1615

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1616
  if (!ue_context_p) return 0;
1617

Robert Schmidt's avatar
Robert Schmidt committed
1618
  if (!ue_context_p->ue_context.measResults) return 0;
1619

Robert Schmidt's avatar
Robert Schmidt committed
1620
  if (!ue_context_p->ue_context.measResults->measResultNeighCells) return 0;
1621

1622
  //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return 0;
Robert Schmidt's avatar
Robert Schmidt committed
1623 1624
  return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.count;
}
1625

1626
long flexran_get_rrc_neigh_phy_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) {
1627
  if (!rrc_is_present(mod_id)) return -1;
1628 1629 1630

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1631
  if (!ue_context_p) return -1;
1632

Robert Schmidt's avatar
Robert Schmidt committed
1633
  if (!ue_context_p->ue_context.measResults) return -1;
1634

Robert Schmidt's avatar
Robert Schmidt committed
1635
  if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1;
1636

1637
  //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1;
Robert Schmidt's avatar
Robert Schmidt committed
1638
  if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1;
1639

Robert Schmidt's avatar
Robert Schmidt committed
1640 1641
  return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->physCellId;
}
1642

1643 1644
int flexran_get_rrc_neigh_cgi(mid_t mod_id, rnti_t rnti, long cell_id) {
  if (!rrc_is_present(mod_id)) return 0;
1645 1646 1647

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

1648
  if (!ue_context_p) return 0;
1649

1650
  if (!ue_context_p->ue_context.measResults) return 0;
1651

1652
  if (!ue_context_p->ue_context.measResults->measResultNeighCells) return 0;
1653

1654 1655
  //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return 0;
  if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return 0;
1656

1657 1658 1659
  return (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info)?0:1;
}

1660
uint32_t flexran_get_rrc_neigh_cgi_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) {
1661
  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
1662 1663 1664 1665 1666
  uint8_t *cId = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.cellIdentity.buf;
  return ((cId[0] << 20) + (cId[1] << 12) + (cId[2] << 4) + (cId[3] >> 4));
}

uint32_t flexran_get_rrc_neigh_cgi_tac(mid_t mod_id, rnti_t rnti, long cell_id) {
1667
  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
1668 1669 1670 1671
  uint8_t *tac = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->trackingAreaCode.buf;
  return (tac[0] << 8) + (tac[1]);
}

1672
int flexran_get_rrc_neigh_cgi_num_mnc(mid_t mod_id, rnti_t rnti, long cell_id) {
1673
  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
1674 1675 1676
  return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.count;
}

1677
int flexran_get_rrc_neigh_cgi_num_mcc(mid_t mod_id, rnti_t rnti, long cell_id) {
1678
  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
1679 1680 1681 1682
  return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.count;
}

uint32_t flexran_get_rrc_neigh_cgi_mnc(mid_t mod_id, rnti_t rnti, long cell_id, int mnc_id) {
1683
  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
1684 1685
  int num_mnc = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.count;
  return *(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.array[mnc_id]) *
1686
         ((uint32_t) pow(10, num_mnc - mnc_id - 1));
1687 1688 1689
}

uint32_t flexran_get_rrc_neigh_cgi_mcc(mid_t mod_id, rnti_t rnti, long cell_id, int mcc_id) {
1690
  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
1691 1692
  int num_mcc = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.count;
  return *(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.array[mcc_id]) *
1693
         ((uint32_t) pow(10, num_mcc - mcc_id - 1));
1694 1695 1696
}

float flexran_get_rrc_neigh_rsrp(mid_t mod_id, rnti_t rnti, long cell_id) {
1697
  if (!rrc_is_present(mod_id)) return -1;
1698 1699 1700

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1701
  if (!ue_context_p) return -1;
1702

Robert Schmidt's avatar
Robert Schmidt committed
1703
  if (!ue_context_p->ue_context.measResults) return -1;
1704

Robert Schmidt's avatar
Robert Schmidt committed
1705
  if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1;
1706

1707
  //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1;
Robert Schmidt's avatar
Robert Schmidt committed
1708
  if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1;
1709

1710
  if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrpResult) return -1;
1711

Robert Schmidt's avatar
Robert Schmidt committed
1712
  return RSRP_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrpResult)];
1713 1714
}

1715
float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id) {
1716
  if (!rrc_is_present(mod_id)) return -1;
1717 1718 1719

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

Robert Schmidt's avatar
Robert Schmidt committed
1720
  if (!ue_context_p) return -1;
1721

Robert Schmidt's avatar
Robert Schmidt committed
1722
  if (!ue_context_p->ue_context.measResults) return -1;
1723

Robert Schmidt's avatar
Robert Schmidt committed
1724
  if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1;
1725

1726 1727
  //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1;
  if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult) return -1;
1728

Robert Schmidt's avatar
Robert Schmidt committed
1729
  return RSRQ_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult)];
1730
}
1731

1732 1733
/* Measurement offsets */

1734 1735
long flexran_get_rrc_ofp(mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return -1;
1736 1737 1738

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

1739
  if (!ue_context_p) return -1;
1740

1741
  if (!ue_context_p->ue_context.measurement_info) return -1;
1742

1743 1744 1745 1746 1747
  return ue_context_p->ue_context.measurement_info->offsetFreq;
}

long flexran_get_rrc_ofn(mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return -1;
1748 1749 1750

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

1751
  if (!ue_context_p) return -1;
1752

1753
  if (!ue_context_p->ue_context.measurement_info) return -1;
1754

1755 1756 1757 1758 1759
  return ue_context_p->ue_context.measurement_info->offsetFreq;
}

long flexran_get_rrc_ocp(mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return -1;
1760 1761 1762

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

1763
  if (!ue_context_p) return -1;
1764

1765
  if (!ue_context_p->ue_context.measurement_info) return -1;
1766

1767
  switch (ue_context_p->ue_context.measurement_info->cellIndividualOffset[0]) {
1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862
    case LTE_Q_OffsetRange_dB_24:
      return -24;

    case LTE_Q_OffsetRange_dB_22:
      return -22;

    case LTE_Q_OffsetRange_dB_20:
      return -20;

    case LTE_Q_OffsetRange_dB_18:
      return -18;

    case LTE_Q_OffsetRange_dB_16:
      return -16;

    case LTE_Q_OffsetRange_dB_14:
      return -14;

    case LTE_Q_OffsetRange_dB_12:
      return -12;

    case LTE_Q_OffsetRange_dB_10:
      return -10;

    case LTE_Q_OffsetRange_dB_8:
      return -8;

    case LTE_Q_OffsetRange_dB_6:
      return -6;

    case LTE_Q_OffsetRange_dB_5:
      return -5;

    case LTE_Q_OffsetRange_dB_4:
      return -4;

    case LTE_Q_OffsetRange_dB_3:
      return -3;

    case LTE_Q_OffsetRange_dB_2:
      return -2;

    case LTE_Q_OffsetRange_dB_1:
      return -1;

    case LTE_Q_OffsetRange_dB0:
      return  0;

    case LTE_Q_OffsetRange_dB1:
      return  1;

    case LTE_Q_OffsetRange_dB2:
      return  2;

    case LTE_Q_OffsetRange_dB3:
      return  3;

    case LTE_Q_OffsetRange_dB4:
      return  4;

    case LTE_Q_OffsetRange_dB5:
      return  5;

    case LTE_Q_OffsetRange_dB6:
      return  6;

    case LTE_Q_OffsetRange_dB8:
      return  8;

    case LTE_Q_OffsetRange_dB10:
      return 10;

    case LTE_Q_OffsetRange_dB12:
      return 12;

    case LTE_Q_OffsetRange_dB14:
      return 14;

    case LTE_Q_OffsetRange_dB16:
      return 16;

    case LTE_Q_OffsetRange_dB18:
      return 18;

    case LTE_Q_OffsetRange_dB20:
      return 20;

    case LTE_Q_OffsetRange_dB22:
      return 22;

    case LTE_Q_OffsetRange_dB24:
      return 24;

    default:
      return -99;
1863
  }
1864 1865
}

1866
long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id) {
1867
  if (!rrc_is_present(mod_id)) return -1;
1868 1869 1870

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

1871
  if (!ue_context_p) return -1;
1872

1873
  if (!ue_context_p->ue_context.measurement_info) return -1;
1874

1875
  switch (ue_context_p->ue_context.measurement_info->cellIndividualOffset[cell_id+1]) {
1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970
    case LTE_Q_OffsetRange_dB_24:
      return -24;

    case LTE_Q_OffsetRange_dB_22:
      return -22;

    case LTE_Q_OffsetRange_dB_20:
      return -20;

    case LTE_Q_OffsetRange_dB_18:
      return -18;

    case LTE_Q_OffsetRange_dB_16:
      return -16;

    case LTE_Q_OffsetRange_dB_14:
      return -14;

    case LTE_Q_OffsetRange_dB_12:
      return -12;

    case LTE_Q_OffsetRange_dB_10:
      return -10;

    case LTE_Q_OffsetRange_dB_8:
      return -8;

    case LTE_Q_OffsetRange_dB_6:
      return -6;

    case LTE_Q_OffsetRange_dB_5:
      return -5;

    case LTE_Q_OffsetRange_dB_4:
      return -4;

    case LTE_Q_OffsetRange_dB_3:
      return -3;

    case LTE_Q_OffsetRange_dB_2:
      return -2;

    case LTE_Q_OffsetRange_dB_1:
      return -1;

    case LTE_Q_OffsetRange_dB0:
      return  0;

    case LTE_Q_OffsetRange_dB1:
      return  1;

    case LTE_Q_OffsetRange_dB2:
      return  2;

    case LTE_Q_OffsetRange_dB3:
      return  3;

    case LTE_Q_OffsetRange_dB4:
      return  4;

    case LTE_Q_OffsetRange_dB5:
      return  5;

    case LTE_Q_OffsetRange_dB6:
      return  6;

    case LTE_Q_OffsetRange_dB8:
      return  8;

    case LTE_Q_OffsetRange_dB10:
      return 10;

    case LTE_Q_OffsetRange_dB12:
      return 12;

    case LTE_Q_OffsetRange_dB14:
      return 14;

    case LTE_Q_OffsetRange_dB16:
      return 16;

    case LTE_Q_OffsetRange_dB18:
      return 18;

    case LTE_Q_OffsetRange_dB20:
      return 20;

    case LTE_Q_OffsetRange_dB22:
      return 22;

    case LTE_Q_OffsetRange_dB24:
      return 24;

    default:
      return -99;
1971
  }
1972 1973
}

1974 1975
long flexran_get_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return -1;
1976 1977 1978

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

1979
  if (!ue_context_p) return -1;
1980

1981
  if (!ue_context_p->ue_context.measurement_info) return -1;
1982

1983
  switch (ue_context_p->ue_context.measurement_info->filterCoefficientRSRP) {
1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033
    case LTE_FilterCoefficient_fc0:
      return 0;

    case LTE_FilterCoefficient_fc1:
      return 1;

    case LTE_FilterCoefficient_fc2:
      return 2;

    case LTE_FilterCoefficient_fc3:
      return 3;

    case LTE_FilterCoefficient_fc4:
      return 4;

    case LTE_FilterCoefficient_fc5:
      return 5;

    case LTE_FilterCoefficient_fc6:
      return 6;

    case LTE_FilterCoefficient_fc7:
      return 7;

    case LTE_FilterCoefficient_fc8:
      return 8;

    case LTE_FilterCoefficient_fc9:
      return 9;

    case LTE_FilterCoefficient_fc11:
      return 11;

    case LTE_FilterCoefficient_fc13:
      return 13;

    case LTE_FilterCoefficient_fc15:
      return 15;

    case LTE_FilterCoefficient_fc17:
      return 17;

    case LTE_FilterCoefficient_fc19:
      return 19;

    case LTE_FilterCoefficient_spare1:
      return -1; /* spare means no coefficient */

    default:
      return -1;
2034
  }
2035 2036 2037 2038
}

long flexran_get_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return -1;
2039 2040 2041

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2042
  if (!ue_context_p) return -1;
2043

2044
  if (!ue_context_p->ue_context.measurement_info) return -1;
2045

2046
  switch (ue_context_p->ue_context.measurement_info->filterCoefficientRSRQ) {
2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096
    case LTE_FilterCoefficient_fc0:
      return 0;

    case LTE_FilterCoefficient_fc1:
      return 1;

    case LTE_FilterCoefficient_fc2:
      return 2;

    case LTE_FilterCoefficient_fc3:
      return 3;

    case LTE_FilterCoefficient_fc4:
      return 4;

    case LTE_FilterCoefficient_fc5:
      return 5;

    case LTE_FilterCoefficient_fc6:
      return 6;

    case LTE_FilterCoefficient_fc7:
      return 7;

    case LTE_FilterCoefficient_fc8:
      return 8;

    case LTE_FilterCoefficient_fc9:
      return 9;

    case LTE_FilterCoefficient_fc11:
      return 11;

    case LTE_FilterCoefficient_fc13:
      return 13;

    case LTE_FilterCoefficient_fc15:
      return 15;

    case LTE_FilterCoefficient_fc17:
      return 17;

    case LTE_FilterCoefficient_fc19:
      return 19;

    case LTE_FilterCoefficient_spare1:
      return -1; /* spare means no coefficient */

    default:
      return -1;
2097
  }
2098 2099
}

2100 2101 2102 2103
/* Periodic event */

long flexran_get_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return -1;
2104 2105 2106

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2107
  if (!ue_context_p) return -1;
2108

2109
  if (!ue_context_p->ue_context.measurement_info) return -1;
2110

2111
  if (!ue_context_p->ue_context.measurement_info->events) return -1;
2112

2113
  if (!ue_context_p->ue_context.measurement_info->events->per_event) return -1;
2114

2115 2116 2117 2118 2119 2120 2121
  return ue_context_p->ue_context.measurement_info->events->per_event->maxReportCells;
}

/* A3 event */

long flexran_get_rrc_a3_event_hysteresis(mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return -1;
2122 2123 2124

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2125
  if (!ue_context_p) return -1;
2126

2127
  if (!ue_context_p->ue_context.measurement_info) return -1;
2128

2129
  if (!ue_context_p->ue_context.measurement_info->events) return -1;
2130

2131
  if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1;
2132

2133 2134 2135 2136 2137
  return ue_context_p->ue_context.measurement_info->events->a3_event->hysteresis;
}

long flexran_get_rrc_a3_event_timeToTrigger(mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return -1;
2138 2139 2140

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2141
  if (!ue_context_p) return -1;
2142

2143
  if (!ue_context_p->ue_context.measurement_info) return -1;
2144

2145
  if (!ue_context_p->ue_context.measurement_info->events) return -1;
2146

2147
  if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1;
2148

2149
  switch (ue_context_p->ue_context.measurement_info->events->a3_event->timeToTrigger) {
2150 2151
    case LTE_TimeToTrigger_ms0:
      return 0;
2152

2153 2154
    case LTE_TimeToTrigger_ms40:
      return 40;
2155

2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203
    case LTE_TimeToTrigger_ms64:
      return 64;

    case LTE_TimeToTrigger_ms80:
      return 80;

    case LTE_TimeToTrigger_ms100:
      return 100;

    case LTE_TimeToTrigger_ms128:
      return 128;

    case LTE_TimeToTrigger_ms160:
      return 160;

    case LTE_TimeToTrigger_ms256:
      return 256;

    case LTE_TimeToTrigger_ms320:
      return 320;

    case LTE_TimeToTrigger_ms480:
      return 480;

    case LTE_TimeToTrigger_ms512:
      return 512;

    case LTE_TimeToTrigger_ms640:
      return 640;

    case LTE_TimeToTrigger_ms1024:
      return 1024;

    case LTE_TimeToTrigger_ms1280:
      return 1280;

    case LTE_TimeToTrigger_ms2560:
      return 2560;

    case LTE_TimeToTrigger_ms5120:
      return 5120;

    default:
      return -1;
  }
}

long flexran_get_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti) {
2204
  if (!rrc_is_present(mod_id)) return -1;
2205 2206 2207

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2208
  if (!ue_context_p) return -1;
2209

2210
  if (!ue_context_p->ue_context.measurement_info) return -1;
2211

2212
  if (!ue_context_p->ue_context.measurement_info->events) return -1;
2213

2214
  if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1;
2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231

  return ue_context_p->ue_context.measurement_info->events->a3_event->maxReportCells;
}

long flexran_get_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return -1;

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

  if (!ue_context_p) return -1;

  if (!ue_context_p->ue_context.measurement_info) return -1;

  if (!ue_context_p->ue_context.measurement_info->events) return -1;

  if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1;

2232 2233 2234 2235 2236
  return ue_context_p->ue_context.measurement_info->events->a3_event->a3_offset;
}

int flexran_get_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return -1;
2237 2238 2239

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2240
  if (!ue_context_p) return -1;
2241

2242
  if (!ue_context_p->ue_context.measurement_info) return -1;
2243

2244
  if (!ue_context_p->ue_context.measurement_info->events) return -1;
2245

2246
  if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1;
2247

2248 2249 2250
  return ue_context_p->ue_context.measurement_info->events->a3_event->reportOnLeave;
}

2251 2252 2253 2254 2255 2256
/* RRC Setters */

/* Measurement offsets */

int flexran_set_rrc_ofp(mid_t mod_id, rnti_t rnti, long offsetFreq) {
  if (!rrc_is_present(mod_id)) return -1;
2257 2258 2259

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2260
  if (!ue_context_p) return -1;
2261

2262
  if (!ue_context_p->ue_context.measurement_info) return -1;
2263

2264
  if (!((offsetFreq >= -15) && (offsetFreq <= 15))) return -1;
2265

2266 2267 2268 2269 2270 2271
  ue_context_p->ue_context.measurement_info->offsetFreq = offsetFreq;
  return 0;
}

int flexran_set_rrc_ofn(mid_t mod_id, rnti_t rnti, long offsetFreq) {
  if (!rrc_is_present(mod_id)) return -1;
2272 2273 2274

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2275
  if (!ue_context_p) return -1;
2276

2277
  if (!ue_context_p->ue_context.measurement_info) return -1;
2278

2279
  if (!((offsetFreq >= -15) && (offsetFreq <= 15))) return -1;
2280

2281 2282 2283 2284 2285 2286
  ue_context_p->ue_context.measurement_info->offsetFreq = offsetFreq;
  return 0;
}

int flexran_set_rrc_ocp(mid_t mod_id, rnti_t rnti, long cellIndividualOffset) {
  if (!rrc_is_present(mod_id)) return -1;
2287 2288 2289

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2290
  if (!ue_context_p) return -1;
2291

2292
  if (!ue_context_p->ue_context.measurement_info) return -1;
2293

2294
  LTE_Q_OffsetRange_t *cio = &ue_context_p->ue_context.measurement_info->cellIndividualOffset[0];
2295

2296
  switch (cellIndividualOffset) {
2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422
    case -24:
      *cio = LTE_Q_OffsetRange_dB_24;
      break;

    case -22:
      *cio = LTE_Q_OffsetRange_dB_22;
      break;

    case -20:
      *cio = LTE_Q_OffsetRange_dB_20;
      break;

    case -18:
      *cio = LTE_Q_OffsetRange_dB_18;
      break;

    case -16:
      *cio = LTE_Q_OffsetRange_dB_16;
      break;

    case -14:
      *cio = LTE_Q_OffsetRange_dB_14;
      break;

    case -12:
      *cio = LTE_Q_OffsetRange_dB_12;
      break;

    case -10:
      *cio = LTE_Q_OffsetRange_dB_10;
      break;

    case -8:
      *cio = LTE_Q_OffsetRange_dB_8;
      break;

    case -6:
      *cio = LTE_Q_OffsetRange_dB_6;
      break;

    case -5:
      *cio = LTE_Q_OffsetRange_dB_5;
      break;

    case -4:
      *cio = LTE_Q_OffsetRange_dB_4;
      break;

    case -3:
      *cio = LTE_Q_OffsetRange_dB_3;
      break;

    case -2:
      *cio = LTE_Q_OffsetRange_dB_2;
      break;

    case -1:
      *cio = LTE_Q_OffsetRange_dB_1;
      break;

    case 0:
      *cio = LTE_Q_OffsetRange_dB0;
      break;

    case 1:
      *cio = LTE_Q_OffsetRange_dB1;
      break;

    case 2:
      *cio = LTE_Q_OffsetRange_dB2;
      break;

    case 3:
      *cio = LTE_Q_OffsetRange_dB3;
      break;

    case 4:
      *cio = LTE_Q_OffsetRange_dB4;
      break;

    case 5:
      *cio = LTE_Q_OffsetRange_dB5;
      break;

    case 6:
      *cio = LTE_Q_OffsetRange_dB6;
      break;

    case 8:
      *cio = LTE_Q_OffsetRange_dB8;
      break;

    case 10:
      *cio = LTE_Q_OffsetRange_dB10;
      break;

    case 12:
      *cio = LTE_Q_OffsetRange_dB12;
      break;

    case 14:
      *cio = LTE_Q_OffsetRange_dB14;
      break;

    case 16:
      *cio = LTE_Q_OffsetRange_dB16;
      break;

    case 18:
      *cio = LTE_Q_OffsetRange_dB18;
      break;

    case 20:
      *cio = LTE_Q_OffsetRange_dB20;
      break;

    case 22:
      *cio = LTE_Q_OffsetRange_dB22;
      break;

    case 24:
      *cio = LTE_Q_OffsetRange_dB24;
      break;

    default:
      return -1;
2423
  }
2424

2425 2426 2427 2428 2429
  return 0;
}

int flexran_set_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id, long cellIndividualOffset) {
  if (!rrc_is_present(mod_id)) return -1;
2430 2431 2432

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2433
  if (!ue_context_p) return -1;
2434

2435
  if (!ue_context_p->ue_context.measurement_info) return -1;
2436

2437
  LTE_Q_OffsetRange_t *cio = &ue_context_p->ue_context.measurement_info->cellIndividualOffset[cell_id+1];
2438

2439
  switch (cellIndividualOffset) {
2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565
    case -24:
      *cio = LTE_Q_OffsetRange_dB_24;
      break;

    case -22:
      *cio = LTE_Q_OffsetRange_dB_22;
      break;

    case -20:
      *cio = LTE_Q_OffsetRange_dB_20;
      break;

    case -18:
      *cio = LTE_Q_OffsetRange_dB_18;
      break;

    case -16:
      *cio = LTE_Q_OffsetRange_dB_16;
      break;

    case -14:
      *cio = LTE_Q_OffsetRange_dB_14;
      break;

    case -12:
      *cio = LTE_Q_OffsetRange_dB_12;
      break;

    case -10:
      *cio = LTE_Q_OffsetRange_dB_10;
      break;

    case -8:
      *cio = LTE_Q_OffsetRange_dB_8;
      break;

    case -6:
      *cio = LTE_Q_OffsetRange_dB_6;
      break;

    case -5:
      *cio = LTE_Q_OffsetRange_dB_5;
      break;

    case -4:
      *cio = LTE_Q_OffsetRange_dB_4;
      break;

    case -3:
      *cio = LTE_Q_OffsetRange_dB_3;
      break;

    case -2:
      *cio = LTE_Q_OffsetRange_dB_2;
      break;

    case -1:
      *cio = LTE_Q_OffsetRange_dB_1;
      break;

    case 0:
      *cio = LTE_Q_OffsetRange_dB0;
      break;

    case 1:
      *cio = LTE_Q_OffsetRange_dB1;
      break;

    case 2:
      *cio = LTE_Q_OffsetRange_dB2;
      break;

    case 3:
      *cio = LTE_Q_OffsetRange_dB3;
      break;

    case 4:
      *cio = LTE_Q_OffsetRange_dB4;
      break;

    case 5:
      *cio = LTE_Q_OffsetRange_dB5;
      break;

    case 6:
      *cio = LTE_Q_OffsetRange_dB6;
      break;

    case 8:
      *cio = LTE_Q_OffsetRange_dB8;
      break;

    case 10:
      *cio = LTE_Q_OffsetRange_dB10;
      break;

    case 12:
      *cio = LTE_Q_OffsetRange_dB12;
      break;

    case 14:
      *cio = LTE_Q_OffsetRange_dB14;
      break;

    case 16:
      *cio = LTE_Q_OffsetRange_dB16;
      break;

    case 18:
      *cio = LTE_Q_OffsetRange_dB18;
      break;

    case 20:
      *cio = LTE_Q_OffsetRange_dB20;
      break;

    case 22:
      *cio = LTE_Q_OffsetRange_dB22;
      break;

    case 24:
      *cio = LTE_Q_OffsetRange_dB24;
      break;

    default:
      return -1;
2566
  }
2567

2568 2569 2570 2571 2572
  return 0;
}

int flexran_set_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti, long filterCoefficientRSRP) {
  if (!rrc_is_present(mod_id)) return -1;
2573 2574 2575

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2576
  if (!ue_context_p) return -1;
2577

2578
  if (!ue_context_p->ue_context.measurement_info) return -1;
2579

2580
  LTE_FilterCoefficient_t *fc = &ue_context_p->ue_context.measurement_info->filterCoefficientRSRP;
2581

2582
  switch (filterCoefficientRSRP) {
2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648
    case 0:
      *fc = LTE_FilterCoefficient_fc0;
      break;

    case 1:
      *fc = LTE_FilterCoefficient_fc1;
      break;

    case 2:
      *fc = LTE_FilterCoefficient_fc2;
      break;

    case 3:
      *fc = LTE_FilterCoefficient_fc3;
      break;

    case 4:
      *fc = LTE_FilterCoefficient_fc4;
      break;

    case 5:
      *fc = LTE_FilterCoefficient_fc5;
      break;

    case 6:
      *fc = LTE_FilterCoefficient_fc6;
      break;

    case 7:
      *fc = LTE_FilterCoefficient_fc7;
      break;

    case 8:
      *fc = LTE_FilterCoefficient_fc8;
      break;

    case 9:
      *fc = LTE_FilterCoefficient_fc9;
      break;

    case 11:
      *fc = LTE_FilterCoefficient_fc11;
      break;

    case 13:
      *fc = LTE_FilterCoefficient_fc13;
      break;

    case 15:
      *fc = LTE_FilterCoefficient_fc15;
      break;

    case 17:
      *fc = LTE_FilterCoefficient_fc17;
      break;

    case 19:
      *fc = LTE_FilterCoefficient_fc19;
      break;

    case -1:
      *fc = LTE_FilterCoefficient_spare1;
      break;

    default:
      return -1;
2649
  }
2650

2651 2652 2653 2654 2655
  return 0;
}

int flexran_set_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti, long filterCoefficientRSRQ) {
  if (!rrc_is_present(mod_id)) return -1;
2656 2657 2658

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2659
  if (!ue_context_p) return -1;
2660

2661
  if (!ue_context_p->ue_context.measurement_info) return -1;
2662

2663
  LTE_FilterCoefficient_t *fc = &ue_context_p->ue_context.measurement_info->filterCoefficientRSRQ;
2664

2665
  switch (filterCoefficientRSRQ) {
2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731
    case 0:
      *fc = LTE_FilterCoefficient_fc0;
      break;

    case 1:
      *fc = LTE_FilterCoefficient_fc1;
      break;

    case 2:
      *fc = LTE_FilterCoefficient_fc2;
      break;

    case 3:
      *fc = LTE_FilterCoefficient_fc3;
      break;

    case 4:
      *fc = LTE_FilterCoefficient_fc4;
      break;

    case 5:
      *fc = LTE_FilterCoefficient_fc5;
      break;

    case 6:
      *fc = LTE_FilterCoefficient_fc6;
      break;

    case 7:
      *fc = LTE_FilterCoefficient_fc7;
      break;

    case 8:
      *fc = LTE_FilterCoefficient_fc8;
      break;

    case 9:
      *fc = LTE_FilterCoefficient_fc9;
      break;

    case 11:
      *fc = LTE_FilterCoefficient_fc11;
      break;

    case 13:
      *fc = LTE_FilterCoefficient_fc13;
      break;

    case 15:
      *fc = LTE_FilterCoefficient_fc15;
      break;

    case 17:
      *fc = LTE_FilterCoefficient_fc17;
      break;

    case 19:
      *fc = LTE_FilterCoefficient_fc19;
      break;

    case -1:
      *fc = LTE_FilterCoefficient_spare1;
      break;

    default:
      return -1;
2732
  }
2733

2734 2735 2736 2737 2738 2739 2740
  return 0;
}

/* Periodic event */

int flexran_set_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti, long maxReportCells) {
  if (!rrc_is_present(mod_id)) return -1;
2741 2742 2743

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2744
  if (!ue_context_p) return -1;
2745

2746
  if (!ue_context_p->ue_context.measurement_info) return -1;
2747

2748
  if (!ue_context_p->ue_context.measurement_info->events) return -1;
2749

2750
  if (!ue_context_p->ue_context.measurement_info->events->per_event) return -1;
2751

2752
  if (!((maxReportCells >= 1) && (maxReportCells <= 8))) return -1;
2753

2754 2755 2756 2757 2758 2759 2760 2761
  ue_context_p->ue_context.measurement_info->events->per_event->maxReportCells = maxReportCells;
  return 0;
}

/* A3 event */

int flexran_set_rrc_a3_event_hysteresis(mid_t mod_id, rnti_t rnti, long hysteresis) {
  if (!rrc_is_present(mod_id)) return -1;
2762 2763 2764

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2765
  if (!ue_context_p) return -1;
2766

2767
  if (!ue_context_p->ue_context.measurement_info) return -1;
2768

2769
  if (!ue_context_p->ue_context.measurement_info->events) return -1;
2770

2771
  if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1;
2772

2773
  if (!((hysteresis >=0) && (hysteresis <= 30))) return -1;
2774

2775 2776 2777 2778 2779 2780
  ue_context_p->ue_context.measurement_info->events->a3_event->hysteresis = hysteresis;
  return 0;
}

int flexran_set_rrc_a3_event_timeToTrigger(mid_t mod_id, rnti_t rnti, long timeToTrigger) {
  if (!rrc_is_present(mod_id)) return -1;
2781 2782 2783

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2784
  if (!ue_context_p) return -1;
2785

2786
  if (!ue_context_p->ue_context.measurement_info) return -1;
2787

2788
  if (!ue_context_p->ue_context.measurement_info->events) return -1;
2789

2790
  if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1;
2791

2792
  LTE_TimeToTrigger_t *ttt = &ue_context_p->ue_context.measurement_info->events->a3_event->timeToTrigger;
2793

2794
  switch (timeToTrigger) {
2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860
    case 0:
      *ttt = LTE_TimeToTrigger_ms0;
      break;

    case 40:
      *ttt = LTE_TimeToTrigger_ms40;
      break;

    case 64:
      *ttt = LTE_TimeToTrigger_ms64;
      break;

    case 80:
      *ttt = LTE_TimeToTrigger_ms80;
      break;

    case 100:
      *ttt = LTE_TimeToTrigger_ms100;
      break;

    case 128:
      *ttt = LTE_TimeToTrigger_ms128;
      break;

    case 160:
      *ttt = LTE_TimeToTrigger_ms160;
      break;

    case 256:
      *ttt = LTE_TimeToTrigger_ms256;
      break;

    case 320:
      *ttt = LTE_TimeToTrigger_ms320;
      break;

    case 480:
      *ttt = LTE_TimeToTrigger_ms480;
      break;

    case 512:
      *ttt = LTE_TimeToTrigger_ms512;
      break;

    case 640:
      *ttt = LTE_TimeToTrigger_ms640;
      break;

    case 1024:
      *ttt = LTE_TimeToTrigger_ms1024;
      break;

    case 1280:
      *ttt = LTE_TimeToTrigger_ms1280;
      break;

    case 2560:
      *ttt = LTE_TimeToTrigger_ms2560;
      break;

    case 5120:
      *ttt = LTE_TimeToTrigger_ms5120;
      break;

    default:
      return -1;
2861
  }
2862

2863 2864 2865 2866 2867
  return 0;
}

int flexran_set_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti, long maxReportCells) {
  if (!rrc_is_present(mod_id)) return -1;
2868 2869 2870

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2871
  if (!ue_context_p) return -1;
2872

2873
  if (!ue_context_p->ue_context.measurement_info) return -1;
2874

2875
  if (!ue_context_p->ue_context.measurement_info->events) return -1;
2876

2877
  if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1;
2878

2879
  if (!((maxReportCells >= 1) && (maxReportCells <= 8))) return -1;
2880

2881 2882 2883 2884 2885 2886
  ue_context_p->ue_context.measurement_info->events->a3_event->maxReportCells = maxReportCells;
  return 0;
}

int flexran_set_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti, long a3_offset) {
  if (!rrc_is_present(mod_id)) return -1;
2887 2888 2889

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2890
  if (!ue_context_p) return -1;
2891

2892
  if (!ue_context_p->ue_context.measurement_info) return -1;
2893

2894
  if (!ue_context_p->ue_context.measurement_info->events) return -1;
2895

2896
  if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1;
2897

2898
  if (!((a3_offset >= -30) && (a3_offset <= 30))) return -1;
2899

2900 2901 2902 2903 2904 2905
  ue_context_p->ue_context.measurement_info->events->a3_event->a3_offset = a3_offset;
  return 0;
}

int flexran_set_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti, int reportOnLeave) {
  if (!rrc_is_present(mod_id)) return -1;
2906 2907 2908

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2909
  if (!ue_context_p) return -1;
2910

2911
  if (!ue_context_p->ue_context.measurement_info) return -1;
2912

2913
  if (!ue_context_p->ue_context.measurement_info->events) return -1;
2914

2915
  if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1;
2916

2917
  if (!((reportOnLeave == 0) || (reportOnLeave == 1))) return -1;
2918

2919 2920 2921 2922
  ue_context_p->ue_context.measurement_info->events->a3_event->reportOnLeave = reportOnLeave;
  return 0;
}

2923 2924
int flexran_set_x2_ho_net_control(mid_t mod_id, int x2_ho_net_control) {
  if (!rrc_is_present(mod_id)) return -1;
2925

2926
  if (!((x2_ho_net_control == 0) || (x2_ho_net_control == 1))) return -1;
2927

2928 2929 2930 2931 2932 2933
  RC.rrc[mod_id]->x2_ho_net_control = x2_ho_net_control;
  return 0;
}

int flexran_get_x2_ho_net_control(mid_t mod_id) {
  if (!rrc_is_present(mod_id)) return -1;
2934

2935 2936 2937
  return RC.rrc[mod_id]->x2_ho_net_control;
}

2938
uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id) {
2939
  if (!rrc_is_present(mod_id)) return 0;
2940

2941 2942 2943
  return RC.rrc[mod_id]->configuration.num_plmn;
}

2944
uint16_t flexran_get_rrc_mcc(mid_t mod_id, uint8_t index) {
2945
  if (!rrc_is_present(mod_id)) return 0;
2946

2947 2948 2949
  return RC.rrc[mod_id]->configuration.mcc[index];
}

2950
uint16_t flexran_get_rrc_mnc(mid_t mod_id, uint8_t index) {
2951
  if (!rrc_is_present(mod_id)) return 0;
2952

2953 2954 2955
  return RC.rrc[mod_id]->configuration.mnc[index];
}

2956
uint8_t flexran_get_rrc_mnc_digit_length(mid_t mod_id, uint8_t index) {
2957
  if (!rrc_is_present(mod_id)) return 0;
2958

2959 2960 2961
  return RC.rrc[mod_id]->configuration.mnc_digit_length[index];
}

2962 2963
int flexran_get_rrc_num_adj_cells(mid_t mod_id) {
  if (!rrc_is_present(mod_id)) return 0;
2964

2965 2966 2967
  return RC.rrc[mod_id]->num_neigh_cells;
}

2968 2969
int flexran_agent_rrc_gtp_num_e_rab(mid_t mod_id, rnti_t rnti) {
  if (!rrc_is_present(mod_id)) return 0;
2970 2971 2972

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2973
  if (!ue_context_p) return 0;
2974

2975 2976 2977 2978 2979
  return ue_context_p->ue_context.setup_e_rabs;
}

int flexran_agent_rrc_gtp_get_e_rab_id(mid_t mod_id, rnti_t rnti, int index) {
  if (!rrc_is_present(mod_id)) return 0;
2980 2981 2982

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2983
  if (!ue_context_p) return 0;
2984

2985 2986 2987 2988 2989
  return ue_context_p->ue_context.e_rab[index].param.e_rab_id;
}

int flexran_agent_rrc_gtp_get_teid_enb(mid_t mod_id, rnti_t rnti, int index) {
  if (!rrc_is_present(mod_id)) return 0;
2990 2991 2992

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

2993
  if (!ue_context_p) return 0;
2994

2995 2996 2997 2998 2999
  return ue_context_p->ue_context.enb_gtp_teid[index];
}

int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index) {
  if (!rrc_is_present(mod_id)) return 0;
3000 3001 3002

  struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);

3003
  if (!ue_context_p) return 0;
3004

3005 3006 3007
  return ue_context_p->ue_context.e_rab[index].param.gtp_teid;
}

3008 3009 3010 3011 3012 3013 3014 3015
uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti)
{
  if (!rrc_is_present(mod_id)) return 0;
  struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
  if (!ue_context_p) return -1;
  return ue_context_p->ue_context.eNB_ue_s1ap_id;
}

3016
/**************************** SLICING ****************************/
3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086
Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id) {
  if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None;

  switch (RC.mac[mod_id]->pre_processor_dl.algorithm) {
    case STATIC_SLICING:
      return PROTOCOL__FLEX_SLICE_ALGORITHM__Static;
    default:
      return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
  }
}

int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) {
  if (!mac_is_present(mod_id)) return 0;
  eNB_MAC_INST *mac = RC.mac[mod_id];
  const int cc_id = 0;

  pp_impl_param_t dl = mac->pre_processor_dl;
  switch (algo) {
    case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
      mac->pre_processor_dl = static_dl_init(mod_id, cc_id);
      break;
    default:
      mac->pre_processor_dl.algorithm = 0;
      mac->pre_processor_dl.dl = dlsch_scheduler_pre_processor;
      mac->pre_processor_dl.dl_algo.data = mac->pre_processor_dl.dl_algo.setup();
      mac->pre_processor_dl.slices = NULL;
      break;
  }
  if (dl.slices)
    dl.destroy(&dl.slices);
  if (dl.dl_algo.data)
    dl.dl_algo.unset(&dl.dl_algo.data);
  return 1;
}

Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id) {
  if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None;

  switch (RC.mac[mod_id]->pre_processor_ul.algorithm) {
    case STATIC_SLICING:
      return PROTOCOL__FLEX_SLICE_ALGORITHM__Static;
    default:
      return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
  }
}

int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) {
  if (!mac_is_present(mod_id)) return 0;
  eNB_MAC_INST *mac = RC.mac[mod_id];
  const int cc_id = 0;

  pp_impl_param_t ul = mac->pre_processor_ul;
  switch (algo) {
    case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
      mac->pre_processor_ul = static_ul_init(mod_id, cc_id);
      break;
    default:
      mac->pre_processor_ul.algorithm = 0;
      mac->pre_processor_ul.ul = ulsch_scheduler_pre_processor;
      mac->pre_processor_ul.ul_algo.data = mac->pre_processor_ul.ul_algo.setup();
      mac->pre_processor_ul.slices = NULL;
      break;
  }
  if (ul.slices)
    ul.destroy(&ul.slices);
  if (ul.ul_algo.data)
    ul.ul_algo.unset(&ul.ul_algo.data);
  return 1;
}

3087
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
3088
  if (!mac_is_present(mod_id)) return -1;
3089 3090 3091 3092 3093 3094
  slice_info_t *slices = RC.mac[mod_id]->pre_processor_dl.slices;
  if (!slices) return -1;
  const int idx = slices->UE_assoc_slice[ue_id];
  return slices->s[idx]->id;
}

3095 3096
int flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
  if (!mac_is_present(mod_id)) return 0;
3097
  int idx = flexran_find_dl_slice(mod_id, slice_id);
3098
  if (idx < 0) return 0;
3099 3100
  pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
  dl->move_UE(dl->slices, ue_id, idx);
3101
  return 1;
3102 3103
}

3104
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) {
3105
  if (!mac_is_present(mod_id)) return -1;
3106 3107 3108 3109
  slice_info_t *slices = RC.mac[mod_id]->pre_processor_ul.slices;
  if (!slices) return -1;
  const int idx = slices->UE_assoc_slice[ue_id];
  return slices->s[idx]->id;
3110 3111
}

3112 3113
int flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
  if (!mac_is_present(mod_id)) return 0;
3114
  int idx = flexran_find_ul_slice(mod_id, slice_id);
3115
  if (idx < 0) return 0;
3116 3117
  pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
  ul->move_UE(ul->slices, ue_id, idx);
3118
  return 1;
3119 3120
}

3121
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object) {
3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137
  if (!mac_is_present(mod_id)) return 0;
  void *params = NULL;
  switch (s->params_case) {
    case PROTOCOL__FLEX_SLICE__PARAMS_STATIC:
      params = malloc(sizeof(static_slice_param_t));
      if (!params) return 0;
      ((static_slice_param_t *)params)->posLow = s->static_->poslow;
      ((static_slice_param_t *)params)->posHigh = s->static_->poshigh;
      break;
    default:
      break;
  }
  pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
  char *l = s->label ? strdup(s->label) : NULL;
  void *algo = &dl->dl_algo; // default scheduler
  if (s->scheduler) {
3138
    algo = dlsym(object, s->scheduler);
3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153
    if (!algo) {
      free(params);
      LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
      return -15;
    }
  }
  return dl->addmod_slice(dl->slices, s->id, l, algo, params);
}

int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
  if (!mac_is_present(mod_id)) return 0;
  const int idx = flexran_find_dl_slice(mod_id, s->id);
  if (idx < 0) return 0;
  pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
  return dl->remove_slice(dl->slices, idx);
3154 3155
}

3156
int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) {
3157
  if (!mac_is_present(mod_id)) return -1;
3158 3159 3160 3161
  slice_info_t *si = RC.mac[mod_id]->pre_processor_dl.slices;
  for (int i = 0; i < si->num; ++i)
    if (si->s[i]->id == slice_id)
      return i;
3162
  return -1;
3163 3164
}

3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190
void flexran_get_dl_slice(mid_t mod_id,
                          int slice_idx,
                          Protocol__FlexSlice *slice,
                          Protocol__FlexSliceAlgorithm algo) {
  if (!mac_is_present(mod_id)) return;
  slice_t *s_ = RC.mac[mod_id]->pre_processor_dl.slices->s[slice_idx];
  slice->has_id = 1;
  slice->id = s_->id;
  slice->label = s_->label;
  slice->scheduler = s_->dl_algo.name;
  slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET;
  switch (algo) {
    case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
      slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic));
      if (!slice->static_) return;
      protocol__flex_slice_static__init(slice->static_);
      slice->static_->has_poslow = 1;
      slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow;
      slice->static_->has_poshigh = 1;
      slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh;
      slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC;
      break;
    default:
      break;
  }
}
3191

3192
int flexran_get_num_dl_slices(mid_t mod_id) {
3193 3194 3195
  if (!mac_is_present(mod_id)) return 0;
  if (!RC.mac[mod_id]->pre_processor_dl.slices) return 0;
  return RC.mac[mod_id]->pre_processor_dl.slices->num;
3196 3197
}

3198
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object) {
3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214
  if (!mac_is_present(mod_id)) return -1;
  void *params = NULL;
  switch (s->params_case) {
    case PROTOCOL__FLEX_SLICE__PARAMS_STATIC:
      params = malloc(sizeof(static_slice_param_t));
      if (!params) return 0;
      ((static_slice_param_t *)params)->posLow = s->static_->poslow;
      ((static_slice_param_t *)params)->posHigh = s->static_->poshigh;
      break;
    default:
      break;
  }
  pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
  char *l = s->label ? strdup(s->label) : NULL;
  void *algo = &ul->ul_algo; // default scheduler
  if (s->scheduler) {
3215
    algo = dlsym(object, s->scheduler);
3216 3217 3218 3219 3220 3221 3222
    if (!algo) {
      free(params);
      LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
      return -15;
    }
  }
  return ul->addmod_slice(ul->slices, s->id, l, algo, params);
3223 3224
}

3225 3226 3227 3228 3229 3230
int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
  if (!mac_is_present(mod_id)) return 0;
  const int idx = flexran_find_ul_slice(mod_id, s->id);
  if (idx < 0) return 0;
  pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
  return ul->remove_slice(ul->slices, idx);
3231 3232
}

3233
int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id) {
3234
  if (!mac_is_present(mod_id)) return -1;
3235 3236 3237 3238
  slice_info_t *si = RC.mac[mod_id]->pre_processor_ul.slices;
  for (int i = 0; i < si->num; ++i)
    if (si->s[i]->id == slice_id)
      return i;
3239 3240 3241
  return -1;
}

3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268
void flexran_get_ul_slice(mid_t mod_id,
                          int slice_idx,
                          Protocol__FlexSlice *slice,
                          Protocol__FlexSliceAlgorithm algo) {
  if (!mac_is_present(mod_id)) return;
  slice_t *s_ = RC.mac[mod_id]->pre_processor_ul.slices->s[slice_idx];
  slice->has_id = 1;
  slice->id = s_->id;
  slice->label = s_->label;
  slice->scheduler = s_->ul_algo.name;
  slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET;
  switch (algo) {
    case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
      slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic));
      if (!slice->static_) return;
      protocol__flex_slice_static__init(slice->static_);
      slice->static_->has_poslow = 1;
      slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow;
      slice->static_->has_poshigh = 1;
      slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh;
      slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC;
      break;
    default:
      break;
  }

}
3269

3270
int flexran_get_num_ul_slices(mid_t mod_id) {
3271 3272 3273 3274 3275 3276 3277 3278 3279 3280
  if (!mac_is_present(mod_id)) return 0;
  if (!RC.mac[mod_id]->pre_processor_ul.slices) return 0;
  return RC.mac[mod_id]->pre_processor_ul.slices->num;
}

char *flexran_get_dl_scheduler_name(mid_t mod_id) {
  if (!mac_is_present(mod_id)) return NULL;
  return RC.mac[mod_id]->pre_processor_dl.dl_algo.name;
}

3281
int flexran_set_dl_scheduler(mid_t mod_id, char *sched, void *object) {
3282
  if (!mac_is_present(mod_id)) return -1;
3283
  void *d = dlsym(object, sched);
3284 3285 3286 3287 3288
  if (!d) return -2;
  pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl;
  dl_pp->dl_algo.unset(&dl_pp->dl_algo.data);
  dl_pp->dl_algo = *(default_sched_dl_algo_t *) d;
  dl_pp->dl_algo.data = dl_pp->dl_algo.setup();
3289
  return 0;
3290 3291
}

3292 3293 3294 3295 3296
char *flexran_get_ul_scheduler_name(mid_t mod_id) {
  if (!mac_is_present(mod_id)) return NULL;
  return RC.mac[mod_id]->pre_processor_ul.ul_algo.name;
}

3297
int flexran_set_ul_scheduler(mid_t mod_id, char *sched, void *object) {
3298
  if (!mac_is_present(mod_id)) return -1;
3299
  void *d = dlsym(object, sched);
3300 3301 3302 3303 3304 3305 3306
  if (!d) return -2;
  pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul;
  ul_pp->ul_algo.unset(&ul_pp->ul_algo.data);
  ul_pp->ul_algo = *(default_sched_ul_algo_t *) d;
  ul_pp->ul_algo.data = ul_pp->ul_algo.setup();
  return 0;
}
3307

3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461
/************************** S1AP **************************/
int flexran_get_s1ap_mme_pending(mid_t mod_id){
  if (!rrc_is_present(mod_id)) return -1;
  s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
  if (!s1ap) return -1;
  return s1ap->s1ap_mme_pending_nb;
}

int flexran_get_s1ap_mme_connected(mid_t mod_id){
  if (!rrc_is_present(mod_id)) return -1;
  s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
  if (!s1ap) return -1;
  return s1ap->s1ap_mme_associated_nb;
}

char* flexran_get_s1ap_enb_s1_ip(mid_t mod_id){
  if (!rrc_is_present(mod_id)) return NULL;
  s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
  if (!s1ap) return NULL;
  if (s1ap->eNB_s1_ip.ipv4)
    return &s1ap->eNB_s1_ip.ipv4_address[0];
  if (s1ap->eNB_s1_ip.ipv6)
    return &s1ap->eNB_s1_ip.ipv6_address[0];
  return NULL;
}

char* flexran_get_s1ap_enb_name(mid_t mod_id){
  if (!rrc_is_present(mod_id)) return NULL;
  s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
  if (!s1ap) return NULL;
  return s1ap->eNB_name;
}

int flexran_get_s1ap_nb_mme(mid_t mod_id) {
  s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
  if (!s1ap) return 0;
  struct s1ap_eNB_mme_data_s *mme = NULL;
  int count = 0;
  RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
    count++;
  }
  return count;
}

int flexran_get_s1ap_nb_ue(mid_t mod_id) {
  s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
  if (!s1ap) return 0;
  struct s1ap_eNB_ue_context_s *ue = NULL;
  int count = 0;
  RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head) {
    count++;
  }
  return count;
}

int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apMme * mme_conf){
  if (!rrc_is_present(mod_id)) return -1;
  s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
  if (!s1ap) return -1;

  struct served_gummei_s   *gummei_p = NULL;
  struct plmn_identity_s   *served_plmn_p = NULL;
  struct served_group_id_s *group_id_p = NULL;
  struct mme_code_s        *mme_code_p = NULL;
  int i = 0;
  Protocol__FlexGummei  **served_gummeis;
  Protocol__FlexPlmn    **requested_plmns;

  struct s1ap_eNB_mme_data_s *mme = NULL;

  RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head){
    if (mme_index == 0) break;
    mme_index--;
  }
  if (mme_index > 0) return -1;

  if (mme->mme_s1_ip.ipv4) {
    mme_conf->s1_ip = (char*) &mme->mme_s1_ip.ipv4_address[0];
  } else if (mme->mme_s1_ip.ipv6) {
    mme_conf->s1_ip = (char*) &mme->mme_s1_ip.ipv6_address[0];
  }
  mme_conf->name = mme->mme_name;
  mme_conf->has_state = 1;
  mme_conf->state = mme->state;

  mme_conf->n_served_gummeis = 0;
  STAILQ_FOREACH(gummei_p, &mme->served_gummei, next) {
    mme_conf->n_served_gummeis++;
  }
  if (mme_conf->n_served_gummeis > 0) {
    served_gummeis = calloc(mme_conf->n_served_gummeis, sizeof(Protocol__FlexGummei*));
    if(served_gummeis == NULL) return -1;

    STAILQ_FOREACH(gummei_p, &mme->served_gummei, next) {
      served_plmn_p = STAILQ_FIRST(&gummei_p->served_plmns);
      group_id_p = STAILQ_FIRST(&gummei_p->served_group_ids);
      mme_code_p = STAILQ_FIRST(&gummei_p->mme_codes);

      served_gummeis[i] = malloc(sizeof(Protocol__FlexGummei));
      if (!served_gummeis[i]) return -1;
      protocol__flex_gummei__init(served_gummeis[i]);
      served_gummeis[i]->plmn = malloc(sizeof(Protocol__FlexPlmn));
      if (!served_gummeis[i]->plmn) return -1;
      protocol__flex_plmn__init(served_gummeis[i]->plmn);

      if (served_plmn_p) {
        served_gummeis[i]->plmn->has_mcc = 1;
        served_gummeis[i]->plmn->mcc = served_plmn_p->mcc;
        served_gummeis[i]->plmn->has_mnc = 1;
        served_gummeis[i]->plmn->mnc = served_plmn_p->mnc;
        served_gummeis[i]->plmn->has_mnc_length = 1;
        served_gummeis[i]->plmn->mnc_length = served_plmn_p-> mnc_digit_length;
        STAILQ_NEXT(served_plmn_p, next);
      }
      if (group_id_p) {
        served_gummeis[i]->has_mme_group_id = 1;
        served_gummeis[i]->mme_group_id = group_id_p->mme_group_id;
        STAILQ_NEXT(group_id_p, next);
      }
      if (mme_code_p){
        served_gummeis[i]->has_mme_code = 1;
        served_gummeis[i]->mme_code = mme_code_p->mme_code;
        STAILQ_NEXT(mme_code_p, next);
      }
      i++;
    }

    mme_conf->served_gummeis = served_gummeis;
  }

  // requested PLMNS
  mme_conf->n_requested_plmns = mme->broadcast_plmn_num;
  if (mme_conf->n_requested_plmns > 0){
    requested_plmns = calloc(mme_conf->n_requested_plmns, sizeof(Protocol__FlexPlmn*));
    if(requested_plmns == NULL) return -1;
    for(int i = 0; i < mme_conf->n_requested_plmns; i++) {
      requested_plmns[i] = malloc(sizeof(Protocol__FlexPlmn));
      if (!requested_plmns[i]) return -1;
      protocol__flex_plmn__init(requested_plmns[i]);
      requested_plmns[i]->mcc = s1ap->mcc[mme->broadcast_plmn_index[i]];
      requested_plmns[i]->has_mcc = 1;
      requested_plmns[i]->mnc = s1ap->mnc[mme->broadcast_plmn_index[i]];
      requested_plmns[i]->has_mnc = 1;
      requested_plmns[i]->mnc_length = s1ap->mnc_digit_length[mme->broadcast_plmn_index[i]];
      requested_plmns[i]->has_mnc_length = 1;
    }
    mme_conf->requested_plmns = requested_plmns;
  }

  mme_conf->has_rel_capacity = 1;
  mme_conf->rel_capacity = mme->relative_mme_capacity;
  return 0;
}

3462 3463 3464 3465 3466 3467
int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) {
  s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
  if (!s1ap) return -1;
  if (!rrc_is_present(mod_id)) return -2;

  /* Reconstruct S1AP_REGISTER_ENB_REQ */
3468
  MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, 0, S1AP_REGISTER_ENB_REQ);
3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493
  RCconfig_S1(m, mod_id);

  const int CC_id = 0;
  eNB_RRC_INST *rrc = RC.rrc[CC_id];
  RrcConfigurationReq *conf = &rrc->configuration;
  S1AP_REGISTER_ENB_REQ(m).num_plmn = conf->num_plmn;
  for (int i = 0; i < conf->num_plmn; ++i) {
    S1AP_REGISTER_ENB_REQ(m).mcc[i] = conf->mcc[i];
    S1AP_REGISTER_ENB_REQ(m).mnc[i] = conf->mnc[i];
    S1AP_REGISTER_ENB_REQ(m).mnc_digit_length[i] = conf->mnc_digit_length[i];
  }

  /* reconstruct MME list, it might have been updated since initial
   * configuration */
  S1AP_REGISTER_ENB_REQ(m).nb_mme = 0;
  struct s1ap_eNB_mme_data_s *mme = NULL;
  RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
    const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme;
    S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = mme->mme_s1_ip.ipv4;
    strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme->mme_s1_ip.ipv4_address);
    S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = mme->mme_s1_ip.ipv6;
    strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6_address, mme->mme_s1_ip.ipv6_address);
    S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = mme->broadcast_plmn_num;
    for (int i = 0; i < mme->broadcast_plmn_num; ++i)
      S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = mme->broadcast_plmn_index[i];
3494
    S1AP_REGISTER_ENB_REQ(m).mme_port[n] = mme->mme_port;
3495 3496 3497 3498 3499 3500
    S1AP_REGISTER_ENB_REQ(m).nb_mme += 1;
  }

  if (S1AP_REGISTER_ENB_REQ(m).nb_mme + n_mme > S1AP_MAX_NB_MME_IP_ADDRESS)
    return -1;

Robert Schmidt's avatar
Robert Schmidt committed
3501 3502 3503 3504 3505 3506 3507 3508 3509
  const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme;
  strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme_ipv4[0]);
  S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = 1;
  S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = 0;
  S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = S1AP_REGISTER_ENB_REQ(m).num_plmn;
  for (int i = 0; i < S1AP_REGISTER_ENB_REQ(m).num_plmn; ++i)
    S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = i;
  S1AP_REGISTER_ENB_REQ(m).mme_port[n] = S1AP_PORT_NUMBER;
  S1AP_REGISTER_ENB_REQ(m).nb_mme += 1;
3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527

  itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m);

  return 0;
}

int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) {
  s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
  if (!s1ap) return -1;
  struct s1ap_eNB_mme_data_s *mme = NULL;
  RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
    if (mme->mme_s1_ip.ipv4
        && strncmp(mme->mme_s1_ip.ipv4_address, mme_ipv4[0], 16) == 0)
        break;
  }
  if (!mme)
    return -2;

3528
  MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, 0, SCTP_CLOSE_ASSOCIATION);
3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551
  SCTP_CLOSE_ASSOCIATION(m).assoc_id = mme->assoc_id;
  itti_send_msg_to_task (TASK_SCTP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m);

  switch (mme->state) {
    case S1AP_ENB_STATE_WAITING:
      s1ap->s1ap_mme_nb -= 1;
      if (s1ap->s1ap_mme_pending_nb > 0)
        s1ap->s1ap_mme_pending_nb -= 1;
      break;
    case S1AP_ENB_STATE_CONNECTED:
    case S1AP_ENB_OVERLOAD: /* I am not sure the decrements are right here */
      s1ap->s1ap_mme_nb -= 1;
      s1ap->s1ap_mme_associated_nb -= 1;
      break;
    case S1AP_ENB_STATE_DISCONNECTED:
    default:
      break;
  }
  RB_REMOVE(s1ap_mme_map, &s1ap->s1ap_mme_head, mme);

  return 0;
}

Robert Schmidt's avatar
Robert Schmidt committed
3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622
int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id) {
  if (!rrc_is_present(mod_id))
    return -1;
  s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
  if (!s1ap)
    return -2;

  eNB_RRC_INST *rrc = RC.rrc[CC_id];
  RrcConfigurationReq *conf = &rrc->configuration;

  uint8_t num_plmn_old = conf->num_plmn;
  uint16_t mcc[PLMN_LIST_MAX_SIZE];
  uint16_t mnc[PLMN_LIST_MAX_SIZE];
  uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE];
  for (int i = 0; i < num_plmn_old; ++i) {
    mcc[i] = conf->mcc[i];
    mnc[i] = conf->mnc[i];
    mnc_digit_length[i] = conf->mnc_digit_length[i];
  }

  conf->num_plmn = (uint8_t) n_plmn;
  for (int i = 0; i < conf->num_plmn; ++i) {
    conf->mcc[i] = plmn_id[i]->mcc;
    conf->mnc[i] = plmn_id[i]->mnc;
    conf->mnc_digit_length[i] = plmn_id[i]->mnc_length;
  }

  rrc_eNB_carrier_data_t *carrier = &rrc->carrier[CC_id];
  extern uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
                         int Mod_id,
                         int CC_id,
                         BOOLEAN_t brOption,
                         RrcConfigurationReq *configuration);
  carrier->sizeof_SIB1 = do_SIB1(carrier, mod_id, CC_id, FALSE, conf);
  if (carrier->sizeof_SIB1 < 0)
    return -1337; /* SIB1 encoding failed, hell will probably break loose */

  s1ap->num_plmn = (uint8_t) n_plmn;
  for (int i = 0; i < conf->num_plmn; ++i) {
    s1ap->mcc[i] = plmn_id[i]->mcc;
    s1ap->mnc[i] = plmn_id[i]->mnc;
    s1ap->mnc_digit_length[i] = plmn_id[i]->mnc_length;
  }

  int bpn_failed = 0;
  struct s1ap_eNB_mme_data_s *mme = NULL;
  RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
    for (int i = 0; i < mme->broadcast_plmn_num; ++i) {
      /* search the new index and update. If we don't find, we count this using
       * bpn_failed to now how many broadcast_plmns could not be updated */
      int idx = mme->broadcast_plmn_index[i];
      int omcc = mcc[idx];
      int omnc = mnc[idx];
      int omncl = mnc_digit_length[idx];
      int j = 0;
      for (j = 0; j < s1ap->num_plmn; ++j) {
        if (s1ap->mcc[j] == omcc
            && s1ap->mnc[j] == omnc
            && s1ap->mnc_digit_length[j] == omncl) {
          mme->broadcast_plmn_index[i] = j;
          break;
        }
      }
      if (j == s1ap->num_plmn) /* could not find the old PLMN in the new ones */
        bpn_failed++;
    }
  }
  if (bpn_failed > 0)
    return -10000 - bpn_failed;
  return 0;
}
3623

3624 3625 3626 3627 3628 3629 3630 3631 3632 3633
int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf){
  if (!rrc_is_present(mod_id)) return -1;
  s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
  if (!s1ap) return -1;

  uint32_t enb_ue_s1ap_id = flexran_get_rrc_enb_ue_s1ap_id(mod_id, rnti);
  struct s1ap_eNB_ue_context_s *ue = NULL;
  RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head){
    if (ue->eNB_ue_s1ap_id == enb_ue_s1ap_id) break;
  }
3634
  if (!ue) return 0; // UE does not exist: it might be connected but CN did not answer
3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658

  if (ue->mme_ref->mme_s1_ip.ipv4)
    ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv4_address[0];
  else if (ue->mme_ref->mme_s1_ip.ipv6)
    ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv6_address[0];

  ue_conf->has_enb_ue_s1ap_id = 1;
  ue_conf->enb_ue_s1ap_id = ue->eNB_ue_s1ap_id;
  ue_conf->has_mme_ue_s1ap_id = 1;
  ue_conf->mme_ue_s1ap_id = ue->mme_ue_s1ap_id;

  ue_conf->selected_plmn = malloc(sizeof(Protocol__FlexPlmn));
  if (!ue_conf->selected_plmn) return -1;
  protocol__flex_plmn__init(ue_conf->selected_plmn);

  ue_conf->selected_plmn->has_mcc = 1;
  ue_conf->selected_plmn->mcc = s1ap->mcc[ue->selected_plmn_identity];
  ue_conf->selected_plmn->has_mnc = 1;
  ue_conf->selected_plmn->mnc = s1ap->mnc[ue->selected_plmn_identity];
  ue_conf->selected_plmn->has_mnc_length = 1;
  ue_conf->selected_plmn->mnc_length = s1ap->mnc_digit_length[ue->selected_plmn_identity];
  return 0;
}

3659
/**************************** General BS info  ****************************/
3660
uint64_t flexran_get_bs_id(mid_t mod_id) {
3661
  if (!rrc_is_present(mod_id)) return 0;
3662

3663 3664 3665
  return RC.rrc[mod_id]->nr_cellid;
}

3666
size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps) {
3667
  if (!caps) return 0;
3668

3669
  if (!rrc_is_present(mod_id)) return 0;
3670

3671
  size_t n_caps = 0;
3672

3673
  switch (RC.rrc[mod_id]->node_type) {
3674 3675 3676
    case ngran_eNB_CU:
    case ngran_ng_eNB_CU:
    case ngran_gNB_CU:
3677
      n_caps = 4;
3678 3679 3680 3681 3682 3683
      *caps = calloc(n_caps, sizeof(Protocol__FlexBsCapability));
      AssertFatal(*caps, "could not allocate %zu bytes for Protocol__FlexBsCapability array\n",
                  n_caps * sizeof(Protocol__FlexBsCapability));
      (*caps)[0] = PROTOCOL__FLEX_BS_CAPABILITY__PDCP;
      (*caps)[1] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP;
      (*caps)[2] = PROTOCOL__FLEX_BS_CAPABILITY__RRC;
3684
      (*caps)[3] = PROTOCOL__FLEX_BS_CAPABILITY__S1AP;
3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700
      break;
    case ngran_eNB_DU:
    case ngran_gNB_DU:
      n_caps = 5;
      *caps = calloc(n_caps, sizeof(Protocol__FlexBsCapability));
      AssertFatal(*caps, "could not allocate %zu bytes for Protocol__FlexBsCapability array\n",
                  n_caps * sizeof(Protocol__FlexBsCapability));
      (*caps)[0] = PROTOCOL__FLEX_BS_CAPABILITY__LOPHY;
      (*caps)[1] = PROTOCOL__FLEX_BS_CAPABILITY__HIPHY;
      (*caps)[2] = PROTOCOL__FLEX_BS_CAPABILITY__LOMAC;
      (*caps)[3] = PROTOCOL__FLEX_BS_CAPABILITY__HIMAC;
      (*caps)[4] = PROTOCOL__FLEX_BS_CAPABILITY__RLC;
      break;
    case ngran_eNB:
    case ngran_ng_eNB:
    case ngran_gNB:
3701
      n_caps = 9;
3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712
      *caps = calloc(n_caps, sizeof(Protocol__FlexBsCapability));
      AssertFatal(*caps, "could not allocate %zu bytes for Protocol__FlexBsCapability array\n",
                  n_caps * sizeof(Protocol__FlexBsCapability));
      (*caps)[0] = PROTOCOL__FLEX_BS_CAPABILITY__LOPHY;
      (*caps)[1] = PROTOCOL__FLEX_BS_CAPABILITY__HIPHY;
      (*caps)[2] = PROTOCOL__FLEX_BS_CAPABILITY__LOMAC;
      (*caps)[3] = PROTOCOL__FLEX_BS_CAPABILITY__HIMAC;
      (*caps)[4] = PROTOCOL__FLEX_BS_CAPABILITY__RLC;
      (*caps)[5] = PROTOCOL__FLEX_BS_CAPABILITY__PDCP;
      (*caps)[6] = PROTOCOL__FLEX_BS_CAPABILITY__SDAP;
      (*caps)[7] = PROTOCOL__FLEX_BS_CAPABILITY__RRC;
3713
      (*caps)[8] = PROTOCOL__FLEX_BS_CAPABILITY__S1AP;
3714
      break;
3715
    case ngran_eNB_MBMS_STA:
3716
      AssertFatal(0, "MBMS STA not supported by FlexRAN!\n");
3717
     break;
3718
  }
3719

3720 3721 3722
  return n_caps;
}

3723
uint32_t flexran_get_capabilities_mask(mid_t mod_id) {
3724
  if (!rrc_is_present(mod_id)) return 0;
3725
  uint32_t mask = 0;
3726
  switch (RC.rrc[mod_id]->node_type) {
3727 3728 3729 3730
    case ngran_eNB_CU:
    case ngran_ng_eNB_CU:
    case ngran_gNB_CU:
      mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
3731
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
3732 3733
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC)
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__S1AP);
3734 3735 3736 3737
      break;
    case ngran_eNB_DU:
    case ngran_gNB_DU:
      mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)
3738 3739 3740 3741
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC);
3742 3743 3744 3745 3746
      break;
    case ngran_eNB:
    case ngran_ng_eNB:
    case ngran_gNB:
      mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)
3747 3748 3749 3750 3751 3752
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC)
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
3753 3754
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC)
           | (1 << PROTOCOL__FLEX_BS_CAPABILITY__S1AP);
3755 3756
      break;
    case ngran_eNB_MBMS_STA:
3757
      AssertFatal(0, "MBMS STA not supported by FlexRAN!\n");
3758
     break;
3759
  }
3760

3761 3762
  return mask;
}
3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790

size_t flexran_get_splits(mid_t mod_id, Protocol__FlexBsSplit **splits) {
  size_t n_splits = 0;
  *splits = NULL;
  if (rrc_is_present(mod_id) && !NODE_IS_MONOLITHIC(RC.rrc[mod_id]->node_type))
    n_splits++;
  if (NFAPI_MODE != NFAPI_MONOLITHIC)
    n_splits++;
  if (RC.ru && RC.ru[mod_id] && RC.ru[mod_id]->if_south != LOCAL_RF)
    n_splits++;
  if (n_splits == 0)
    return 0;

  AssertFatal(n_splits < 3, "illegal number of splits (%lu)\n", n_splits);
  *splits = calloc(n_splits, sizeof(Protocol__FlexBsSplit));
  AssertFatal(*splits, "could not allocate Protocol__FlexBsSplit array\n");
  int n = 0;
  if (rrc_is_present(mod_id) && !NODE_IS_MONOLITHIC(RC.rrc[mod_id]->node_type))
    (*splits)[n++] = PROTOCOL__FLEX_BS_SPLIT__F1;
  if (NFAPI_MODE != NFAPI_MONOLITHIC)
    (*splits)[n++] = PROTOCOL__FLEX_BS_SPLIT__nFAPI;
  if (RC.ru && RC.ru[mod_id] && RC.ru[mod_id]->if_south == REMOTE_IF4p5)
    (*splits)[n++] = PROTOCOL__FLEX_BS_SPLIT__IF4p5;
  if (RC.ru && RC.ru[mod_id] && RC.ru[mod_id]->if_south == REMOTE_IF5)
    (*splits)[n++] = PROTOCOL__FLEX_BS_SPLIT__IF5;
  DevAssert(n == n_splits);
  return n_splits;
}