flexran_agent_mac.c 54.7 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
Cedric Roux's avatar
Cedric Roux committed
20
 */
21

22 23
/*! \file flexran_agent_mac.c
 * \brief FlexRAN agent message handler for MAC layer
24
 * \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
25 26 27 28
 * \date 2016
 * \version 0.1
 */

29 30 31 32
#include "flexran_agent_mac.h"
#include "flexran_agent_extern.h"
#include "flexran_agent_common.h"
#include "flexran_agent_mac_internal.h"
33
#include "flexran_agent_net_comm.h"
34
#include "flexran_agent_timer.h"
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
35
#include "flexran_agent_ran_api.h"
36

37
#include "LAYER2/MAC/mac_proto.h"
38

39 40
#include "liblfds700.h"

41
#include "common/utils/LOG/log.h"
42

43 44 45
/*Array containing the Agent-MAC interfaces*/
AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];

46 47 48 49 50 51 52
/* Ringbuffer related structs used for maintaining the dl mac config messages */
//message_queue_t *dl_mac_config_queue;
struct lfds700_misc_prng_state ps[NUM_MAX_ENB];
struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB];
struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB];


Cedric Roux's avatar
Cedric Roux committed
53
int flexran_agent_mac_stats_reply(mid_t mod_id,
54 55 56
          const report_config_t *report_config,
           Protocol__FlexUeStatsReport **ue_report,
           Protocol__FlexCellStatsReport **cell_report) {
57 58


59 60
  // Protocol__FlexHeader *header;
  int i, j, k;
61
  int cc_id = 0;
62
  int enb_id = mod_id;
63

64 65
  /* Allocate memory for list of UE reports */
  if (report_config->nr_ue > 0) {
66

Cedric Roux's avatar
Cedric Roux committed
67

68 69
          for (i = 0; i < report_config->nr_ue; i++) {

70 71
                ue_report[i]->rnti = report_config->ue_report_type[i].ue_rnti;
                ue_report[i]->has_rnti = 1;
72 73 74 75

                /* Check flag for creation of buffer status report */
                if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_BSR) {
                      //TODO should be automated
Cedric Roux's avatar
Cedric Roux committed
76
                        ue_report[i]->n_bsr = 4;
77 78 79 80 81
                        uint32_t *elem;
                        elem = (uint32_t *) malloc(sizeof(uint32_t)*ue_report[i]->n_bsr);
                        if (elem == NULL)
                               goto error;
                        for (j = 0; j < ue_report[i]->n_bsr; j++) {
Cedric Roux's avatar
Cedric Roux committed
82
                                // NN: we need to know the cc_id here, consider the first one
83
                                elem[j] = flexran_get_ue_bsr_ul_buffer_info (enb_id, i, j);
84
                        }
Cedric Roux's avatar
Cedric Roux committed
85

86 87
                        ue_report[i]->bsr = elem;
                }
Cedric Roux's avatar
Cedric Roux committed
88

89 90 91 92
                /* Check flag for creation of PHR report */
                if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PHR) {
                        ue_report[i]->phr = flexran_get_ue_phr (enb_id, i); // eNB_UE_list->UE_template[UE_PCCID(enb_id,i)][i].phr_info;
                        ue_report[i]->has_phr = 1;
Cedric Roux's avatar
Cedric Roux committed
93

94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
                }

                /* Check flag for creation of RLC buffer status report */
                if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RLC_BS) {
                        ue_report[i]->n_rlc_report = 3; // Set this to the number of LCs for this UE. This needs to be generalized for for LCs
                        Protocol__FlexRlcBsr ** rlc_reports;
                        rlc_reports = malloc(sizeof(Protocol__FlexRlcBsr *) * ue_report[i]->n_rlc_report);
                        if (rlc_reports == NULL)
                              goto error;

                        // NN: see LAYER2/openair2_proc.c for rlc status
                        for (j = 0; j < ue_report[i]->n_rlc_report; j++) {

                              rlc_reports[j] = malloc(sizeof(Protocol__FlexRlcBsr));
                              if (rlc_reports[j] == NULL)
                                 goto error;
                              protocol__flex_rlc_bsr__init(rlc_reports[j]);
                              rlc_reports[j]->lc_id = j+1;
                              rlc_reports[j]->has_lc_id = 1;
113
                              rlc_reports[j]->tx_queue_size = flexran_get_tx_queue_size(enb_id, i, j + 1);
114 115 116
                              rlc_reports[j]->has_tx_queue_size = 1;

                              //TODO:Set tx queue head of line delay in ms
117
                              rlc_reports[j]->tx_queue_hol_delay = flexran_get_hol_delay(enb_id, i, j + 1);
118 119 120 121 122 123 124 125
                              rlc_reports[j]->has_tx_queue_hol_delay = 1;
                              //TODO:Set retransmission queue size in bytes
                              rlc_reports[j]->retransmission_queue_size = 10;
                              rlc_reports[j]->has_retransmission_queue_size = 0;
                              //TODO:Set retransmission queue head of line delay in ms
                              rlc_reports[j]->retransmission_queue_hol_delay = 100;
                              rlc_reports[j]->has_retransmission_queue_hol_delay = 0;
                              //TODO DONE:Set current size of the pending message in bytes
126
                              rlc_reports[j]->status_pdu_size = flexran_get_num_pdus_buffer(enb_id , i, j + 1);
127 128 129 130 131 132 133
                              rlc_reports[j]->has_status_pdu_size = 1;

                        }
                        // Add RLC buffer status reports to the full report
                        if (ue_report[i]->n_rlc_report > 0)
                            ue_report[i]->rlc_report = rlc_reports;

Cedric Roux's avatar
Cedric Roux committed
134

135 136 137 138 139
                }

                /* Check flag for creation of MAC CE buffer status report */
                if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_CE_BS) {
                        // TODO: Fill in the actual MAC CE buffer status report
Cedric Roux's avatar
Cedric Roux committed
140
                        ue_report[i]->pending_mac_ces = (flexran_get_MAC_CE_bitmap_TA(enb_id,i,0) | (0 << 1) | (0 << 2) | (0 << 3)) & 15;
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
141 142 143
                                      // Use as bitmap. Set one or more of the; /* Use as bitmap. Set one or more of the
                                       // PROTOCOL__FLEX_CE_TYPE__FLPCET_ values
                                       // found in stats_common.pb-c.h. See
Cedric Roux's avatar
Cedric Roux committed
144
                                       // flex_ce_type in FlexRAN specification
145
                        ue_report[i]->has_pending_mac_ces = 1;
Cedric Roux's avatar
Cedric Roux committed
146

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
                }

                /* Check flag for creation of DL CQI report */
                if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) {
                        // TODO: Fill in the actual DL CQI report for the UE based on its configuration
                        Protocol__FlexDlCqiReport * dl_report;
                        dl_report = malloc(sizeof(Protocol__FlexDlCqiReport));
                        if (dl_report == NULL)
                          goto error;
                        protocol__flex_dl_cqi_report__init(dl_report);

                        dl_report->sfn_sn = flexran_get_sfn_sf(enb_id);
                        dl_report->has_sfn_sn = 1;
                        //Set the number of DL CQI reports for this UE. One for each CC
                        dl_report->n_csi_report = flexran_get_active_CC(enb_id,i);
                        dl_report->n_csi_report = 1 ;
                        //Create the actual CSI reports.
                        Protocol__FlexDlCsi **csi_reports;
                        csi_reports = malloc(sizeof(Protocol__FlexDlCsi *)*dl_report->n_csi_report);
                        if (csi_reports == NULL)
Cedric Roux's avatar
Cedric Roux committed
167
                          goto error;
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
                        for (j = 0; j < dl_report->n_csi_report; j++) {

                              csi_reports[j] = malloc(sizeof(Protocol__FlexDlCsi));
                              if (csi_reports[j] == NULL)
                                goto error;
                              protocol__flex_dl_csi__init(csi_reports[j]);
                              //The servCellIndex for this report
                              csi_reports[j]->serv_cell_index = j;
                              csi_reports[j]->has_serv_cell_index = 1;
                              //The rank indicator value for this cc
                              csi_reports[j]->ri = flexran_get_current_RI(enb_id,i,j);
                              csi_reports[j]->has_ri = 1;
                              //TODO: the type of CSI report based on the configuration of the UE
                              //For now we only support type P10, which only needs a wideband value
                              //The full set of types can be found in stats_common.pb-c.h and
                              //in the FlexRAN specifications
                              csi_reports[j]->type =  PROTOCOL__FLEX_CSI_TYPE__FLCSIT_P10;
                              csi_reports[j]->has_type = 1;
                              csi_reports[j]->report_case = PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI;

                              if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI){

                                    Protocol__FlexCsiP10 *csi10;
                                    csi10 = malloc(sizeof(Protocol__FlexCsiP10));
                                    if (csi10 == NULL)
                                    goto error;
                                    protocol__flex_csi_p10__init(csi10);
                                    //TODO: set the wideband value
                                    // NN: this is also depends on cc_id
                                    csi10->wb_cqi = flexran_get_ue_wcqi (enb_id, i); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].dl_cqi;
                                    csi10->has_wb_cqi = 1;
                                    //Add the type of measurements to the csi report in the proper union type
                                    csi_reports[j]->p10csi = csi10;
                              }

                              else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI){


                                    Protocol__FlexCsiP11 *csi11;
                                    csi11 = malloc(sizeof(Protocol__FlexCsiP11));
                                    if (csi11 == NULL)
                                    goto error;
                                    protocol__flex_csi_p11__init(csi11);
Cedric Roux's avatar
Cedric Roux committed
211 212

                                    csi11->wb_cqi = malloc(sizeof(csi11->wb_cqi));
Xenofon Foukas's avatar
Xenofon Foukas committed
213
				    csi11->n_wb_cqi = 1;
Cedric Roux's avatar
Cedric Roux committed
214 215 216
				    csi11->wb_cqi[0] = flexran_get_ue_wcqi (enb_id, i);
                                    // According To spec 36.213

217 218
                                    if (flexran_get_antenna_ports(enb_id, j) == 2 && csi_reports[j]->ri == 1) {
                                        // TODO PMI
Robert Schmidt's avatar
Robert Schmidt committed
219
                                        csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, i, 0);
220 221
                                        csi11->has_wb_pmi = 1;

Cedric Roux's avatar
Cedric Roux committed
222
                                       }
