flexran_agent_ran_api.c 71.3 KB
Newer Older
1 2 3 4 5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * 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
 */ 

/*! \file flexran_agent_ran_api.c
 * \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 31
#include "flexran_agent_ran_api.h"

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

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

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

Robert Schmidt's avatar
Robert Schmidt committed
47
uint32_t flexran_get_current_time_ms(mid_t mod_id, int subframe_flag)
48
{
49
  if (!mac_is_present(mod_id)) return 0;
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
}

Robert Schmidt's avatar
Robert Schmidt committed
56 57
frame_t flexran_get_current_frame(mid_t mod_id)
{
58
  if (!mac_is_present(mod_id)) return 0;
59
  //  #warning "SFN will not be in [0-1023] when oaisim is used"
60
  return RC.mac[mod_id]->frame;
61 62
}

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

Robert Schmidt's avatar
Robert Schmidt committed
68 69
sub_frame_t flexran_get_current_subframe(mid_t mod_id)
{
70 71
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->subframe;
72 73
}

Robert Schmidt's avatar
Robert Schmidt committed
74 75 76
/* Why uint16_t, frame_t and sub_frame_t are defined as uint32_t? */
uint16_t flexran_get_sfn_sf(mid_t mod_id)
{
77
  if (!mac_is_present(mod_id)) return 0;
Robert Schmidt's avatar
Robert Schmidt committed
78 79
  frame_t frame = flexran_get_current_system_frame_num(mod_id);
  sub_frame_t subframe = flexran_get_current_subframe(mod_id);
80
  uint16_t sfn_sf, frame_mask, sf_mask;
Robert Schmidt's avatar
Robert Schmidt committed
81 82 83

  frame_mask = (1 << 12) - 1;
  sf_mask = (1 << 4) - 1;
84
  sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4);
Robert Schmidt's avatar
Robert Schmidt committed
85

86 87 88
  return sfn_sf;
}

Robert Schmidt's avatar
Robert Schmidt committed
89 90
uint16_t flexran_get_future_sfn_sf(mid_t mod_id, int ahead_of_time)
{
91
  if (!mac_is_present(mod_id)) return 0;
Robert Schmidt's avatar
Robert Schmidt committed
92 93
  frame_t frame = flexran_get_current_system_frame_num(mod_id);
  sub_frame_t subframe = flexran_get_current_subframe(mod_id);
94
  uint16_t sfn_sf, frame_mask, sf_mask;
Robert Schmidt's avatar
Robert Schmidt committed
95
  int additional_frames;
96

Robert Schmidt's avatar
Robert Schmidt committed
97 98 99
  subframe = (subframe + ahead_of_time) % 10;

  if (subframe < flexran_get_current_subframe(mod_id))
100
    frame = (frame + 1) % 1024;
Robert Schmidt's avatar
Robert Schmidt committed
101 102

  additional_frames = ahead_of_time / 10;
103
  frame = (frame + additional_frames) % 1024;
Robert Schmidt's avatar
Robert Schmidt committed
104 105 106

  frame_mask = (1 << 12) - 1;
  sf_mask = (1 << 4) - 1;
107
  sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4);
Robert Schmidt's avatar
Robert Schmidt committed
108

109 110 111
  return sfn_sf;
}

112
int flexran_get_mac_num_ues(mid_t mod_id)
Robert Schmidt's avatar
Robert Schmidt committed
113
{
114 115
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.num_UEs;
116 117
}

118 119 120 121
int flexran_get_num_ue_lcs(mid_t mod_id, mid_t ue_id)
{
  if (!mac_is_present(mod_id)) return 0;
  // Not sure whether this is needed: if (!rrc_is_present(mod_id)) return 0;
122
  const rnti_t rnti = flexran_get_mac_ue_crnti(mod_id, ue_id);
123 124 125 126 127 128 129 130 131
  const int s = mac_eNB_get_rrc_status(mod_id, rnti);
  if (s < RRC_CONNECTED)
    return 0;
  else if (s == RRC_CONNECTED)
    return 1;
  else
    return 3;
}

132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
int flexran_get_mac_ue_id_rnti(mid_t mod_id, rnti_t rnti)
{
  int n;
  if (!mac_is_present(mod_id)) return 0;
  /* get the (active) UE with RNTI i */
  for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) {
    if (RC.mac[mod_id]->UE_list.active[n] == TRUE
        && rnti == UE_RNTI(mod_id, n)) {
      return n;
    }
  }
  return 0;

}

147
int flexran_get_mac_ue_id(mid_t mod_id, int i)
148 149 150 151 152 153 154 155 156 157 158 159 160 161
{
  int n;
  if (!mac_is_present(mod_id)) return 0;
  /* get the (i+1)'th active UE */
  for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) {
    if (RC.mac[mod_id]->UE_list.active[n] == TRUE) {
      if (i == 0)
        return n;
      --i;
    }
  }
  return 0;
}

162
rnti_t flexran_get_mac_ue_crnti(mid_t mod_id, mid_t ue_id)
Robert Schmidt's avatar
Robert Schmidt committed
163
{
164
  if (!mac_is_present(mod_id)) return 0;
Robert Schmidt's avatar
Robert Schmidt committed
165
  return UE_RNTI(mod_id, ue_id);
166 167
}

168
int flexran_get_ue_bsr_ul_buffer_info(mid_t mod_id, mid_t ue_id, lcid_t lcid)
Robert Schmidt's avatar
Robert Schmidt committed
169
{
170 171
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->UE_list.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].ul_buffer_info[lcid];
172 173
}

Robert Schmidt's avatar
Robert Schmidt committed
174 175
int8_t flexran_get_ue_phr(mid_t mod_id, mid_t ue_id)
{
176 177
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].phr_info;
178 179
}

Robert Schmidt's avatar
Robert Schmidt committed
180 181
uint8_t flexran_get_ue_wcqi(mid_t mod_id, mid_t ue_id)
{
182
  if (!mac_is_present(mod_id)) return 0;
183
  return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].dl_cqi[0];
184 185
}

Robert Schmidt's avatar
Robert Schmidt committed
186 187
rlc_buffer_occupancy_t flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id)
{
188
  if (!mac_is_present(mod_id)) return 0;
189
  rnti_t rnti = flexran_get_mac_ue_crnti(mod_id, ue_id);
Robert Schmidt's avatar
Robert Schmidt committed
190 191
  frame_t frame = flexran_get_current_frame(mod_id);
  sub_frame_t subframe = flexran_get_current_subframe(mod_id);
192
  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
193
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
194 195 196
                                                    ,0, 0
#endif
                                                    );
197
  return rlc_status.bytes_in_buffer;
198 199
}

Robert Schmidt's avatar
Robert Schmidt committed
200 201
rlc_buffer_occupancy_t flexran_get_num_pdus_buffer(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id)
{
202
  if (!mac_is_present(mod_id)) return 0;
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
207
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
208 209 210
                                                    ,0, 0
#endif
                                                    );
211 212 213
  return rlc_status.pdus_in_buffer;
}

Robert Schmidt's avatar
Robert Schmidt committed
214 215
frame_t flexran_get_hol_delay(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id)
{
216
  if (!mac_is_present(mod_id)) return 0;
217
  rnti_t rnti = flexran_get_mac_ue_crnti(mod_id,ue_id);
Robert Schmidt's avatar
Robert Schmidt committed
218 219
  frame_t frame = flexran_get_current_frame(mod_id);
  sub_frame_t subframe = flexran_get_current_subframe(mod_id);
220
  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
221
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
222 223 224
                                                    ,0, 0
#endif
                                                    );
225 226 227
  return rlc_status.head_sdu_creation_time;
}