223 224 225

                                      else if (flexran_get_antenna_ports(enb_id, j) == 2 && csi_reports[j]->ri == 2){
                                        // TODO PMI
Robert Schmidt's avatar
Robert Schmidt committed
226
                                        csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, i, 0);
227 228 229 230 231 232
                                        csi11->has_wb_pmi = 1;

                                      }

                                      else if (flexran_get_antenna_ports(enb_id, j) == 4 && csi_reports[j]->ri == 2){
                                        // TODO PMI
Robert Schmidt's avatar
Robert Schmidt committed
233
                                        csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, i, 0);
234 235 236 237 238
                                        csi11->has_wb_pmi = 1;


                                      }

Cedric Roux's avatar
Cedric Roux committed
239
                                      csi11->has_wb_pmi = 0;
240 241 242 243 244

                                      csi_reports[j]->p11csi = csi11;

                               }

Cedric Roux's avatar
Cedric Roux committed
245 246


247 248 249 250 251 252 253 254 255


                              else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI){

                                    Protocol__FlexCsiP20 *csi20;
                                    csi20 = malloc(sizeof(Protocol__FlexCsiP20));
                                    if (csi20 == NULL)
                                    goto error;
                                    protocol__flex_csi_p20__init(csi20);
Cedric Roux's avatar
Cedric Roux committed
256 257

                                    csi20->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
258
                                    csi20->has_wb_cqi = 1;
259

Cedric Roux's avatar
Cedric Roux committed
260

261 262
                                    csi20->bandwidth_part_index = 1 ;//TODO
                                    csi20->has_bandwidth_part_index = 1;
263

264
                                    csi20->sb_index = 1 ;//TODO
Cedric Roux's avatar
Cedric Roux committed
265
                                    csi20->has_sb_index = 1 ;
266 267


268
                                    csi_reports[j]->p20csi = csi20;
269

270

271
                              }
272

273
                              else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI){
274

275 276 277 278 279
                                  // Protocol__FlexCsiP21 *csi21;
                                  // csi21 = malloc(sizeof(Protocol__FlexCsiP21));
                                  // if (csi21 == NULL)
                                  // goto error;
                                  // protocol__flex_csi_p21__init(csi21);
Cedric Roux's avatar
Cedric Roux committed
280 281 282 283

                                  // csi21->wb_cqi = flexran_get_ue_wcqi (enb_id, i);


284 285
                                  // csi21->wb_pmi = flexran_get_ue_pmi(enb_id); //TDO inside
                                  // csi21->has_wb_pmi = 1;
286

Cedric Roux's avatar
Cedric Roux committed
287 288
                                  // csi21->sb_cqi = 1; // TODO

289
                                  // csi21->bandwidth_part_index = 1 ; //TDO inside
Cedric Roux's avatar
Cedric Roux committed
290
                                  // csi21->has_bandwidth_part_index = 1 ;
291

292
                                  // csi21->sb_index = 1 ;//TODO
Cedric Roux's avatar
Cedric Roux committed
293
                                  // csi21->has_sb_index = 1 ;
294

295

296
                                  // csi_reports[j]->p20csi = csi21;
297

298
                              }
299

300
                              else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI){
301

302

303 304 305 306 307
                                  // Protocol__FlexCsiA12 *csi12;
                                  // csi12 = malloc(sizeof(Protocol__FlexCsiA12));
                                  // if (csi12 == NULL)
                                  // goto error;
                                  // protocol__flex_csi_a12__init(csi12);
Cedric Roux's avatar
Cedric Roux committed
308 309 310 311

                                  // csi12->wb_cqi = flexran_get_ue_wcqi (enb_id, i);

                                  // csi12->sb_pmi = 1 ; //TODO inside
312

313 314
                                  // TODO continou
                              }
315

316
                              else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI){
317

318 319 320 321 322
                                    // Protocol__FlexCsiA22 *csi22;
                                    // csi22 = malloc(sizeof(Protocol__FlexCsiA22));
                                    // if (csi22 == NULL)
                                    // goto error;
                                    // protocol__flex_csi_a22__init(csi22);
323

Cedric Roux's avatar
Cedric Roux committed
324 325 326 327 328
                                    // csi22->wb_cqi = flexran_get_ue_wcqi (enb_id, i);

                                    // csi22->sb_cqi = 1 ; //TODO inside

                                    // csi22->wb_pmi = flexran_get_ue_wcqi (enb_id, i);
329
                                    // csi22->has_wb_pmi = 1;
Cedric Roux's avatar
Cedric Roux committed
330 331

                                    // csi22->sb_pmi = 1 ; //TODO inside
332
                                    // csi22->has_wb_pmi = 1;
333

Cedric Roux's avatar
Cedric Roux committed
334
                                    // csi22->sb_list = flexran_get_ue_wcqi (enb_id, i);
335

336 337 338 339 340 341 342 343 344 345 346

                                }

                                else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI){

                                    // Protocol__FlexCsiA20 *csi20;
                                    // csi20 = malloc(sizeof(Protocol__FlexCsiA20));
                                    // if (csi20 == NULL)
                                    // goto error;
                                    // protocol__flex_csi_a20__init(csi20);

Cedric Roux's avatar
Cedric Roux committed
347
                                    // csi20->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
348 349
                                    // csi20->has_wb_cqi = 1;

Cedric Roux's avatar
Cedric Roux committed
350
                                    // csi20>sb_cqi = 1 ; //TODO inside
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
                                    // csi20>has_sb_cqi = 1 ;

                                    // csi20->sb_list = 1; // TODO inside


                                }

                                else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI){

                                }

                                else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI){

                                }

                        }
                     //Add the csi reports to the full DL CQI report
                    dl_report->csi_report = csi_reports;
                    //Add the DL CQI report to the stats report
                     ue_report[i]->dl_cqi_report = dl_report;