Robert Schmidt's avatar
Robert Schmidt committed
228 229
int32_t flexran_get_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id)
{
230
  if (!phy_is_present(mod_id, cc_id)) return 0;
231

232
  int32_t tau = RC.eNB[mod_id][cc_id]->UE_stats[ue_id].timing_advance_update;
Robert Schmidt's avatar
Robert Schmidt committed
233
  switch (flexran_get_N_RB_DL(mod_id, cc_id)) {
234
  case 6:
Robert Schmidt's avatar
Robert Schmidt committed
235
    return tau;
236
  case 15:
Robert Schmidt's avatar
Robert Schmidt committed
237
    return tau / 2;
238
  case 25:
Robert Schmidt's avatar
Robert Schmidt committed
239
    return tau / 4;
240
  case 50:
Robert Schmidt's avatar
Robert Schmidt committed
241
    return tau / 8;
242
  case 75:
Robert Schmidt's avatar
Robert Schmidt committed
243
    return tau / 12;
244
  case 100:
Robert Schmidt's avatar
Robert Schmidt committed
245 246 247 248
    if (flexran_get_threequarter_fs(mod_id, cc_id) == 0)
      return tau / 16;
    else
      return tau / 12;
249 250 251 252 253
  default:
    return 0;
  }
}

254 255
uint32_t flexran_get_total_size_dl_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id)
{
256 257 258 259
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_sdu_bytes;
}

260 261 262
uint32_t flexran_get_total_size_ul_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id)
{
  if (!mac_is_present(mod_id)) return 0;
263 264 265 266 267
  uint64_t bytes = 0;
  for (int i = 0; i < NB_RB_MAX; ++i) {
    bytes += RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].num_bytes_rx[i];
  }
  return bytes;
268 269
}

270 271
uint32_t flexran_get_TBS_dl(mid_t mod_id, mid_t ue_id, int cc_id)
{
272
  if (!mac_is_present(mod_id)) return 0;
273
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].TBS[TB1];
274 275
}

276 277
uint32_t flexran_get_TBS_ul(mid_t mod_id, mid_t ue_id, int cc_id)
{
278 279 280 281
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].ulsch_TBS;
}

282 283 284 285
uint16_t flexran_get_num_prb_retx_dl_per_ue(mid_t mod_id, mid_t ue_id, int cc_id)
{
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used_retx;
286 287
}

288 289
uint32_t flexran_get_num_prb_retx_ul_per_ue(mid_t mod_id, mid_t ue_id, int cc_id)
{
290 291 292 293
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used_retx_rx;
}

294 295 296 297
uint16_t flexran_get_num_prb_dl_tx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id)
{
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used;
298 299
}

300 301 302 303
uint16_t flexran_get_num_prb_ul_rx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id)
{
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used_rx;
304 305
}

Robert Schmidt's avatar
Robert Schmidt committed
306 307
uint8_t flexran_get_ue_wpmi(mid_t mod_id, mid_t ue_id, uint8_t cc_id)
{
308 309
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].periodic_wideband_pmi[cc_id];
310 311
}

312 313
uint8_t flexran_get_mcs1_dl(mid_t mod_id, mid_t ue_id, int cc_id)
{
314
  if (!mac_is_present(mod_id)) return 0;
315
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].dlsch_mcs[TB1];
316 317
}

318 319
uint8_t flexran_get_mcs2_dl(mid_t mod_id, mid_t ue_id, int cc_id)
{
320
  if (!mac_is_present(mod_id)) return 0;
321
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].dlsch_mcs[TB2];
322 323
}

324 325
uint8_t flexran_get_mcs1_ul(mid_t mod_id, mid_t ue_id, int cc_id)
{
326 327 328 329
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].ulsch_mcs1;
}

330 331
uint8_t flexran_get_mcs2_ul(mid_t mod_id, mid_t ue_id, int cc_id)
{
332 333 334 335
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].ulsch_mcs2;
}

336 337
uint32_t flexran_get_total_prb_dl_tx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id)
{
338 339 340 341
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_rbs_used;
}

342 343
uint32_t flexran_get_total_prb_ul_rx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id)
{
344 345 346 347
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_rbs_used_rx;
}

348 349
uint32_t flexran_get_total_num_pdu_dl(mid_t mod_id, mid_t ue_id, int cc_id)
{
350 351 352 353
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_num_pdus;
}

354 355
uint32_t flexran_get_total_num_pdu_ul(mid_t mod_id, mid_t ue_id, int cc_id)
{
356 357 358 359
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_num_pdus_rx;
}

360 361
uint64_t flexran_get_total_TBS_dl(mid_t mod_id, mid_t ue_id, int cc_id)
{
362 363 364 365
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_pdu_bytes;
}

366 367
uint64_t flexran_get_total_TBS_ul(mid_t mod_id, mid_t ue_id, int cc_id)
{
368 369 370 371
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_ulsch_TBS;
}

372 373
int flexran_get_harq_round(mid_t mod_id, uint8_t cc_id, mid_t ue_id)
{
374
  if (!mac_is_present(mod_id)) return 0;
375
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].harq_round[TB1];
376 377
}

378 379 380 381
uint32_t flexran_get_num_mac_sdu_tx(mid_t mod_id, mid_t ue_id, int cc_id)
{
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].num_mac_sdu_tx;
382 383
}

384 385
unsigned char flexran_get_mac_sdu_lcid_index(mid_t mod_id, mid_t ue_id, int cc_id, int index)
{
386 387 388 389
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].lcid_sdu[index];
}

390 391
uint32_t flexran_get_mac_sdu_size(mid_t mod_id, mid_t ue_id, int cc_id, int lcid)
{
392 393 394 395 396
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].sdu_length_tx[lcid];
}


Robert Schmidt's avatar
Robert Schmidt committed
397 398 399 400
/* TODO needs to be revised */
void flexran_update_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id)
{
/*
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
  UE_list_t *UE_list=&eNB_mac_inst[mod_id].UE_list;
  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id];

  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      
  }
Robert Schmidt's avatar
Robert Schmidt committed
417
#warning "Implement flexran_update_TA() in RAN API"
418
*/
419 420
}

Robert Schmidt's avatar
Robert Schmidt committed
421 422 423
/* TODO needs to be revised, looks suspicious: why do we need UE stats? */
int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id)
{
424
/*
Robert Schmidt's avatar
Robert Schmidt committed
425
#warning "Implement flexran_get_MAC_CE_bitmap_TA() in RAN API"
426
*/
427
  if (!phy_is_present(mod_id, cc_id)) return 0;
428

Robert Schmidt's avatar
Robert Schmidt committed
429
  /* UE_stats can not be null, they are an array in RC
430 431 432 433 434
  LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
  
  if (eNB_UE_stats == NULL) {
    return 0;
  }
Robert Schmidt's avatar
Robert Schmidt committed
435
  */
436

Robert Schmidt's avatar
Robert Schmidt committed
437
  if (flexran_get_TA(mod_id, ue_id, cc_id) != 0) {
438 439 440 441 442 443
    return PROTOCOL__FLEX_CE_TYPE__FLPCET_TA;
  } else {
    return 0;
  }
}

Robert Schmidt's avatar
Robert Schmidt committed
444 445
int flexran_get_active_CC(mid_t mod_id, mid_t ue_id)
{
446 447
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.numactiveCCs[ue_id];
448 449
}

Robert Schmidt's avatar
Robert Schmidt committed
450 451
uint8_t flexran_get_current_RI(mid_t mod_id, mid_t ue_id, uint8_t cc_id)
{
452 453
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->UE_stats[ue_id].rank;
454 455
}

Robert Schmidt's avatar
Robert Schmidt committed
456 457
int flexran_get_tpc(mid_t mod_id, mid_t ue_id, uint8_t cc_id)
{
458
  if (!phy_is_present(mod_id, cc_id)) return 0;
Robert Schmidt's avatar
Robert Schmidt committed
459 460 461 462

  /* 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);
463 464
  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
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488

  int tpc;
  if (normalized_rx_power > target_rx_power + 1)
    tpc = 0;	//-1
  else if (normalized_rx_power < target_rx_power - 1)
    tpc = 2;	//+1
  else
    tpc = 1;	//0
  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,
                     uint8_t     harq_flag)
{
  /* 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];*/
489

Robert Schmidt's avatar
Robert Schmidt committed
490 491
  /* TODO IMPLEMENT */
  /*
492 493 494
  uint8_t harq_pid;
  uint8_t harq_round;
  
495
  if (mac_xface_not_ready()) return 0 ;
496

497
  uint16_t rnti = flexran_get_mac_ue_crnti(mod_id,ue_id);
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
498
  if (harq_flag == openair_harq_DL){
499

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

shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
502 503
   } else if (harq_flag == openair_harq_UL){

shahab SHARIAT BAGHERI's avatar
shahab SHARIAT BAGHERI committed
504
     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
505 506 507 508 509 510 511 512
   }
   else {

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


  *pid = harq_pid;
Robert Schmidt's avatar
Robert Schmidt committed
513
  *round = harq_round;*/
514 515 516 517 518
  /* if (round > 0) { */
  /*   *status = 1; */
  /* } else { */
  /*   *status = 0; */
  /* } */
Robert Schmidt's avatar
Robert Schmidt committed
519
  /*return *round;*/
520
/*
Robert Schmidt's avatar
Robert Schmidt committed
521
#warning "Implement flexran_get_harq() in RAN API"
522
*/
Robert Schmidt's avatar
Robert Schmidt committed
523
  return 0;
524 525
}

Robert Schmidt's avatar
Robert Schmidt committed
526 527
int32_t flexran_get_p0_pucch_dbm(mid_t mod_id, mid_t ue_id, uint8_t cc_id)
{
528 529
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->UE_stats[ue_id].Po_PUCCH_dBm;
530 531
}

Robert Schmidt's avatar
Robert Schmidt committed
532 533
int8_t flexran_get_p0_nominal_pucch(mid_t mod_id, uint8_t cc_id)
{
534 535
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.ul_power_control_config_common.p0_NominalPUCCH;
536 537
}

Robert Schmidt's avatar
Robert Schmidt committed
538 539
int32_t flexran_get_p0_pucch_status(mid_t mod_id, mid_t ue_id, uint8_t cc_id)
{
540 541
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->UE_stats[ue_id].Po_PUCCH_update;
542 543
}

Robert Schmidt's avatar
Robert Schmidt committed
544 545
int flexran_update_p0_pucch(mid_t mod_id, mid_t ue_id, uint8_t cc_id)
{
546 547
  if (!phy_is_present(mod_id, cc_id)) return 0;
  RC.eNB[mod_id][cc_id]->UE_stats[ue_id].Po_PUCCH_update = 0;
548 549 550 551 552 553 554 555 556
  return 0;
}


/*
 * ************************************
 * Get Messages for eNB Configuration Reply
 * ************************************
 */
Robert Schmidt's avatar
Robert Schmidt committed
557 558
uint8_t flexran_get_threequarter_fs(mid_t mod_id, uint8_t cc_id)
{
559 560
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.threequarter_fs;
561 562
}

563

Robert Schmidt's avatar
Robert Schmidt committed
564 565
uint8_t flexran_get_hopping_offset(mid_t mod_id, uint8_t cc_id)
{
566 567
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.pusch_config_common.pusch_HoppingOffset;
568 569
}

570 571 572 573 574 575 576 577 578 579
Protocol__FlexHoppingMode flexran_get_hopping_mode(mid_t mod_id, uint8_t cc_id)
{
  if (!phy_is_present(mod_id, cc_id)) return -1;
  switch (RC.eNB[mod_id][cc_id]->frame_parms.pusch_config_common.hoppingMode) {
  case interSubFrame:
    return PROTOCOL__FLEX_HOPPING_MODE__FLHM_INTER;
  case intraAndInterSubFrame:
    return PROTOCOL__FLEX_HOPPING_MODE__FLHM_INTERINTRA;
  }
  return -1;
580 581
}

Robert Schmidt's avatar
Robert Schmidt committed
582 583
uint8_t flexran_get_n_SB(mid_t mod_id, uint8_t cc_id)
{
584 585
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.pusch_config_common.n_SB;
586 587
}

588
Protocol__FlexQam flexran_get_enable64QAM(mid_t mod_id, uint8_t cc_id)
Robert Schmidt's avatar
Robert Schmidt committed
589
{
590
  if (!phy_is_present(mod_id, cc_id)) return 0;
591 592 593 594
  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;
595 596
}

597
Protocol__FlexPhichDuration flexran_get_phich_duration(mid_t mod_id, uint8_t cc_id)
Robert Schmidt's avatar
Robert Schmidt committed
598
{
599 600 601 602 603 604 605 606
  if (!phy_is_present(mod_id, cc_id)) return -1;
  switch (RC.eNB[mod_id][cc_id]->frame_parms.phich_config_common.phich_duration) {
  case normal:
    return PROTOCOL__FLEX_PHICH_DURATION__FLPD_NORMAL;
  case extended:
    return PROTOCOL__FLEX_PHICH_DURATION__FLPD_EXTENDED;
  }
  return -1;
607 608
}

609
Protocol__FlexPhichResource flexran_get_phich_resource(mid_t mod_id, uint8_t cc_id)
Robert Schmidt's avatar
Robert Schmidt committed
610
{
611
  if (!phy_is_present(mod_id, cc_id)) return -1;
612
  switch (RC.eNB[mod_id][cc_id]->frame_parms.phich_config_common.phich_resource) {
Robert Schmidt's avatar
Robert Schmidt committed
613
  case oneSixth:
614
    return PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_ONE_SIXTH;
Robert Schmidt's avatar
Robert Schmidt committed
615
  case half:
616
    return PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_HALF;
Robert Schmidt's avatar
Robert Schmidt committed
617
  case one:
618
    return PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_ONE;
Robert Schmidt's avatar
Robert Schmidt committed
619
  case two:
620
    return PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_TWO;
Robert Schmidt's avatar
Robert Schmidt committed
621
  }
622
  return -1;
623 624
}

Robert Schmidt's avatar
Robert Schmidt committed
625 626
uint16_t flexran_get_n1pucch_an(mid_t mod_id, uint8_t cc_id)
{
627 628
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.pucch_config_common.n1PUCCH_AN;
629 630
}

Robert Schmidt's avatar
Robert Schmidt committed
631 632
uint8_t flexran_get_nRB_CQI(mid_t mod_id, uint8_t cc_id)
{
633 634
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.pucch_config_common.nRB_CQI;
635 636
}

Robert Schmidt's avatar
Robert Schmidt committed
637 638
uint8_t flexran_get_deltaPUCCH_Shift(mid_t mod_id, uint8_t cc_id)
{
639 640
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.pucch_config_common.deltaPUCCH_Shift;
641 642
}

Robert Schmidt's avatar
Robert Schmidt committed
643 644
uint8_t flexran_get_prach_ConfigIndex(mid_t mod_id, uint8_t cc_id)
{
645 646
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex;
647 648
}

Robert Schmidt's avatar
Robert Schmidt committed
649 650
uint8_t flexran_get_prach_FreqOffset(mid_t mod_id, uint8_t cc_id)
{
651 652
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset;
653 654
}

Robert Schmidt's avatar
Robert Schmidt committed
655 656
uint8_t flexran_get_maxHARQ_Msg3Tx(mid_t mod_id, uint8_t cc_id)
{
657 658
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.maxHARQ_Msg3Tx;
659 660
}

661
Protocol__FlexUlCyclicPrefixLength flexran_get_ul_cyclic_prefix_length(mid_t mod_id, uint8_t cc_id)
Robert Schmidt's avatar
Robert Schmidt committed
662
{
663 664 665 666 667 668 669 670
  if (!phy_is_present(mod_id, cc_id)) return -1;
  switch (RC.eNB[mod_id][cc_id]->frame_parms.Ncp_UL) {
  case EXTENDED:
    return PROTOCOL__FLEX_UL_CYCLIC_PREFIX_LENGTH__FLUCPL_EXTENDED;
  case NORMAL:
    return PROTOCOL__FLEX_UL_CYCLIC_PREFIX_LENGTH__FLUCPL_NORMAL;
  }
  return -1;
671 672
}

673
Protocol__FlexDlCyclicPrefixLength flexran_get_dl_cyclic_prefix_length(mid_t mod_id, uint8_t cc_id)
Robert Schmidt's avatar
Robert Schmidt committed
674
{
675 676 677 678 679 680 681 682
  if (!phy_is_present(mod_id, cc_id)) return -1;
  switch (RC.eNB[mod_id][cc_id]->frame_parms.Ncp) {
  case EXTENDED:
    return PROTOCOL__FLEX_DL_CYCLIC_PREFIX_LENGTH__FLDCPL_EXTENDED;
  case NORMAL:
    return PROTOCOL__FLEX_DL_CYCLIC_PREFIX_LENGTH__FLDCPL_NORMAL;
  }
  return -1;
683 684
}