Cedric Roux's avatar
Cedric Roux committed
371

372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
                }

                /* Check flag for creation of paging buffer status report */
                if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) {
                            //TODO: Fill in the actual paging buffer status report. For this field to be valid, the RNTI
                            //set in the report must be a P-RNTI
                            Protocol__FlexPagingBufferReport *paging_report;
                            paging_report = malloc(sizeof(Protocol__FlexPagingBufferReport));
                            if (paging_report == NULL)
                              goto error;
                            protocol__flex_paging_buffer_report__init(paging_report);
                            //Set the number of pending paging messages
                            paging_report->n_paging_info = 1;
                            //Provide a report for each pending paging message
                            Protocol__FlexPagingInfo **p_info;
                            p_info = malloc(sizeof(Protocol__FlexPagingInfo *) * paging_report->n_paging_info);
                            if (p_info == NULL)
                              goto error;

                            for (j = 0; j < paging_report->n_paging_info; j++) {

                                    p_info[j] = malloc(sizeof(Protocol__FlexPagingInfo));
                                    if(p_info[j] == NULL)
                                      goto error;
                                    protocol__flex_paging_info__init(p_info[j]);
                                    //TODO: Set paging index. This index is the same that will be used for the scheduling of the
                                    //paging message by the controller
                                    p_info[j]->paging_index = 10;
                                    p_info[j]->has_paging_index = 1;
                                    //TODO:Set the paging message size
                                    p_info[j]->paging_message_size = 100;
                                    p_info[j]->has_paging_message_size = 1;
                                    //TODO: Set the paging subframe
                                    p_info[j]->paging_subframe = 10;
                                    p_info[j]->has_paging_subframe = 1;
                                    //TODO: Set the carrier index for the pending paging message
                                    p_info[j]->carrier_index = 0;
                                    p_info[j]->has_carrier_index = 1;

                            }
                            //Add all paging info to the paging buffer rerport
                            paging_report->paging_info = p_info;
                            //Add the paging report to the UE report
                            ue_report[i]->pbr = paging_report;
                }

                  /* Check flag for creation of UL CQI report */
                if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) {

                      //Fill in the full UL CQI report of the UE
                      Protocol__FlexUlCqiReport *full_ul_report;
                      full_ul_report = malloc(sizeof(Protocol__FlexUlCqiReport));
                      if(full_ul_report == NULL)
                        goto error;
                      protocol__flex_ul_cqi_report__init(full_ul_report);
                      //TODO:Set the SFN and SF of the generated report
                      full_ul_report->sfn_sn = flexran_get_sfn_sf(enb_id);
                      full_ul_report->has_sfn_sn = 1;
                      //TODO:Set the number of UL measurement reports based on the types of measurements
                      //configured for this UE and on the servCellIndex
                      full_ul_report->n_cqi_meas = 1;
                      Protocol__FlexUlCqi **ul_report;
                      ul_report = malloc(sizeof(Protocol__FlexUlCqi *) * full_ul_report->n_cqi_meas);
                      if(ul_report == NULL)
                        goto error;
                      //Fill each UL report of the UE for each of the configured report types
                      for(j = 0; j < full_ul_report->n_cqi_meas; j++) {

                              ul_report[j] = malloc(sizeof(Protocol__FlexUlCqi));
                              if(ul_report[j] == NULL)
                              goto error;
                              protocol__flex_ul_cqi__init(ul_report[j]);
                              //TODO: Set the type of the UL report. As an example set it to SRS UL report
                              // See enum flex_ul_cqi_type in FlexRAN specification for more details
                              ul_report[j]->type = PROTOCOL__FLEX_UL_CQI_TYPE__FLUCT_SRS;
                              ul_report[j]->has_type = 1;
                              //TODO:Set the number of SINR measurements based on the report type
                              //See struct flex_ul_cqi in FlexRAN specification for more details
                              ul_report[j]->n_sinr = 0;
                              uint32_t *sinr_meas;
                              sinr_meas = (uint32_t *) malloc(sizeof(uint32_t) * ul_report[j]->n_sinr);
                              if (sinr_meas == NULL)
                                goto error;
                              //TODO:Set the SINR measurements for the specified type
                              for (k = 0; k < ul_report[j]->n_sinr; k++) {
                                      sinr_meas[k] = 10;
                              }
                              ul_report[j]->sinr = sinr_meas;
                              //TODO: Set the servCellIndex for this report
                              ul_report[j]->serv_cell_index = 0;
                              ul_report[j]->has_serv_cell_index = 1;
Cedric Roux's avatar
Cedric Roux committed
463

464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
                              //Set the list of UL reports of this UE to the full UL report
                              full_ul_report->cqi_meas = ul_report;

                              full_ul_report->n_pucch_dbm = MAX_NUM_CCs;
                              full_ul_report->pucch_dbm = malloc(sizeof(Protocol__FlexPucchDbm *) * full_ul_report->n_pucch_dbm);

                              for (j = 0; j < MAX_NUM_CCs; j++) {

                                      full_ul_report->pucch_dbm[j] = malloc(sizeof(Protocol__FlexPucchDbm));
                                      protocol__flex_pucch_dbm__init(full_ul_report->pucch_dbm[j]);
                                      full_ul_report->pucch_dbm[j]->has_serv_cell_index = 1;
                                      full_ul_report->pucch_dbm[j]->serv_cell_index = j;

                                      if(flexran_get_p0_pucch_dbm(enb_id,i, j) != -1){
                                        full_ul_report->pucch_dbm[j]->p0_pucch_dbm = flexran_get_p0_pucch_dbm(enb_id,i,j);
                                        full_ul_report->pucch_dbm[j]->has_p0_pucch_dbm = 1;
                                      }
                              }


                          }
                        //  Add full UL CQI report to the UE report
                        ue_report[i]->ul_cqi_report = full_ul_report;

Cedric Roux's avatar
Cedric Roux committed
488 489

                     }