Robert Schmidt's avatar
Robert Schmidt committed
685 686
uint16_t flexran_get_cell_id(mid_t mod_id, uint8_t cc_id)
{
687 688
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.Nid_cell;
689 690
}

Robert Schmidt's avatar
Robert Schmidt committed
691 692
uint8_t flexran_get_srs_BandwidthConfig(mid_t mod_id, uint8_t cc_id)
{
693 694
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.soundingrs_ul_config_common.srs_BandwidthConfig;
695 696
}

Robert Schmidt's avatar
Robert Schmidt committed
697 698
uint8_t flexran_get_srs_SubframeConfig(mid_t mod_id, uint8_t cc_id)
{
699 700
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.soundingrs_ul_config_common.srs_SubframeConfig;
701 702
}

Robert Schmidt's avatar
Robert Schmidt committed
703 704
uint8_t flexran_get_srs_MaxUpPts(mid_t mod_id, uint8_t cc_id)
{
705 706
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.soundingrs_ul_config_common.srs_MaxUpPts;
707 708
}

Robert Schmidt's avatar
Robert Schmidt committed
709 710
uint8_t flexran_get_N_RB_DL(mid_t mod_id, uint8_t cc_id)
{
711 712
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.N_RB_DL;
713 714
}

Robert Schmidt's avatar
Robert Schmidt committed
715 716
uint8_t flexran_get_N_RB_UL(mid_t mod_id, uint8_t cc_id)
{
717 718
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.N_RB_UL;
719 720
}

Robert Schmidt's avatar
Robert Schmidt committed
721 722
uint8_t flexran_get_N_RBG(mid_t mod_id, uint8_t cc_id)
{
723 724
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.N_RBG;
725 726
}

Robert Schmidt's avatar
Robert Schmidt committed
727 728
uint8_t flexran_get_subframe_assignment(mid_t mod_id, uint8_t cc_id)
{
729 730
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.tdd_config;
731 732
}

Robert Schmidt's avatar
Robert Schmidt committed
733 734
uint8_t flexran_get_special_subframe_assignment(mid_t mod_id, uint8_t cc_id)
{
735 736
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.tdd_config_S;
737 738
}

Robert Schmidt's avatar
Robert Schmidt committed
739 740
long flexran_get_ra_ResponseWindowSize(mid_t mod_id, uint8_t cc_id)
{
741
  if (!rrc_is_present(mod_id)) return 0;
742
  return RC.rrc[mod_id]->configuration.radioresourceconfig[cc_id].rach_raResponseWindowSize;
743 744
}

Robert Schmidt's avatar
Robert Schmidt committed
745 746
long flexran_get_mac_ContentionResolutionTimer(mid_t mod_id, uint8_t cc_id)
{
747
  if (!rrc_is_present(mod_id)) return 0;
748
  return RC.rrc[mod_id]->configuration.radioresourceconfig[cc_id].rach_macContentionResolutionTimer;
749 750
}

Robert Schmidt's avatar
Robert Schmidt committed
751 752
Protocol__FlexDuplexMode flexran_get_duplex_mode(mid_t mod_id, uint8_t cc_id)
{
753 754
  if (!phy_is_present(mod_id, cc_id)) return 0;
  switch (RC.eNB[mod_id][cc_id]->frame_parms.frame_type) {
Robert Schmidt's avatar
Robert Schmidt committed
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;
  }
762 763
}

Robert Schmidt's avatar
Robert Schmidt committed
764 765
long flexran_get_si_window_length(mid_t mod_id, uint8_t cc_id)
{
766 767
  if (!rrc_is_present(mod_id) || !RC.rrc[mod_id]->carrier[cc_id].sib1) return 0;
  return RC.rrc[mod_id]->carrier[cc_id].sib1->si_WindowLength;
768 769
}

Robert Schmidt's avatar
Robert Schmidt committed
770 771
uint8_t flexran_get_sib1_length(mid_t mod_id, uint8_t cc_id)
{
772 773
  if (!rrc_is_present(mod_id)) return 0;
  return RC.rrc[mod_id]->carrier[cc_id].sizeof_SIB1;
774 775
}

776 777
uint8_t flexran_get_num_pdcch_symb(mid_t mod_id, uint8_t cc_id)
{
778 779
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->pdcch_vars[0].num_pdcch_symbols;
780 781 782 783 784 785 786 787 788
}



/*
 * ************************************
 * Get Messages for UE Configuration Reply
 * ************************************
 */
789 790 791 792 793
int flexran_get_rrc_num_ues(mid_t mod_id)
{
  if (!rrc_is_present(mod_id)) return 0;
  return RC.rrc[mod_id]->Nb_ue;
}
794

795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
rnti_t flexran_get_rrc_rnti_nth_ue(mid_t mod_id, int index)
{
  if (!rrc_is_present(mod_id)) return 0;
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  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;
    --index;
  }
  return 0;
}

int flexran_get_rrc_rnti_list(mid_t mod_id, rnti_t *list, int max_list)
{
  if (!rrc_is_present(mod_id)) return 0;
  int n = 0;
  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
  RB_FOREACH(ue_context_p, rrc_ue_tree_s, &RC.rrc[mod_id]->rrc_ue_head) {
    if (n >= max_list) break;
    list[n] = ue_context_p->ue_context.rnti;
    ++n;
  }
  return n;
}
818

819
LTE_TimeAlignmentTimer_t  flexran_get_time_alignment_timer(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
820
{
821 822
  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);
Robert Schmidt's avatar
Robert Schmidt committed
823 824 825
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.mac_MainConfig) return -1;
  return ue_context_p->ue_context.mac_MainConfig->timeAlignmentTimerDedicated;
826 827
}

828
Protocol__FlexMeasGapConfigPattern flexran_get_meas_gap_config(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
829
{
830 831
  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);
Robert Schmidt's avatar
Robert Schmidt committed
832 833
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.measGapConfig) return -1;
834
  if (ue_context_p->ue_context.measGapConfig->present != LTE_MeasGapConfig_PR_setup) return -1;
Robert Schmidt's avatar
Robert Schmidt committed
835
  switch (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present) {
836
  case LTE_MeasGapConfig__setup__gapOffset_PR_gp0:
Robert Schmidt's avatar
Robert Schmidt committed
837
    return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_GP1;
838
  case LTE_MeasGapConfig__setup__gapOffset_PR_gp1:
Robert Schmidt's avatar
Robert Schmidt committed
839 840 841
    return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_GP2;
  default:
    return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF;
842 843 844
  }
}

shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
845

846
long flexran_get_meas_gap_config_offset(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
847
{
848 849
  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);
Robert Schmidt's avatar
Robert Schmidt committed
850 851
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.measGapConfig) return -1;
852
  if (ue_context_p->ue_context.measGapConfig->present != LTE_MeasGapConfig_PR_setup) return -1;
Robert Schmidt's avatar
Robert Schmidt committed
853
  switch (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present) {
854
  case LTE_MeasGapConfig__setup__gapOffset_PR_gp0:
Robert Schmidt's avatar
Robert Schmidt committed
855
    return ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.choice.gp0;
856
  case LTE_MeasGapConfig__setup__gapOffset_PR_gp1:
Robert Schmidt's avatar
Robert Schmidt committed
857 858 859 860 861
    return ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.choice.gp1;
  default:
    return -1;
  }
}
862

863
uint8_t flexran_get_rrc_status(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
864
{
865 866
  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);
Robert Schmidt's avatar
Robert Schmidt committed
867 868
  if (!ue_context_p) return RRC_INACTIVE;
  return ue_context_p->ue_context.Status;
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
869 870
}

Robert Schmidt's avatar
Robert Schmidt committed
871 872
uint64_t flexran_get_ue_aggregated_max_bitrate_dl(mid_t mod_id, mid_t ue_id)
{
873 874
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL;
875 876
}

Robert Schmidt's avatar
Robert Schmidt committed
877 878
uint64_t flexran_get_ue_aggregated_max_bitrate_ul(mid_t mod_id, mid_t ue_id)
{
879 880
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateUL;
881 882
}

883
int flexran_get_half_duplex(mid_t mod_id, rnti_t rnti)
884 885 886 887 888
{
  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.UE_Capability) return -1;
889
  LTE_SupportedBandListEUTRA_t *bands = &ue_context_p->ue_context.UE_Capability->rf_Parameters.supportedBandListEUTRA;
890 891 892
  for (int i = 0; i < bands->list.count; i++) {
    if (bands->list.array[i]->halfDuplex > 0) return 1;
  }
893 894 895
  return 0;
}

896
int flexran_get_intra_sf_hopping(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
897
{
898 899 900 901 902 903 904 905 906 907 908
  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.UE_Capability) return -1;
  if (!ue_context_p->ue_context.UE_Capability->featureGroupIndicators) return -1;
  /* 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;
909 910
}

911
int flexran_get_type2_sb_1(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
912
{
913 914 915 916 917 918 919 920 921 922 923 924
  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.UE_Capability) return -1;
  if (!ue_context_p->ue_context.UE_Capability->featureGroupIndicators) return -1;
  /* 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;
925 926
}

927
long flexran_get_ue_category(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
928
{
929 930 931 932 933
  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.UE_Capability) return -1;
  return ue_context_p->ue_context.UE_Capability->ue_Category;
934 935
}

936
int flexran_get_res_alloc_type1(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
937
{
938 939 940 941 942 943 944 945 946 947 948
  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.UE_Capability) return -1;
  if (!ue_context_p->ue_context.UE_Capability->featureGroupIndicators) return -1;
  /* 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;
949 950
}

951
long flexran_get_ue_transmission_mode(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
952
{
953 954
  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);
Robert Schmidt's avatar
Robert Schmidt committed
955 956 957 958
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated->antennaInfo) return -1;
  return ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode;
959 960
}

961
BOOLEAN_t flexran_get_tti_bundling(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
962
{
963 964
  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);
Robert Schmidt's avatar
Robert Schmidt committed
965 966 967 968
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.mac_MainConfig) return -1;
  if (!ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config) return -1;
  return ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config->ttiBundling;
969 970
}

971
long flexran_get_maxHARQ_TX(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
972
{
973 974
  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);
Robert Schmidt's avatar
Robert Schmidt committed
975 976 977 978
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.mac_MainConfig) return -1;
  if (!ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config) return -1;
  return *(ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config->maxHARQ_Tx);
979 980
}

981
long flexran_get_beta_offset_ack_index(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
982
{
983 984
  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);
Robert Schmidt's avatar
Robert Schmidt committed
985 986 987 988
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated) return -1;
  return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_ACK_Index;
989 990
}

991
long flexran_get_beta_offset_ri_index(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
992
{
993 994
  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);
Robert Schmidt's avatar
Robert Schmidt committed
995 996 997 998
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated) return -1;
  return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index;
999 1000
}

1001
long flexran_get_beta_offset_cqi_index(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
1002
{
1003 1004
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1005 1006 1007 1008
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated) return -1;
  return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index;
1009 1010
}

1011
BOOLEAN_t flexran_get_simultaneous_ack_nack_cqi(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
1012
{
1013 1014
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1015 1016 1017 1018 1019
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic) return -1;
  return ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.simultaneousAckNackAndCQI;
1020 1021
}

1022
BOOLEAN_t flexran_get_ack_nack_simultaneous_trans(mid_t mod_id, uint8_t cc_id)
Robert Schmidt's avatar
Robert Schmidt committed
1023
{
1024 1025 1026
  if (!rrc_is_present(mod_id)) return -1;
  if (!RC.rrc[mod_id]->carrier[cc_id].sib2) return -1;
  return RC.rrc[mod_id]->carrier[cc_id].sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission;
Robert Schmidt's avatar
Robert Schmidt committed
1027
}
1028

1029
Protocol__FlexAperiodicCqiReportMode flexran_get_aperiodic_cqi_rep_mode(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
1030
{
1031 1032
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1033 1034 1035
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig) return -1;
1036
  switch (*ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic) {
1037
  case LTE_CQI_ReportModeAperiodic_rm12:
1038
    return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM12;
1039
  case LTE_CQI_ReportModeAperiodic_rm20:
1040
    return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM20;
1041
  case LTE_CQI_ReportModeAperiodic_rm22:
1042
    return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM22;
1043
  case LTE_CQI_ReportModeAperiodic_rm30:
1044
    return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM30;
1045
  case LTE_CQI_ReportModeAperiodic_rm31:
1046
    return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM31;
1047
  case LTE_CQI_ReportModeAperiodic_rm32_v1250:
1048
    return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM32_v1250;
1049
  case LTE_CQI_ReportModeAperiodic_rm10_v1310:
1050
    return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM10_v1310;
1051
  case LTE_CQI_ReportModeAperiodic_rm11_v1310:
1052 1053 1054 1055
    return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_RM11_v1310;
  default:
    return PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
  }
1056 1057
}

1058
long flexran_get_tdd_ack_nack_feedback_mode(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
1059
{
1060 1061
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1062 1063 1064 1065 1066
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode) return -1;
  return *(ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode);
1067 1068
}

1069
long flexran_get_ack_nack_repetition_factor(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
1070
{
1071 1072
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1073 1074 1075 1076
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated) return -1;
  return ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->ackNackRepetition.choice.setup.repetitionFactor;
1077 1078
}

1079
long flexran_get_extended_bsr_size(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
1080
{
1081 1082
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1083 1084 1085 1086 1087
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.mac_MainConfig) return -1;
  if (!ue_context_p->ue_context.mac_MainConfig->ext2) return -1;
  if (!ue_context_p->ue_context.mac_MainConfig->ext2->mac_MainConfig_v1020) return -1;
  return *(ue_context_p->ue_context.mac_MainConfig->ext2->mac_MainConfig_v1020->extendedBSR_Sizes_r10);
1088 1089
}

1090
int flexran_get_ue_transmission_antenna(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
1091
{
1092 1093
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1094 1095 1096 1097
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated) return -1;
  if (!ue_context_p->ue_context.physicalConfigDedicated->antennaInfo) return -1;
  switch (ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.choice.setup) {
1098
  case LTE_AntennaInfoDedicated__ue_TransmitAntennaSelection__setup_closedLoop:
Robert Schmidt's avatar
Robert Schmidt committed
1099
    return 2;
1100
  case LTE_AntennaInfoDedicated__ue_TransmitAntennaSelection__setup_openLoop:
Robert Schmidt's avatar
Robert Schmidt committed
1101 1102 1103
    return 1;
  default:
    return 0;
1104 1105 1106
  }
}

1107
uint64_t flexran_get_ue_imsi(mid_t mod_id, rnti_t rnti)
1108
{
1109
  uint64_t imsi;
1110
  if (!rrc_is_present(mod_id)) return 0;
1111
  struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
1112
  if (!ue_context_p) return 0;
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
  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;
1129 1130
}

1131
long flexran_get_lcg(mid_t mod_id, mid_t ue_id, mid_t lc_id)
Robert Schmidt's avatar
Robert Schmidt committed
1132
{
1133 1134
  if (!mac_is_present(mod_id)) return 0;
  return RC.mac[mod_id]->UE_list.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].lcgidmap[lc_id];
1135 1136
}

Robert Schmidt's avatar
Robert Schmidt committed
1137
/* TODO Navid: needs to be revised */
Robert Schmidt's avatar
Robert Schmidt committed
1138 1139 1140 1141 1142
int flexran_get_direction(mid_t ue_id, mid_t lc_id)
{
  switch (lc_id) {
  case DCCH:
  case DCCH1:
1143
    return 2;
Robert Schmidt's avatar
Robert Schmidt committed
1144
  case DTCH:
1145
    return 1;
Robert Schmidt's avatar
Robert Schmidt committed
1146
  default:
1147 1148 1149 1150
    return -1;
  }
}

Robert Schmidt's avatar
Robert Schmidt committed
1151 1152
uint8_t flexran_get_antenna_ports(mid_t mod_id, uint8_t cc_id)
{
1153 1154
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.nb_antenna_ports_eNB;
1155
}
1156

Robert Schmidt's avatar
Robert Schmidt committed
1157 1158
uint32_t flexran_agent_get_operating_dl_freq(mid_t mod_id, uint8_t cc_id)
{
1159 1160
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.dl_CarrierFreq / 1000000;
1161 1162
}

Robert Schmidt's avatar
Robert Schmidt committed
1163 1164
uint32_t flexran_agent_get_operating_ul_freq(mid_t mod_id, uint8_t cc_id)
{
1165 1166
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.ul_CarrierFreq / 1000000;
1167 1168
}

Robert Schmidt's avatar
Robert Schmidt committed
1169 1170
uint8_t flexran_agent_get_operating_eutra_band(mid_t mod_id, uint8_t cc_id)
{
1171 1172
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.eutra_band;
1173
}
Robert Schmidt's avatar
Robert Schmidt committed
1174 1175 1176

int8_t flexran_agent_get_operating_pdsch_refpower(mid_t mod_id, uint8_t cc_id)
{
1177 1178
  if (!phy_is_present(mod_id, cc_id)) return 0;
  return RC.eNB[mod_id][cc_id]->frame_parms.pdsch_config_common.referenceSignalPower;
1179 1180
}

Robert Schmidt's avatar
Robert Schmidt committed
1181 1182
long flexran_agent_get_operating_pusch_p0(mid_t mod_id, uint8_t cc_id)
{
1183
  if (!rrc_is_present(mod_id)) return 0;
1184
  return RC.rrc[mod_id]->configuration.radioresourceconfig[cc_id].pusch_p0_Nominal;
Robert Schmidt's avatar
Robert Schmidt committed
1185
}
1186

Robert Schmidt's avatar
Robert Schmidt committed
1187 1188
void flexran_agent_set_operating_dl_freq(mid_t mod_id, uint8_t cc_id, uint32_t dl_freq_mhz)
{
1189 1190 1191 1192
  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
1193
  }
1194 1195 1196 1197
  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
1198
  }