490 491 492 493 494 495 496
                      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_STATS) {

                            Protocol__FlexMacStats *macstats;
                            macstats = malloc(sizeof(Protocol__FlexMacStats));
                            if (macstats == NULL)
                              goto error;
                            protocol__flex_mac_stats__init(macstats);
Cedric Roux's avatar
Cedric Roux committed
497

498 499 500 501 502 503 504 505 506 507

                            macstats->total_bytes_sdus_dl = flexran_get_total_size_dl_mac_sdus(mod_id, i, cc_id);
                            macstats->has_total_bytes_sdus_dl = 1;

                            macstats->total_bytes_sdus_ul = flexran_get_total_size_ul_mac_sdus(mod_id, i, cc_id);
                            macstats->has_total_bytes_sdus_ul = 1;

                            macstats->tbs_dl = flexran_get_TBS_dl(mod_id, i, cc_id);
                            macstats->has_tbs_dl = 1;

Cedric Roux's avatar
Cedric Roux committed
508
                            macstats->tbs_ul = flexran_get_TBS_ul(mod_id, i, cc_id);
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
                            macstats->has_tbs_ul = 1;

                            macstats->prb_retx_dl = flexran_get_num_prb_retx_dl_per_ue(mod_id, i, cc_id);
                            macstats->has_prb_retx_dl = 1;

                            macstats->prb_retx_ul = flexran_get_num_prb_retx_ul_per_ue(mod_id, i, cc_id);
                            macstats->has_prb_retx_ul = 1;

                            macstats->prb_dl = flexran_get_num_prb_dl_tx_per_ue(mod_id, i, cc_id);
                            macstats->has_prb_dl = 1;

                            macstats->prb_ul = flexran_get_num_prb_ul_rx_per_ue(mod_id, i, cc_id);
                            macstats->has_prb_ul = 1;

                            macstats->mcs1_dl = flexran_get_mcs1_dl(mod_id, i, cc_id);
                            macstats->has_mcs1_dl = 1;

                            macstats->mcs2_dl = flexran_get_mcs2_dl(mod_id, i, cc_id);
                            macstats->has_mcs2_dl = 1;

                            macstats->mcs1_ul = flexran_get_mcs1_ul(mod_id, i, cc_id);
                            macstats->has_mcs1_ul = 1;

                            macstats->mcs2_ul = flexran_get_mcs2_ul(mod_id, i, cc_id);
                            macstats->has_mcs2_ul = 1;

                            macstats->total_prb_dl = flexran_get_total_prb_dl_tx_per_ue(mod_id, i, cc_id);
                            macstats->has_total_prb_dl = 1;

                            macstats->total_prb_ul = flexran_get_total_prb_ul_rx_per_ue(mod_id, i, cc_id);
                            macstats->has_total_prb_ul = 1;

                            macstats->total_pdu_dl = flexran_get_total_num_pdu_dl(mod_id, i, cc_id);
                            macstats->has_total_pdu_dl = 1;

                            macstats->total_pdu_ul = flexran_get_total_num_pdu_ul(mod_id, i, cc_id);
                            macstats->has_total_pdu_ul = 1;

                            macstats->total_tbs_dl = flexran_get_total_TBS_dl(mod_id, i, cc_id);
                            macstats->has_total_tbs_dl = 1;

                            macstats->total_tbs_ul = flexran_get_total_TBS_ul(mod_id, i, cc_id);
                            macstats->has_total_tbs_ul = 1;

                            macstats->harq_round = flexran_get_harq_round(mod_id, cc_id, i);
                            macstats->has_harq_round = 1;

Cedric Roux's avatar
Cedric Roux committed
556
                            Protocol__FlexMacSdusDl ** mac_sdus;
557 558 559 560
                            mac_sdus = malloc(sizeof(Protocol__FlexMacSdusDl) * flexran_get_num_mac_sdu_tx(mod_id, i, cc_id));
                            if (mac_sdus == NULL)
                                goto error;

Cedric Roux's avatar
Cedric Roux committed
561 562
                            macstats->n_mac_sdus_dl = flexran_get_num_mac_sdu_tx(mod_id, i, cc_id);

563 564
                            for (j = 0; j < macstats->n_mac_sdus_dl; j++){

Cedric Roux's avatar
Cedric Roux committed
565

566 567 568 569 570 571 572 573 574 575 576 577 578
                                mac_sdus[j] = malloc(sizeof(Protocol__FlexMacSdusDl));
                                protocol__flex_mac_sdus_dl__init(mac_sdus[j]);

                                mac_sdus[j]->lcid = flexran_get_mac_sdu_lcid_index(mod_id, i, cc_id, j);
                                mac_sdus[j]->has_lcid = 1;

                                mac_sdus[j]->sdu_length = flexran_get_mac_sdu_size(mod_id, i, cc_id, mac_sdus[j]->lcid);
                                mac_sdus[j]->has_sdu_length = 1;


                            }


Cedric Roux's avatar
Cedric Roux committed
579 580 581 582 583 584 585 586 587
                            macstats->mac_sdus_dl = mac_sdus;


                        ue_report[i]->mac_stats = macstats;

               }



588

Cedric Roux's avatar
Cedric Roux committed
589
             }
590 591


Cedric Roux's avatar
Cedric Roux committed
592 593 594


     }
595 596 597

  /* Allocate memory for list of cell reports */
  if (report_config->nr_cc > 0) {
Cedric Roux's avatar
Cedric Roux committed
598 599


600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
            // Fill in the Cell reports
            for (i = 0; i < report_config->nr_cc; i++) {


                      /* Check flag for creation of noise and interference report */
                      if(report_config->cc_report_type[i].cc_report_flags & PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE) {
                            // TODO: Fill in the actual noise and interference report for this cell
                            Protocol__FlexNoiseInterferenceReport *ni_report;
                            ni_report = malloc(sizeof(Protocol__FlexNoiseInterferenceReport));
                            if(ni_report == NULL)
                              goto error;
                            protocol__flex_noise_interference_report__init(ni_report);
                            // Current frame and subframe number
                            ni_report->sfn_sf = flexran_get_sfn_sf(enb_id);
                            ni_report->has_sfn_sf = 1;
                            //TODO:Received interference power in dbm
                            ni_report->rip = 0;
                            ni_report->has_rip = 1;
                            //TODO:Thermal noise power in dbm
                            ni_report->tnp = 0;
                            ni_report->has_tnp = 1;

                            ni_report->p0_nominal_pucch = flexran_get_p0_nominal_pucch(enb_id, 0);
                            ni_report->has_p0_nominal_pucch = 1;
                            cell_report[i]->noise_inter_report = ni_report;
                      }
            }

Cedric Roux's avatar
Cedric Roux committed
628 629 630



631
  }
632

633
  return 0;
634

635
 error:
636 637 638 639 640 641

  if (cell_report != NULL)
        free(cell_report);
  if (ue_report != NULL)
        free(ue_report);

642 643 644
  return -1;
}

645
int flexran_agent_mac_destroy_stats_reply(Protocol__FlexranMessage *msg) {
646
  //TODO: Need to deallocate memory for the stats reply message
647
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG)
648 649 650
    goto error;
  free(msg->stats_reply_msg->header);
  int i, j, k;
651

652 653 654 655
  Protocol__FlexStatsReply *reply = msg->stats_reply_msg;
  Protocol__FlexDlCqiReport *dl_report;
  Protocol__FlexUlCqiReport *ul_report;
  Protocol__FlexPagingBufferReport *paging_report;