1199 1200
}

Robert Schmidt's avatar
Robert Schmidt committed
1201 1202
void flexran_agent_set_operating_ul_freq(mid_t mod_id, uint8_t cc_id, int32_t ul_freq_mhz_offset)
{
1203
  if (phy_is_present(mod_id, cc_id)) {
Robert Schmidt's avatar
Robert Schmidt committed
1204
    uint32_t new_ul_freq_mhz = flexran_agent_get_operating_dl_freq(mod_id, cc_id) + ul_freq_mhz_offset;
1205 1206 1207
    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
1208
  }
1209 1210 1211 1212
  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
1213
  }
1214
}
Robert Schmidt's avatar
Robert Schmidt committed
1215 1216 1217

void flexran_agent_set_operating_eutra_band(mid_t mod_id, uint8_t cc_id, uint8_t eutra_band)
{
1218 1219 1220 1221
  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
1222
  }
1223 1224 1225 1226
  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
1227
  }
1228 1229
}

Robert Schmidt's avatar
Robert Schmidt committed
1230 1231 1232
/* Sets both DL/UL */
void flexran_agent_set_operating_bandwidth(mid_t mod_id, uint8_t cc_id, uint8_t N_RB)
{
1233 1234 1235 1236 1237
  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
1238
  }
1239 1240 1241 1242
  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
1243
  }
1244 1245
}

Robert Schmidt's avatar
Robert Schmidt committed
1246 1247
void flexran_agent_set_operating_frame_type(mid_t mod_id, uint8_t cc_id, lte_frame_type_t frame_type)
{
1248 1249 1250 1251
  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
1252
  }
1253 1254 1255 1256
  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
1257
  }
1258 1259
}

1260
/*********** PDCP  *************/
1261

1262
uint16_t flexran_get_pdcp_uid_from_rnti(mid_t mod_id, rnti_t rnti)
1263 1264
{
  if (rnti == NOT_A_RNTI) return 0;
1265 1266
  if (mod_id < 0 || mod_id >= RC.nb_inst)
    return 0;
1267 1268 1269 1270 1271 1272 1273 1274

  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;
  }
  return 0;
}

1275
/*PDCP super frame counter flexRAN*/
1276 1277
uint32_t flexran_get_pdcp_sfn(mid_t mod_id)
{
1278 1279
  if (mod_id < 0 || mod_id >= RC.nb_inst)
    return 0;
1280
  return pdcp_enb[mod_id].sfn;
1281
}
1282

1283
/*PDCP super frame counter flexRAN*/
1284
void flexran_set_pdcp_tx_stat_window(mid_t mod_id, uint16_t uid, uint16_t obs_window)
1285
{
1286 1287 1288 1289
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB)
    return;
  Pdcp_stats_tx_window_ms[mod_id][uid] = obs_window > 0 ? obs_window : 1000;
1290 1291 1292
}

/*PDCP super frame counter flexRAN*/
1293
void flexran_set_pdcp_rx_stat_window(mid_t mod_id, uint16_t uid, uint16_t obs_window)
1294
{
1295 1296 1297 1298
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB)
    return;
  Pdcp_stats_rx_window_ms[mod_id][uid] = obs_window > 0 ? obs_window : 1000;
1299 1300
}

1301
/*PDCP num tx pdu status flexRAN*/
1302
uint32_t flexran_get_pdcp_tx(mid_t mod_id, uint16_t uid, lcid_t lcid)
1303
{
1304 1305 1306
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1307
  return Pdcp_stats_tx[mod_id][uid][lcid];
1308 1309 1310
}

/*PDCP num tx bytes status flexRAN*/
1311
uint32_t flexran_get_pdcp_tx_bytes(mid_t mod_id, uint16_t uid, lcid_t lcid)
1312
{
1313 1314 1315
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1316
  return Pdcp_stats_tx_bytes[mod_id][uid][lcid];
1317 1318 1319
}

/*PDCP number of transmit packet / second status flexRAN*/
1320
uint32_t flexran_get_pdcp_tx_w(mid_t mod_id, uint16_t uid, lcid_t lcid)
1321
{
1322 1323 1324
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1325
  return Pdcp_stats_tx_w[mod_id][uid][lcid];
1326 1327 1328
}

/*PDCP throughput (bit/s) status flexRAN*/
1329
uint32_t flexran_get_pdcp_tx_bytes_w(mid_t mod_id, uint16_t uid, lcid_t lcid)
1330
{
1331 1332 1333
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1334
  return Pdcp_stats_tx_bytes_w[mod_id][uid][lcid];
1335 1336 1337
}

/*PDCP tx sequence number flexRAN*/
1338
uint32_t flexran_get_pdcp_tx_sn(mid_t mod_id, uint16_t uid, lcid_t lcid)
1339
{
1340 1341 1342
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1343
  return Pdcp_stats_tx_sn[mod_id][uid][lcid];
1344 1345 1346
}

/*PDCP tx aggregated packet arrival  flexRAN*/
1347
uint32_t flexran_get_pdcp_tx_aiat(mid_t mod_id, uint16_t uid, lcid_t lcid)
1348
{
1349 1350 1351
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1352
  return Pdcp_stats_tx_aiat[mod_id][uid][lcid];
1353 1354 1355
}

/*PDCP tx aggregated packet arrival  flexRAN*/
1356
uint32_t flexran_get_pdcp_tx_aiat_w(mid_t mod_id, uint16_t uid, lcid_t lcid)
1357
{
1358 1359 1360
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1361
  return Pdcp_stats_tx_aiat_w[mod_id][uid][lcid];
1362 1363 1364
}

/*PDCP num rx pdu status flexRAN*/
1365
uint32_t flexran_get_pdcp_rx(mid_t mod_id, uint16_t uid, lcid_t lcid)
1366
{
1367 1368 1369
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1370
  return Pdcp_stats_rx[mod_id][uid][lcid];
1371 1372 1373
}

/*PDCP num rx bytes status flexRAN*/
1374
uint32_t flexran_get_pdcp_rx_bytes(mid_t mod_id, uint16_t uid, lcid_t lcid)
1375
{
1376 1377 1378
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1379
  return Pdcp_stats_rx_bytes[mod_id][uid][lcid];
1380 1381 1382
}

/*PDCP number of received packet / second  flexRAN*/
1383
uint32_t flexran_get_pdcp_rx_w(mid_t mod_id, uint16_t uid, lcid_t lcid)
1384
{
1385 1386 1387
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1388
  return Pdcp_stats_rx_w[mod_id][uid][lcid];
1389 1390 1391
}