656 657 658 659 660 661 662 663 664

  // Free the memory for the UE reports
  for (i = 0; i < reply->n_ue_report; i++) {
    free(reply->ue_report[i]->bsr);
    for (j = 0; j < reply->ue_report[i]->n_rlc_report; j++) {
      free(reply->ue_report[i]->rlc_report[j]);
    }
    free(reply->ue_report[i]->rlc_report);
    // If DL CQI report flag was set
665
    if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) {
666 667 668 669 670
      dl_report = reply->ue_report[i]->dl_cqi_report;
      // Delete all CSI reports
      for (j = 0; j < dl_report->n_csi_report; j++) {
	//Must free memory based on the type of report
	switch(dl_report->csi_report[j]->report_case) {
671
	case PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI:
672 673
	  free(dl_report->csi_report[j]->p10csi);
	  break;
674
	case PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI:
675 676 677
	  free(dl_report->csi_report[j]->p11csi->wb_cqi);
	  free(dl_report->csi_report[j]->p11csi);
	  break;
678
	case PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI:
679 680
	  free(dl_report->csi_report[j]->p20csi);
	  break;
681
	case PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI:
682 683 684 685
	  free(dl_report->csi_report[j]->p21csi->wb_cqi);
	  free(dl_report->csi_report[j]->p21csi->sb_cqi);
	  free(dl_report->csi_report[j]->p21csi);
	  break;
686
	case PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI:
687 688 689 690
	  free(dl_report->csi_report[j]->a12csi->wb_cqi);
	  free(dl_report->csi_report[j]->a12csi->sb_pmi);
	  free(dl_report->csi_report[j]->a12csi);
	  break;
691
	case PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI:
692 693 694 695 696
	  free(dl_report->csi_report[j]->a22csi->wb_cqi);
	  free(dl_report->csi_report[j]->a22csi->sb_cqi);
	  free(dl_report->csi_report[j]->a22csi->sb_list);
	  free(dl_report->csi_report[j]->a22csi);
	  break;
697
	case PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI:
698 699 700
	  free(dl_report->csi_report[j]->a20csi->sb_list);
	  free(dl_report->csi_report[j]->a20csi);
	  break;
701
	case PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI:
702 703 704
	  free(dl_report->csi_report[j]->a30csi->sb_cqi);
	  free(dl_report->csi_report[j]->a30csi);
	  break;
705
	case PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI:
706 707 708 709 710 711
	  free(dl_report->csi_report[j]->a31csi->wb_cqi);
	  for (k = 0; k < dl_report->csi_report[j]->a31csi->n_sb_cqi; k++) {
	    free(dl_report->csi_report[j]->a31csi->sb_cqi[k]);
	  }
	  free(dl_report->csi_report[j]->a31csi->sb_cqi);
	  break;
712 713
	default:
	  break;
714 715
	}

716 717 718 719 720 721
	free(dl_report->csi_report[j]);
      }
      free(dl_report->csi_report);
      free(dl_report);
    }
    // If Paging buffer report flag was set
722
    if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) {
723 724 725 726 727 728 729 730 731
      paging_report = reply->ue_report[i]->pbr;
      // Delete all paging buffer reports
      for (j = 0; j < paging_report->n_paging_info; j++) {
	free(paging_report->paging_info[j]);
      }
      free(paging_report->paging_info);
      free(paging_report);
    }
    // If UL CQI report flag was set
732
    if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) {
733 734 735 736 737 738
      ul_report = reply->ue_report[i]->ul_cqi_report;
      for (j = 0; j < ul_report->n_cqi_meas; j++) {
	free(ul_report->cqi_meas[j]->sinr);
	free(ul_report->cqi_meas[j]);
      }
      free(ul_report->cqi_meas);
739 740 741 742
      for (j = 0; j < ul_report->n_pucch_dbm; j++) {
	free(ul_report->pucch_dbm[j]);
      }
      free(ul_report->pucch_dbm);
743 744 745 746 747 748 749 750 751 752 753
    }
    free(reply->ue_report[i]);
  }
  free(reply->ue_report);

  // Free memory for all Cell reports
  for (i = 0; i < reply->n_cell_report; i++) {
    free(reply->cell_report[i]->noise_inter_report);
    free(reply->cell_report[i]);
  }
  free(reply->cell_report);
754

755 756 757
  free(reply);
  free(msg);
  return 0;
758

759 760 761 762
 error:
  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
  return -1;
}
763

764
int flexran_agent_mac_sr_info(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
765
  Protocol__FlexHeader *header = NULL;
766 767 768
  int i;
  const int xid = *((int *)params);

769 770
  Protocol__FlexUlSrInfo *ul_sr_info_msg;
  ul_sr_info_msg = malloc(sizeof(Protocol__FlexUlSrInfo));
771 772 773
  if (ul_sr_info_msg == NULL) {
    goto error;
  }
774
  protocol__flex_ul_sr_info__init(ul_sr_info_msg);
775

776 777 778
  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_UL_SR_INFO, &header) != 0)
    goto error;

779 780
  ul_sr_info_msg->header = header;
  ul_sr_info_msg->has_sfn_sf = 1;
781
  ul_sr_info_msg->sfn_sf = flexran_get_sfn_sf(mod_id);
782 783 784 785 786 787 788 789 790 791 792
  /*TODO: Set the number of UEs that sent an SR */
  ul_sr_info_msg->n_rnti = 1;
  ul_sr_info_msg->rnti = (uint32_t *) malloc(ul_sr_info_msg->n_rnti * sizeof(uint32_t));

  if(ul_sr_info_msg->rnti == NULL) {
    goto error;
  }
  /*TODO:Set the rnti of the UEs that sent an SR */
  for (i = 0; i < ul_sr_info_msg->n_rnti; i++) {
    ul_sr_info_msg->rnti[i] = 1;
  }
793

794
  *msg = malloc(sizeof(Protocol__FlexranMessage));
795 796
  if(*msg == NULL)
    goto error;
797 798 799
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG;
  (*msg)->msg_dir =  PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
800 801
  (*msg)->ul_sr_info_msg = ul_sr_info_msg;
  return 0;
802

803 804 805 806 807 808 809 810 811 812 813 814 815 816
 error:
  // TODO: Need to make proper error handling
  if (header != NULL)
    free(header);
  if (ul_sr_info_msg != NULL) {
    free(ul_sr_info_msg->rnti);
    free(ul_sr_info_msg);
  }
  if(*msg != NULL)
    free(*msg);
  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
  return -1;
}

817
int flexran_agent_mac_destroy_sr_info(Protocol__FlexranMessage *msg) {
818
   if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG)
819 820 821 822 823 824 825 826 827 828 829 830 831
     goto error;

   free(msg->ul_sr_info_msg->header);
   free(msg->ul_sr_info_msg->rnti);
   free(msg->ul_sr_info_msg);
   free(msg);
   return 0;

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

832
int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
833
  Protocol__FlexHeader *header = NULL;
834
  int i, j, UE_id;
Cedric Roux's avatar
Cedric Roux committed
835

836
  int available_harq[MAX_MOBILES_PER_ENB];
Cedric Roux's avatar
Cedric Roux committed
837

838 839
  const int xid = *((int *)params);

840

841 842
  Protocol__FlexSfTrigger *sf_trigger_msg;
  sf_trigger_msg = malloc(sizeof(Protocol__FlexSfTrigger));
843
  if (sf_trigger_msg == NULL) {
844 845
    goto error;
  }
846
  protocol__flex_sf_trigger__init(sf_trigger_msg);
847

848 849 850
  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_SF_TRIGGER, &header) != 0)
    goto error;

851 852 853
  frame_t frame;
  sub_frame_t subframe;

854
  for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
855 856 857 858
    available_harq[i] = -1;
  }

  int ahead_of_time = 0;
Cedric Roux's avatar
Cedric Roux committed
859

860 861
  frame = (frame_t) flexran_get_current_system_frame_num(mod_id);
  subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
862 863

  subframe = ((subframe + ahead_of_time) % 10);
Cedric Roux's avatar
Cedric Roux committed
864

865
  if (subframe < flexran_get_current_subframe(mod_id)) {
866
    frame = (frame + 1) % 1024;
867 868
  }

869 870 871
  int additional_frames = ahead_of_time / 10;
  frame = (frame + additional_frames) % 1024;

872 873
  sf_trigger_msg->header = header;
  sf_trigger_msg->has_sfn_sf = 1;
874
  sf_trigger_msg->sfn_sf = flexran_get_future_sfn_sf(mod_id, 3);
875

876 877
  sf_trigger_msg->n_dl_info = 0;

878
  for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