/*PDCP gootput (bit/s) status flexRAN*/
1392
uint32_t flexran_get_pdcp_rx_bytes_w(mid_t mod_id, uint16_t uid, lcid_t lcid)
1393
{
1394 1395 1396
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1397
  return Pdcp_stats_rx_bytes_w[mod_id][uid][lcid];
1398 1399 1400
}

/*PDCP rx sequence number flexRAN*/
1401
uint32_t flexran_get_pdcp_rx_sn(mid_t mod_id, uint16_t uid, lcid_t lcid)
1402
{
1403 1404 1405
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1406
  return Pdcp_stats_rx_sn[mod_id][uid][lcid];
1407 1408 1409
}

/*PDCP rx aggregated packet arrival  flexRAN*/
1410
uint32_t flexran_get_pdcp_rx_aiat(mid_t mod_id, uint16_t uid, lcid_t lcid)
1411
{
1412 1413 1414
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1415
  return Pdcp_stats_rx_aiat[mod_id][uid][lcid];
1416 1417 1418
}

/*PDCP rx aggregated packet arrival  flexRAN*/
1419
uint32_t flexran_get_pdcp_rx_aiat_w(mid_t mod_id, uint16_t uid, lcid_t lcid)
1420
{
1421 1422 1423
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1424
  return Pdcp_stats_rx_aiat_w[mod_id][uid][lcid];
1425 1426 1427
}

/*PDCP num of received outoforder pdu status flexRAN*/
1428
uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, uint16_t uid, lcid_t lcid)
1429
{
1430 1431 1432
  if (mod_id < 0 || mod_id >= RC.nb_inst || uid < 0
      || uid >= MAX_MOBILES_PER_ENB || lcid < 0 || lcid >= NB_RB_MAX)
    return 0;
1433
  return Pdcp_stats_rx_outoforder[mod_id][uid][lcid];
1434
}
1435

1436
/******************** RRC *****************************/
1437

1438
LTE_MeasId_t  flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
1439
{
1440 1441
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1442 1443 1444
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.measResults) return -1;
  return ue_context_p->ue_context.measResults->measId;
1445
}
1446

1447
float flexran_get_rrc_pcell_rsrp(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
1448
{
1449 1450
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1451 1452 1453
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.measResults) return -1;
  return RSRP_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrpResult];
1454 1455
}

1456
float flexran_get_rrc_pcell_rsrq(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
1457
{
1458 1459
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1460 1461 1462
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.measResults) return -1;
  return RSRQ_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrqResult];
1463 1464
}

Robert Schmidt's avatar
Robert Schmidt committed
1465
/*Number of neighbouring cells for specific UE*/
1466
int flexran_get_rrc_num_ncell(mid_t mod_id, rnti_t rnti)
Robert Schmidt's avatar
Robert Schmidt committed
1467
{
1468 1469
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1470 1471 1472
  if (!ue_context_p) return 0;
  if (!ue_context_p->ue_context.measResults) return 0;
  if (!ue_context_p->ue_context.measResults->measResultNeighCells) return 0;
1473
  if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return 0;
Robert Schmidt's avatar
Robert Schmidt committed
1474 1475
  return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.count;
}
1476

1477
long flexran_get_rrc_neigh_phy_cell_id(mid_t mod_id, rnti_t rnti, long cell_id)
Robert Schmidt's avatar
Robert Schmidt committed
1478
{
1479 1480
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1481 1482 1483
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.measResults) return -1;
  if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1;
1484
  if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1;
Robert Schmidt's avatar
Robert Schmidt committed
1485 1486 1487
  if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1;
  return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->physCellId;
}
1488

1489
float flexran_get_rrc_neigh_rsrp(mid_t mod_id, rnti_t rnti, long cell_id)
Robert Schmidt's avatar
Robert Schmidt committed
1490
{
1491 1492
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1493 1494 1495
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.measResults) return -1;
  if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1;
1496
  if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1;
Robert Schmidt's avatar
Robert Schmidt committed
1497 1498 1499
  if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1;
  if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrpResult) return 0;
  return RSRP_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrpResult)];
1500 1501
}

1502
float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id)
Robert Schmidt's avatar
Robert Schmidt committed
1503
{
1504 1505
  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);
Robert Schmidt's avatar
Robert Schmidt committed
1506 1507 1508
  if (!ue_context_p) return -1;
  if (!ue_context_p->ue_context.measResults) return -1;
  if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1;
1509
  if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1;
Robert Schmidt's avatar
Robert Schmidt committed
1510 1511
  if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult) return 0;
  return RSRQ_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult)];
1512
}
1513

1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537
uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id)
{
  if (!rrc_is_present(mod_id)) return 0;
  return RC.rrc[mod_id]->configuration.num_plmn;
}

uint16_t flexran_get_rrc_mcc(mid_t mod_id, uint8_t index)
{
  if (!rrc_is_present(mod_id)) return 0;
  return RC.rrc[mod_id]->configuration.mcc[index];
}

uint16_t flexran_get_rrc_mnc(mid_t mod_id, uint8_t index)
{
  if (!rrc_is_present(mod_id)) return 0;
  return RC.rrc[mod_id]->configuration.mnc[index];
}

uint8_t flexran_get_rrc_mnc_digit_length(mid_t mod_id, uint8_t index)
{
  if (!rrc_is_present(mod_id)) return 0;
  return RC.rrc[mod_id]->configuration.mnc_digit_length[index];
}

1538
/**************************** SLICING ****************************/
1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id)
{
  if (!mac_is_present(mod_id)) return -1;
  int slice_idx = RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id];
  if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl)
    return RC.mac[mod_id]->slice_info.dl[slice_idx].id;
  return 0;
}

void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return;
1551
  if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return;
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567
  if (!flexran_dl_slice_exists(mod_id, slice_idx)) return;
  RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id] = slice_idx;
}

int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id)
{
  if (!mac_is_present(mod_id)) return -1;
  int slice_idx = RC.mac[mod_id]->UE_list.assoc_ul_slice_idx[ue_id];
  if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul)
    return RC.mac[mod_id]->slice_info.ul[slice_idx].id;
  return 0;
}

void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return;
1568
  if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return;
1569 1570 1571 1572 1573 1574 1575 1576 1577 1578
  if (!flexran_ul_slice_exists(mod_id, slice_idx)) return;
  RC.mac[mod_id]->UE_list.assoc_ul_slice_idx[ue_id] = slice_idx;
}

int flexran_dl_slice_exists(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl;
}

1579
int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id)
1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605
{
  if (!mac_is_present(mod_id)) return -1;
  int newidx = RC.mac[mod_id]->slice_info.n_dl;
  if (newidx >= MAX_NUM_SLICES) return -1;
  ++RC.mac[mod_id]->slice_info.n_dl;
  flexran_set_dl_slice_id(mod_id, newidx, slice_id);
  return newidx;
}

int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id)
{
  if (!mac_is_present(mod_id)) return -1;
  slice_info_t *sli = &RC.mac[mod_id]->slice_info;
  int n = sli->n_dl;
  for (int i = 0; i < n; i++) {
    if (sli->dl[i].id == slice_id) return i;
  }
  return -1;
}

int flexran_remove_dl_slice(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  slice_info_t *sli = &RC.mac[mod_id]->slice_info;
  if (sli->n_dl <= 1) return -1;

1606
  if (sli->dl[slice_idx].sched_name) free(sli->dl[slice_idx].sched_name);
1607 1608 1609 1610
  --sli->n_dl;
  /* move last element to the position of the removed one */
  if (slice_idx != sli->n_dl)
    memcpy(&sli->dl[slice_idx], &sli->dl[sli->n_dl], sizeof(sli->dl[sli->n_dl]));
1611
  memset(&sli->dl[sli->n_dl], 0, sizeof(sli->dl[sli->n_dl]));
1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 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

  /* all UEs that have been in the old slice are put into slice index 0 */
  int *assoc_list = RC.mac[mod_id]->UE_list.assoc_dl_slice_idx;
  for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) {
    if (assoc_list[i] == slice_idx)
      assoc_list[i] = 0;
  }
  return sli->n_dl;
}

int flexran_get_num_dl_slices(mid_t mod_id)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.n_dl;
}