879
    for (j = 0; j < 8; j++) {
880
      if (RC.mac && RC.mac[mod_id] && RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid == 1) {
881 882 883 884 885 886
	available_harq[i] = j;
	sf_trigger_msg->n_dl_info++;
	break;
      }
    }
  }
Cedric Roux's avatar
Cedric Roux committed
887

888 889 890

  //  LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10);

891 892 893
  /*TODO: Fill in the number of dl HARQ related info, based on the number of currently
   *transmitting UEs
   */
894
  //  sf_trigger_msg->n_dl_info = flexran_get_num_ues(mod_id);
895

896
  Protocol__FlexDlInfo **dl_info = NULL;
897

898
  if (sf_trigger_msg->n_dl_info > 0) {
899
    dl_info = malloc(sizeof(Protocol__FlexDlInfo *) * sf_trigger_msg->n_dl_info);
900 901
    if(dl_info == NULL)
      goto error;
902
    i = -1;
903
    //Fill the status of the current HARQ process for each UE
904
    for(UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
905 906 907 908 909
      if (available_harq[UE_id] < 0) {
	continue;
      } else {
	i++;
      }
910
      dl_info[i] = malloc(sizeof(Protocol__FlexDlInfo));
911 912
      if(dl_info[i] == NULL)
	goto error;
913
      protocol__flex_dl_info__init(dl_info[i]);
914
      dl_info[i]->rnti = flexran_get_ue_crnti(mod_id, UE_id);
915
      dl_info[i]->has_rnti = 1;
916
      /*Fill in the right id of this round's HARQ process for this UE*/
917 918 919
      //      uint8_t harq_id;
      //uint8_t harq_status;
      //      flexran_get_harq(mod_id, UE_PCCID(mod_id,i), i, frame, subframe, &harq_id, &harq_status);
Cedric Roux's avatar
Cedric Roux committed
920 921


922
      dl_info[i]->harq_process_id = available_harq[UE_id];
923 924
      if (RC.mac && RC.mac[mod_id])
        RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id,i)][UE_id].harq_pid = 0;
925
      dl_info[i]->has_harq_process_id = 1;
926
      /* Fill in the status of the HARQ process (2 TBs)*/
927 928
      dl_info[i]->n_harq_status = 2;
      dl_info[i]->harq_status = malloc(sizeof(uint32_t) * dl_info[i]->n_harq_status);
929
      for (j = 0; j < dl_info[i]->n_harq_status; j++) {
930 931
        dl_info[i]->harq_status[j] = RC.mac[mod_id]->UE_list.UE_sched_ctrl[i].round[UE_PCCID(mod_id,i)][j];
        // TODO: This should be different per TB
932 933 934 935
      }
      //      LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d and harq %d (round %d)\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10, dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]);
      if(dl_info[i]->harq_status[0] > 0) {
	//	LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d]Need to make a retransmission for harq %d (round %d)\n", flexran_get_current_frame(mod_id), flexran_get_current_subframe(mod_id), dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]);
936
      }
937
      /*Fill in the serving cell index for this UE */
MKassem's avatar
MKassem committed
938
      dl_info[i]->serv_cell_index = UE_PCCID(mod_id,i);
939 940 941
      dl_info[i]->has_serv_cell_index = 1;
    }
  }
942

943
  sf_trigger_msg->dl_info = dl_info;
944

945 946
  /* Fill in the number of UL reception status related info, based on the number of currently
   * transmitting UEs
947
   */
948
  sf_trigger_msg->n_ul_info = flexran_get_num_ues(mod_id);
949

950
  Protocol__FlexUlInfo **ul_info = NULL;
951

952
  if (sf_trigger_msg->n_ul_info > 0) {
953
    ul_info = malloc(sizeof(Protocol__FlexUlInfo *) * sf_trigger_msg->n_ul_info);
954 955 956
    if(ul_info == NULL)
      goto error;
    //Fill the reception info for each transmitting UE
957
    for(i = 0; i < sf_trigger_msg->n_ul_info; i++) {
958
      ul_info[i] = malloc(sizeof(Protocol__FlexUlInfo));
959 960
      if(ul_info[i] == NULL)
	goto error;
961
      protocol__flex_ul_info__init(ul_info[i]);
962
      ul_info[i]->rnti = flexran_get_ue_crnti(mod_id, i);
963
      ul_info[i]->has_rnti = 1;
Robert Schmidt's avatar
Robert Schmidt committed
964 965 966 967 968
      /* Fill in the Tx power control command for this UE (if available),
       * primary carrier */
      if(flexran_get_tpc(mod_id, i, 0) != 1){
          /* assume primary carrier */
          ul_info[i]->tpc = flexran_get_tpc(mod_id, i, 0);
MKassem's avatar
MKassem committed
969 970 971
          ul_info[i]->has_tpc = 1;
      }
      else{
Robert Schmidt's avatar
Robert Schmidt committed
972 973
          /* assume primary carrier */
          ul_info[i]->tpc = flexran_get_tpc(mod_id, i, 0);
MKassem's avatar
MKassem committed
974 975
    	  ul_info[i]->has_tpc = 0;
      }
976
      /*TODO: fill in the amount of data in bytes in the MAC SDU received in this subframe for the
977
	given logical channel*/
978
      ul_info[i]->n_ul_reception = 0;
979
      ul_info[i]->ul_reception = malloc(sizeof(uint32_t) * ul_info[i]->n_ul_reception);
980
      for (j = 0; j < ul_info[i]->n_ul_reception; j++) {
981 982 983
	ul_info[i]->ul_reception[j] = 100;
      }
      /*TODO: Fill in the reception status for each UEs data*/
984
      ul_info[i]->reception_status = PROTOCOL__FLEX_RECEPTION_STATUS__FLRS_OK;
985
      ul_info[i]->has_reception_status = 1;
986
      /*Fill in the serving cell index for this UE */
MKassem's avatar
MKassem committed
987
      ul_info[i]->serv_cell_index = UE_PCCID(mod_id,i);
988 989 990
      ul_info[i]->has_serv_cell_index = 1;
    }
  }
991

992 993
  sf_trigger_msg->ul_info = ul_info;

994
  *msg = malloc(sizeof(Protocol__FlexranMessage));
995 996
  if(*msg == NULL)
    goto error;
997 998 999
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG;
  (*msg)->msg_dir =  PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
1000
  (*msg)->sf_trigger_msg = sf_trigger_msg;
1001
  return 0;
1002

1003 1004 1005
 error:
  if (header != NULL)
    free(header);
1006 1007 1008 1009
  if (sf_trigger_msg != NULL) {
    for (i = 0; i < sf_trigger_msg->n_dl_info; i++) {
      free(sf_trigger_msg->dl_info[i]->harq_status);
    }
Cedric Roux's avatar
Cedric Roux committed
1010
    free(sf_trigger_msg->dl_info);
1011 1012
    free(sf_trigger_msg->ul_info);
    free(sf_trigger_msg);
1013 1014 1015 1016 1017 1018 1019
  }
  if(*msg != NULL)
    free(*msg);
  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
  return -1;
}

1020
int flexran_agent_mac_destroy_sf_trigger(Protocol__FlexranMessage *msg) {
1021
  int i;
1022
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG)
1023
    goto error;
1024

1025 1026 1027
  free(msg->sf_trigger_msg->header);
  for (i = 0; i < msg->sf_trigger_msg->n_dl_info; i++) {
    free(msg->sf_trigger_msg->dl_info[i]->harq_status);
1028
    free(msg->sf_trigger_msg->dl_info[i]);
1029
  }
1030 1031
  free(msg->sf_trigger_msg->dl_info);
  for (i = 0; i < msg->sf_trigger_msg->n_ul_info; i++) {
1032 1033
    free(msg->sf_trigger_msg->ul_info[i]->ul_reception);
    free(msg->sf_trigger_msg->ul_info[i]);
1034 1035 1036
  }
  free(msg->sf_trigger_msg->ul_info);
  free(msg->sf_trigger_msg);