int flexran_get_intraslice_sharing_active(mid_t mod_id)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.intraslice_share_active;
}
void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.intraslice_share_active = intraslice_active;
}

int flexran_get_interslice_sharing_active(mid_t mod_id)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.interslice_share_active;
}
void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.interslice_share_active = interslice_active;
}

slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.dl[slice_idx].id;
}
void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.dl[slice_idx].id = slice_id;
}

int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.dl[slice_idx].pct * 100.0f;
}
void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.dl[slice_idx].pct = percentage / 100.0f;
}

int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.dl[slice_idx].isol;
}
void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.dl[slice_idx].isol = is_isolated;
}

int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.dl[slice_idx].prio;
}
void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.dl[slice_idx].prio = priority;
}

int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low;
}
void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low = poslow;
}

int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high;
}
void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high = poshigh;
}

int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs;
}
void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs = maxmcs;
}

int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list)
{
  if (!mac_is_present(mod_id)) return -1;
  if (!(*sorting_list)) {
    *sorting_list = calloc(CR_NUM, sizeof(Protocol__FlexDlSorting));
    if (!(*sorting_list)) return -1;
  }
  uint32_t policy = RC.mac[mod_id]->slice_info.dl[slice_idx].sorting;
  for (int i = 0; i < CR_NUM; i++) {
    switch (policy >> 4 * (CR_NUM - 1 - i) & 0xF) {
    case CR_ROUND:
      (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND;
      break;
    case CR_SRB12:
      (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_SRB12;
      break;
    case CR_HOL:
      (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_HOL;
      break;
    case CR_LC:
      (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LC;
      break;
    case CR_CQI:
      (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_CQI;
      break;
    case CR_LCP:
      (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LCP;
      break;
    default:
      /* this should not happen, but a "default" */
      (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND;
      break;
    }
  }
  return CR_NUM;
}
void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n)
{
  if (!mac_is_present(mod_id)) return;
  uint32_t policy = 0;
  for (int i = 0; i < n && i < CR_NUM; i++) {
    switch (sorting_list[i]) {
    case PROTOCOL__FLEX_DL_SORTING__CR_ROUND:
      policy = policy << 4 | CR_ROUND;
      break;
    case PROTOCOL__FLEX_DL_SORTING__CR_SRB12:
      policy = policy << 4 | CR_SRB12;
      break;
    case PROTOCOL__FLEX_DL_SORTING__CR_HOL:
      policy = policy << 4 | CR_HOL;
      break;
    case PROTOCOL__FLEX_DL_SORTING__CR_LC:
      policy = policy << 4 | CR_LC;
      break;
    case PROTOCOL__FLEX_DL_SORTING__CR_CQI:
      policy = policy << 4 | CR_CQI;
      break;
    case PROTOCOL__FLEX_DL_SORTING__CR_LCP:
      policy = policy << 4 | CR_LCP;
      break;
    default: /* suppresses warnings */
      policy = policy << 4 | CR_ROUND;
      break;
    }
  }
  /* fill up with 0 == CR_ROUND */
  if (CR_NUM > n) policy = policy << 4 * (CR_NUM - n);
  RC.mac[mod_id]->slice_info.dl[slice_idx].sorting = policy;
}

Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
  switch (RC.mac[mod_id]->slice_info.dl[slice_idx].accounting) {
  case POL_FAIR:
    return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
  case POL_GREEDY:
    return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY;
  default:
    return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
  }
}
void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting)
{
  if (!mac_is_present(mod_id)) return;
  switch (accounting) {
  case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR:
    RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR;
    return;
  case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY:
    RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_GREEDY;
    return;
  default:
    RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR;
    return;
  }
}

1825
char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx)
1826 1827 1828 1829
{
  if (!mac_is_present(mod_id)) return NULL;
  return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name;
}
1830
int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name)
1831
{
1832
  if (!mac_is_present(mod_id)) return 0;
1833 1834
  if (RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name)
    free(RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name);
1835 1836 1837
  RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name = strdup(name);
  RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb = dlsym(NULL, name);
  return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb != NULL;
1838 1839
}

1840
int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id)
1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866
{
  if (!mac_is_present(mod_id)) return -1;
  int newidx = RC.mac[mod_id]->slice_info.n_ul;
  if (newidx >= MAX_NUM_SLICES) return -1;
  ++RC.mac[mod_id]->slice_info.n_ul;
  flexran_set_ul_slice_id(mod_id, newidx, slice_id);
  return newidx;
}

int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id)
{
  if (!mac_is_present(mod_id)) return -1;
  slice_info_t *sli = &RC.mac[mod_id]->slice_info;
  int n = sli->n_ul;
  for (int i = 0; i < n; i++) {
    if (sli->ul[i].id == slice_id) return i;
  }
  return -1;
}

int flexran_remove_ul_slice(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  slice_info_t *sli = &RC.mac[mod_id]->slice_info;
  if (sli->n_ul <= 1) return -1;

1867
  if (sli->ul[slice_idx].sched_name) free(sli->ul[slice_idx].sched_name);
1868 1869 1870 1871
  --sli->n_ul;
  /* move last element to the position of the removed one */
  if (slice_idx != sli->n_ul)
    memcpy(&sli->ul[slice_idx], &sli->ul[sli->n_ul], sizeof(sli->ul[sli->n_ul]));
1872
  memset(&sli->ul[sli->n_ul], 0, sizeof(sli->ul[sli->n_ul]));
1873 1874 1875 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

  /* all UEs that have been in the old slice are put into slice index 0 */
  int *assoc_list = RC.mac[mod_id]->UE_list.assoc_ul_slice_idx;
  for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) {
    if (assoc_list[i] == slice_idx)
      assoc_list[i] = 0;
  }
  return sli->n_ul;
}

int flexran_get_num_ul_slices(mid_t mod_id)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.n_ul;
}

int flexran_ul_slice_exists(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul;
}

slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.ul[slice_idx].id;
}
void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.ul[slice_idx].id = slice_id;
}

int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.ul[slice_idx].pct * 100.0f;
}
void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.ul[slice_idx].pct = percentage / 100.0f;
}

int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb;
}

void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb = first_rb;
}

int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx)
{
  if (!mac_is_present(mod_id)) return -1;
  return RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs;
}
void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs)
{
  if (!mac_is_present(mod_id)) return;
  RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs = maxmcs;
}

1940
char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx)
1941 1942 1943 1944
{
  if (!mac_is_present(mod_id)) return NULL;
  return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name;
}
1945
int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name)
1946
{
1947
  if (!mac_is_present(mod_id)) return 0;
1948 1949
  if (RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name)
    free(RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name);
1950 1951 1952
  RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name = strdup(name);
  RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb = dlsym(NULL, name);
  return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb != NULL;
1953
}
1954 1955

/**************************** General BS info  ****************************/
1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 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 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045
uint64_t flexran_get_bs_id(mid_t mod_id)
{
  if (!rrc_is_present(mod_id)) return 0;
  return RC.rrc[mod_id]->nr_cellid;
}

size_t flexran_get_capabilities(mid_t mod_id, Protocol__FlexBsCapability **caps)
{
  if (!caps) return 0;
  if (!rrc_is_present(mod_id)) return 0;
  size_t n_caps = 0;
  switch (RC.rrc[mod_id]->node_type) {
  case ngran_eNB_CU:
  case ngran_ng_eNB_CU:
  case ngran_gNB_CU:
    n_caps = 3;
    *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;
    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:
    n_caps = 8;
    *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;
    break;
  }
  return n_caps;
}

uint16_t flexran_get_capabilities_mask(mid_t mod_id)
{
  if (!rrc_is_present(mod_id)) return 0;
  uint16_t mask = 0;
  switch (RC.rrc[mod_id]->node_type) {
  case ngran_eNB_CU:
  case ngran_ng_eNB_CU:
  case ngran_gNB_CU:
    mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
         | (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
         | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC);
    break;
  case ngran_eNB_DU:
  case ngran_gNB_DU:
    mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)
         | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)
         | (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
         | (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
         | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC);
    break;
  case ngran_eNB:
  case ngran_ng_eNB:
  case ngran_gNB:
    mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)
         | (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)
         | (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC);
    break;
  }
  return mask;
}