1037
  free(msg);
1038

1039 1040 1041 1042 1043 1044 1045
  return 0;

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

1046
int flexran_agent_mac_create_empty_dl_config(mid_t mod_id, Protocol__FlexranMessage **msg) {
1047 1048

  int xid = 0;
1049
  Protocol__FlexHeader *header = NULL;
1050
  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_DL_MAC_CONFIG, &header) != 0)
1051 1052
    goto error;

1053 1054
  Protocol__FlexDlMacConfig *dl_mac_config_msg;
  dl_mac_config_msg = malloc(sizeof(Protocol__FlexDlMacConfig));
1055 1056 1057
  if (dl_mac_config_msg == NULL) {
    goto error;
  }
1058
  protocol__flex_dl_mac_config__init(dl_mac_config_msg);
1059

1060 1061
  dl_mac_config_msg->header = header;
  dl_mac_config_msg->has_sfn_sf = 1;
1062
  dl_mac_config_msg->sfn_sf = flexran_get_sfn_sf(mod_id);
1063

1064
  *msg = malloc(sizeof(Protocol__FlexranMessage));
1065 1066
  if(*msg == NULL)
    goto error;
1067 1068 1069
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG;
  (*msg)->msg_dir =  PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
1070 1071 1072 1073 1074 1075 1076 1077
  (*msg)->dl_mac_config_msg = dl_mac_config_msg;

  return 0;

 error:
  return -1;
}

1078
int flexran_agent_mac_destroy_dl_config(Protocol__FlexranMessage *msg) {
1079
  int i,j, k;
1080
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG)
1081 1082
    goto error;

1083
  Protocol__FlexDlDci *dl_dci;
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104

  free(msg->dl_mac_config_msg->header);
  for (i = 0; i < msg->dl_mac_config_msg->n_dl_ue_data; i++) {
    free(msg->dl_mac_config_msg->dl_ue_data[i]->ce_bitmap);
    for (j = 0; j < msg->dl_mac_config_msg->dl_ue_data[i]->n_rlc_pdu; j++) {
      for (k = 0; k <  msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->n_rlc_pdu_tb; k++) {
	free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb[k]);
      }
      free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb);
      free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]);
    }
    free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu);
    dl_dci = msg->dl_mac_config_msg->dl_ue_data[i]->dl_dci;
    free(dl_dci->tbs_size);
    free(dl_dci->mcs);
    free(dl_dci->ndi);
    free(dl_dci->rv);
    free(dl_dci);
    free(msg->dl_mac_config_msg->dl_ue_data[i]);
  }
  free(msg->dl_mac_config_msg->dl_ue_data);
1105

1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
  for (i = 0; i <  msg->dl_mac_config_msg->n_dl_rar; i++) {
    dl_dci = msg->dl_mac_config_msg->dl_rar[i]->rar_dci;
    free(dl_dci->tbs_size);
    free(dl_dci->mcs);
    free(dl_dci->ndi);
    free(dl_dci->rv);
    free(dl_dci);
    free(msg->dl_mac_config_msg->dl_rar[i]);
  }
  free(msg->dl_mac_config_msg->dl_rar);

  for (i = 0; i < msg->dl_mac_config_msg->n_dl_broadcast; i++) {
    dl_dci = msg->dl_mac_config_msg->dl_broadcast[i]->broad_dci;
    free(dl_dci->tbs_size);
    free(dl_dci->mcs);
    free(dl_dci->ndi);
    free(dl_dci->rv);
    free(dl_dci);
    free(msg->dl_mac_config_msg->dl_broadcast[i]);
  }
  free(msg->dl_mac_config_msg->dl_broadcast);

    for ( i = 0; i < msg->dl_mac_config_msg->n_ofdm_sym; i++) {
    free(msg->dl_mac_config_msg->ofdm_sym[i]);
  }
  free(msg->dl_mac_config_msg->ofdm_sym);
1132 1133
  free(msg->dl_mac_config_msg);
  free(msg);
1134 1135 1136 1137

  return 0;

 error:
1138 1139 1140
  return -1;
}

shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
1141 1142 1143
int flexran_agent_mac_create_empty_ul_config(mid_t mod_id, Protocol__FlexranMessage **msg) {

  int xid = 0;
1144
  Protocol__FlexHeader *header = NULL;
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_UL_MAC_CONFIG, &header) != 0)
    goto error;

  Protocol__FlexUlMacConfig *ul_mac_config_msg;
  ul_mac_config_msg = malloc(sizeof(Protocol__FlexUlMacConfig));
  if (ul_mac_config_msg == NULL) {
    goto error;
  }
  protocol__flex_ul_mac_config__init(ul_mac_config_msg);

  ul_mac_config_msg->header = header;
  ul_mac_config_msg->has_sfn_sf = 1;
  ul_mac_config_msg->sfn_sf = flexran_get_sfn_sf(mod_id);

  *msg = malloc(sizeof(Protocol__FlexranMessage));
  if(*msg == NULL)
    goto error;
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_MAC_CONFIG_MSG;
  (*msg)->msg_dir =  PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
  (*msg)->ul_mac_config_msg = ul_mac_config_msg;

  return 0;

 error:
  return -1;
}


shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
1174
int flexran_agent_mac_destroy_ul_config(Protocol__FlexranMessage *msg) {
shahab SHARIAT BAGHERI's avatar
shahab SHARIAT BAGHERI committed
1175
  int i; //,j, k;
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
1176 1177 1178
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_MAC_CONFIG_MSG)
    goto error;

shahab SHARIAT BAGHERI's avatar
shahab SHARIAT BAGHERI committed
1179
  // Protocol__FlexUlDci *ul_dci;
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
1180 1181 1182 1183

  free(msg->ul_mac_config_msg->header);
  for (i = 0; i < msg->ul_mac_config_msg->n_ul_ue_data; i++) {
    // TODO  uplink rlc ...
Cedric Roux's avatar
Cedric Roux committed
1184
    // free(msg->ul_mac_config_msg->dl_ue_data[i]->ce_bitmap);
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
1185 1186 1187 1188 1189 1190 1191 1192
  //   for (j = 0; j < msg->ul_mac_config_msg->ul_ue_data[i]->n_rlc_pdu; j++) {
  //     for (k = 0; k <  msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu[j]->n_rlc_pdu_tb; k++) {
  // free(msg->ul_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb[k]);
  //     }
  //     free(msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb);
  //     free(msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu[j]);
  //   }
    // free(msg->ul_mac_config_msg->ul_ue_data[i]->rlc_pdu);
shahab SHARIAT BAGHERI's avatar
shahab SHARIAT BAGHERI committed
1193
    // ul_dci = msg->ul_mac_config_msg->ul_ue_data[i]->ul_dci;
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
1194 1195 1196 1197 1198
    // free(dl_dci->tbs_size);
    // free(ul_dci->mcs);
    // free(ul_dci->ndi);
    // free(ul_dci->rv);
    // free(ul_dci);
shahab SHARIAT BAGHERI's avatar
shahab SHARIAT BAGHERI committed
1199
    // free(msg->ul_mac_config_msg->ul_ue_data[i]);
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
1200 1201
  }
  free(msg->ul_mac_config_msg->ul_ue_data);
Cedric Roux's avatar
Cedric Roux committed
1202

shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212
  free(msg->ul_mac_config_msg);
  free(msg);

  return 0;

 error:
  return -1;
}


1213
void flexran_agent_get_pending_dl_mac_config(mid_t mod_id, Protocol__FlexranMessage **msg) {
1214 1215

  struct lfds700_misc_prng_state ls;
Cedric Roux's avatar
Cedric Roux committed
1216

1217 1218
  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
  lfds700_misc_prng_init(&ls);
Cedric Roux's avatar
Cedric Roux committed
1219

1220 1221 1222 1223 1224
  if (lfds700_ringbuffer_read(&ringbuffer_state[mod_id], NULL, (void **) msg, &ls) == 0) {
    *msg = NULL;
  }
}

1225
int flexran_agent_mac_handle_dl_mac_config(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
1226 1227 1228

  struct lfds700_misc_prng_state ls;
  enum lfds700_misc_flag overwrite_occurred_flag;
1229
  Protocol__FlexranMessage *overwritten_dl_config;
Cedric Roux's avatar
Cedric Roux committed
1230

1231 1232
  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
  lfds700_misc_prng_init(&ls);
Cedric Roux's avatar
Cedric Roux committed
1233

1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
  lfds700_ringbuffer_write( &ringbuffer_state[mod_id],
			    NULL,
			    (void *) params,
			    &overwrite_occurred_flag,
			    NULL,
			    (void **)&overwritten_dl_config,
			    &ls);

  if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) {
    // Delete unmanaged dl_config
1244
    flexran_agent_mac_destroy_dl_config(overwritten_dl_config);
1245 1246 1247 1248
  }
  *msg = NULL;
  return 2;

1249 1250 1251
  // error:
  //*msg = NULL;
  //return -1;
1252 1253
}

1254
void flexran_agent_init_mac_agent(mid_t mod_id) {
1255
  int i, j;
1256 1257 1258 1259 1260 1261
  lfds700_misc_library_init_valid_on_current_logical_core();
  lfds700_misc_prng_init(&ps[mod_id]);
  int num_elements = RINGBUFFER_SIZE + 1;
  //Allow RINGBUFFER_SIZE messages to be stored in the ringbuffer at any time
  dl_mac_config_array[mod_id] = malloc( sizeof(struct lfds700_ringbuffer_element) *  num_elements);
  lfds700_ringbuffer_init_valid_on_current_logical_core( &ringbuffer_state[mod_id], dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL );
1262
  for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
1263
    for (j = 0; j < 8; j++) {
1264 1265
      if (RC.mac && RC.mac[mod_id])
        RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid = 0;
1266 1267
    }
  }
1268 1269
}

1270
/***********************************************
1271
 * FlexRAN agent - technology mac API implementation
1272 1273
 ***********************************************/

1274
void flexran_agent_send_sr_info(mid_t mod_id) {
1275
  int size;
1276
  Protocol__FlexranMessage *msg;
1277
  void *data;
1278
  int priority = 0;
1279 1280
  err_code_t err_code;

1281 1282
  int xid = 0;

1283
  /*TODO: Must use a proper xid*/
1284
  err_code = flexran_agent_mac_sr_info(mod_id, (void *) &xid, &msg);
1285 1286 1287 1288 1289
  if (err_code < 0) {
    goto error;
  }

  if (msg != NULL){
1290
    data=flexran_agent_pack_message(msg, &size);
1291
    /*Send sr info using the MAC channel of the eNB*/
1292
    if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_MAC, data, size, priority)) {
1293
      err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
1294 1295
      goto error;
    }
1296

1297
    LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
1298
    return;
1299 1300
  }
 error:
1301
  LOG_D(FLEXRAN_AGENT, "Could not send sr message\n");
1302 1303
}

1304
void flexran_agent_send_sf_trigger(mid_t mod_id) {
1305
  int size;
1306
  Protocol__FlexranMessage *msg;
1307
  void *data;
1308
  int priority = 0;
1309 1310
  err_code_t err_code;

1311
  int xid = 0;
1312

1313
  /*TODO: Must use a proper xid*/
1314
  err_code = flexran_agent_mac_sf_trigger(mod_id, (void *) &xid, &msg);
1315 1316 1317 1318 1319
  if (err_code < 0) {
    goto error;
  }

  if (msg != NULL){
1320
    data=flexran_agent_pack_message(msg, &size);
1321
    /*Send sr info using the MAC channel of the eNB*/
1322
    if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_MAC, data, size, priority)) {
1323
      err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
1324 1325 1326
      goto error;
    }

1327
    LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
1328 1329 1330
    return;
  }
 error:
1331
  LOG_D(FLEXRAN_AGENT, "Could not send sf trigger message\n");
1332 1333
}

1334 1335


1336 1337 1338
int flexran_agent_register_mac_xface(mid_t mod_id)
{
  if (agent_mac_xface[mod_id]) {
1339 1340 1341
    LOG_E(MAC, "MAC agent for eNB %d is already registered\n", mod_id);
    return -1;
  }
1342 1343 1344 1345 1346
  AGENT_MAC_xface *xface = malloc(sizeof(AGENT_MAC_xface));
  if (!xface) {
    LOG_E(FLEXRAN_AGENT, "could not allocate memory for MAC agent xface %d\n", mod_id);
    return -1;
  }
1347

1348
  //xface->agent_ctxt = &shared_ctxt[mod_id];
1349 1350
  xface->flexran_agent_send_sr_info = flexran_agent_send_sr_info;
  xface->flexran_agent_send_sf_trigger = flexran_agent_send_sf_trigger;
1351
  //xface->flexran_agent_send_update_mac_stats = flexran_agent_send_update_mac_stats;
1352
  xface->flexran_agent_get_pending_dl_mac_config = flexran_agent_get_pending_dl_mac_config;
Cedric Roux's avatar
Cedric Roux committed
1353

1354
  xface->dl_scheduler_loaded_lib = NULL;
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
1355
  xface->ul_scheduler_loaded_lib = NULL;
1356
  agent_mac_xface[mod_id] = xface;
1357 1358

  return 0;
1359 1360
}

1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374
void flexran_agent_fill_mac_cell_config(mid_t mod_id, uint8_t cc_id,
    Protocol__FlexCellConfig *conf) {
  if (!conf->si_config) {
    conf->si_config = malloc(sizeof(Protocol__FlexSiConfig));
    if (conf->si_config)
      protocol__flex_si_config__init(conf->si_config);
  }

  if (conf->si_config) {
    conf->si_config->sfn = flexran_get_current_system_frame_num(mod_id);
    conf->si_config->has_sfn = 1;
  }
}

1375 1376 1377 1378 1379 1380 1381
int flexran_agent_unregister_mac_xface(mid_t mod_id)
{
  if (!agent_mac_xface[mod_id]) {
    LOG_E(FLEXRAN_AGENT, "MAC agent CM for eNB %d is not registered\n", mod_id);
    return -1;
  }
  AGENT_MAC_xface *xface = agent_mac_xface[mod_id];
1382
  //xface->agent_ctxt = NULL;
1383 1384
  xface->flexran_agent_send_sr_info = NULL;
  xface->flexran_agent_send_sf_trigger = NULL;
1385
  //xface->flexran_agent_send_update_mac_stats = NULL;
1386
  xface->flexran_agent_get_pending_dl_mac_config = NULL;
1387

1388
  xface->dl_scheduler_loaded_lib = NULL;
shahab SHARIATBAGHERI's avatar
shahab SHARIATBAGHERI committed
1389
  xface->ul_scheduler_loaded_lib = NULL;
1390
  free(xface);
1391
  agent_mac_xface[mod_id] = NULL;
1392

1393 1394 1395
  return 0;
}

1396 1397 1398 1399
AGENT_MAC_xface *flexran_agent_get_mac_xface(mid_t mod_id)
{
  return agent_mac_xface[mod_id];
}