flexran_agent_mac.c 53.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */ 
nikaeinn's avatar
nikaeinn committed
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
nikaeinn's avatar
nikaeinn committed
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

35
#include "LAYER2/MAC/proto.h"
36
37
#include "LAYER2/MAC/flexran_agent_mac_proto.h"
#include "LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h"
38

39
40
#include "liblfds700.h"

nikaeinn's avatar
nikaeinn committed
41
42
#include "log.h"

43
44
45
46

/*Flags showing if a mac agent has already been registered*/
unsigned int mac_agent_registered[NUM_MAX_ENB];

47
48
49
/*Array containing the Agent-MAC interfaces*/
AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];

50
51
52
53
54
55
56
/* 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];


57
int flexran_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg){
58

59
60
  // TODO: Must deal with sanitization of input
  // TODO: Must check if RNTIs and cell ids of the request actually exist
61
  // TODO: Must resolve conflicts among stats requests
62

63
  int i;
nikaeinn's avatar
nikaeinn committed
64
  err_code_t err_code;
65
  xid_t xid;
66
  uint32_t usec_interval, sec_interval;
67
68

  //TODO: We do not deal with multiple CCs at the moment and eNB id is 0
69
  int enb_id = mod_id;
nikaeinn's avatar
nikaeinn committed
70

71
72
  //eNB_MAC_INST *eNB = &eNB_mac_inst[enb_id];
  //UE_list_t *eNB_UE_list=  &eNB->UE_list;
73

nikaeinn's avatar
nikaeinn committed
74
75
76
77
78
  report_config_t report_config;

  uint32_t ue_flags = 0;
  uint32_t c_flags = 0;

79
  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
80

81
  Protocol__FlexStatsRequest *stats_req = input->stats_request_msg;
82
  xid = (stats_req->header)->xid;
83
84
85

  // Check the type of request that is made
  switch(stats_req->body_case) {
86
87
88
  case PROTOCOL__FLEX_STATS_REQUEST__BODY_COMPLETE_STATS_REQUEST: ;
    Protocol__FlexCompleteStatsRequest *comp_req = stats_req->complete_stats_request;
    if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_OFF) {
89
      /*Disable both periodic and continuous updates*/
90
91
      flexran_agent_disable_cont_mac_stats_update(mod_id);
      flexran_agent_destroy_timer_by_task_id(xid);
92
93
      *msg = NULL;
      return 0;
94
    } else { //One-off, periodical or continuous reporting
95
96
97
98
      //Set the proper flags
      ue_flags = comp_req->ue_report_flags;
      c_flags = comp_req->cell_report_flags;
      //Create a list of all eNB RNTIs and cells
99

100
      //Set the number of UEs and create list with their RNTIs stats configs
101
      report_config.nr_ue = flexran_get_num_ues(mod_id); //eNB_UE_list->num_UEs
102
103
104
105
106
107
108
      report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t) * report_config.nr_ue);
      if (report_config.ue_report_type == NULL) {
	// TODO: Add appropriate error code
	err_code = -100;
	goto error;
      }
      for (i = 0; i < report_config.nr_ue; i++) {
109
	report_config.ue_report_type[i].ue_rnti = flexran_get_ue_crnti(enb_id, i); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].crnti;
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
	report_config.ue_report_type[i].ue_report_flags = ue_flags;
      }
      //Set the number of CCs and create a list with the cell stats configs
      report_config.nr_cc = MAX_NUM_CCs;
      report_config.cc_report_type = (cc_report_type_t *) malloc(sizeof(cc_report_type_t) * report_config.nr_cc);
      if (report_config.cc_report_type == NULL) {
	// TODO: Add appropriate error code
	err_code = -100;
	goto error;
      }
      for (i = 0; i < report_config.nr_cc; i++) {
	//TODO: Must fill in the proper cell ids
	report_config.cc_report_type[i].cc_id = i;
	report_config.cc_report_type[i].cc_report_flags = c_flags;
      }
125
      /* Check if request was periodical */
126
127
128
      if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_PERIODICAL) {
	/* Create a one off flexran message as an argument for the periodical task */
	Protocol__FlexranMessage *timer_msg;
129
	stats_request_config_t request_config;
130
131
	request_config.report_type = PROTOCOL__FLEX_STATS_TYPE__FLST_COMPLETE_STATS;
	request_config.report_frequency = PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_ONCE;
132
	request_config.period = 0;
133
134
135
136
137
138
139
140
141
142
143
144
	/* Need to make sure that the ue flags are saved (Bug) */
	if (report_config.nr_ue == 0) {
	  report_config.nr_ue = 1;
	  report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t));
	   if (report_config.ue_report_type == NULL) {
	     // TODO: Add appropriate error code
	     err_code = -100;
	     goto error;
	   }
	   report_config.ue_report_type[0].ue_rnti = 0; // Dummy value
	   report_config.ue_report_type[0].ue_report_flags = ue_flags;
	}
145
	request_config.config = &report_config;
146
	flexran_agent_mac_stats_request(enb_id, xid, &request_config, &timer_msg);
147
148
	/* Create a timer */
	long timer_id = 0;
149
150
151
	flexran_agent_timer_args_t *timer_args;
	timer_args = malloc(sizeof(flexran_agent_timer_args_t));
	memset (timer_args, 0, sizeof(flexran_agent_timer_args_t));
152
	timer_args->mod_id = enb_id;
153
154
155
156
157
158
159
160
161
	timer_args->msg = timer_msg;
	/*Convert subframes to usec time*/
	usec_interval = 1000*comp_req->sf;
	sec_interval = 0;
	/*add seconds if required*/
	if (usec_interval >= 1000*1000) {
	  sec_interval = usec_interval/(1000*1000);
	  usec_interval = usec_interval%(1000*1000);
	}
162
	flexran_agent_create_timer(sec_interval, usec_interval, FLEXRAN_AGENT_DEFAULT, enb_id, FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, xid, flexran_agent_handle_timed_task,(void*) timer_args, &timer_id);
163
      } else if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_CONTINUOUS) {
164
165
	/*If request was for continuous updates, disable the previous configuration and
	  set up a new one*/
166
	flexran_agent_disable_cont_mac_stats_update(mod_id);
167
	stats_request_config_t request_config;
168
169
	request_config.report_type = PROTOCOL__FLEX_STATS_TYPE__FLST_COMPLETE_STATS;
	request_config.report_frequency = PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_ONCE;
170
	request_config.period = 0;
171
172
173
174
175
176
177
178
179
180
181
182
	/* Need to make sure that the ue flags are saved (Bug) */
	if (report_config.nr_ue == 0) {
	  report_config.nr_ue = 1;
	  report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t));
	  if (report_config.ue_report_type == NULL) {
	    // TODO: Add appropriate error code
	    err_code = -100;
	    goto error;
	  }
	  report_config.ue_report_type[0].ue_rnti = 0; // Dummy value
	  report_config.ue_report_type[0].ue_report_flags = ue_flags;
	}
183
	request_config.config = &report_config;
184
	flexran_agent_enable_cont_mac_stats_update(enb_id, xid, &request_config);
185
      }
186
187
    }
    break;
188
189
  case PROTOCOL__FLEX_STATS_REQUEST__BODY_CELL_STATS_REQUEST:;
    Protocol__FlexCellStatsRequest *cell_req = stats_req->cell_stats_request;
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
    // UE report config will be blank
    report_config.nr_ue = 0;
    report_config.ue_report_type = NULL;
    report_config.nr_cc = cell_req->n_cell;
    report_config.cc_report_type = (cc_report_type_t *) malloc(sizeof(cc_report_type_t) * report_config.nr_cc);
    if (report_config.cc_report_type == NULL) {
      // TODO: Add appropriate error code
      err_code = -100;
      goto error;
    }
    for (i = 0; i < report_config.nr_cc; i++) {
	//TODO: Must fill in the proper cell ids
      report_config.cc_report_type[i].cc_id = cell_req->cell[i];
      report_config.cc_report_type[i].cc_report_flags = cell_req->flags;
    }
    break;
206
207
  case PROTOCOL__FLEX_STATS_REQUEST__BODY_UE_STATS_REQUEST:;
    Protocol__FlexUeStatsRequest *ue_req = stats_req->ue_stats_request;
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
    // Cell report config will be blank
    report_config.nr_cc = 0;
    report_config.cc_report_type = NULL;
    report_config.nr_ue = ue_req->n_rnti;
    report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t) * report_config.nr_ue);
    if (report_config.ue_report_type == NULL) {
      // TODO: Add appropriate error code
      err_code = -100;
      goto error;
    }
    for (i = 0; i < report_config.nr_ue; i++) {
      report_config.ue_report_type[i].ue_rnti = ue_req->rnti[i];
      report_config.ue_report_type[i].ue_report_flags = ue_req->flags;
    }
    break;
  default:
    //TODO: Add appropriate error code
    err_code = -100;
    goto error;
  }
nikaeinn's avatar
nikaeinn committed
228

229
  if (flexran_agent_mac_stats_reply(enb_id, xid, &report_config, msg) < 0 ){
230
    err_code = PROTOCOL__FLEXRAN_ERR__MSG_BUILD;
nikaeinn's avatar
nikaeinn committed
231
232
233
    goto error;
  }

234
235
236
  free(report_config.ue_report_type);
  free(report_config.cc_report_type);

nikaeinn's avatar
nikaeinn committed
237
238
239
  return 0;

 error :
240
  LOG_E(FLEXRAN_AGENT, "errno %d occured\n", err_code);
nikaeinn's avatar
nikaeinn committed
241
242
243
  return err_code;
}

244
245
246
247
int flexran_agent_mac_stats_request(mid_t mod_id,
				    xid_t xid,
				    const stats_request_config_t *report_config,
				    Protocol__FlexranMessage **msg) {
248
  Protocol__FlexHeader *header;
249
  int i;
250

251
252
  Protocol__FlexStatsRequest *stats_request_msg;
  stats_request_msg = malloc(sizeof(Protocol__FlexStatsRequest));
253
254
  if(stats_request_msg == NULL)
    goto error;
255
  protocol__flex_stats_request__init(stats_request_msg);
256
257
258
259

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

260
  stats_request_msg->header = header;
261

262
263
  stats_request_msg->type = report_config->report_type;
  stats_request_msg->has_type = 1;
264

265
  switch (report_config->report_type) {
266
267
268
269
  case PROTOCOL__FLEX_STATS_TYPE__FLST_COMPLETE_STATS:
    stats_request_msg->body_case =  PROTOCOL__FLEX_STATS_REQUEST__BODY_COMPLETE_STATS_REQUEST;
    Protocol__FlexCompleteStatsRequest *complete_stats;
    complete_stats = malloc(sizeof(Protocol__FlexCompleteStatsRequest));
270
271
    if(complete_stats == NULL)
      goto error;
272
    protocol__flex_complete_stats_request__init(complete_stats);
273
274
275
276
277
278
279
280
281
282
283
284
285
286
    complete_stats->report_frequency = report_config->report_frequency;
    complete_stats->has_report_frequency = 1;
    complete_stats->sf = report_config->period;
    complete_stats->has_sf = 1;
    complete_stats->has_cell_report_flags = 1;
    complete_stats->has_ue_report_flags = 1;
    if (report_config->config->nr_cc > 0) {
      complete_stats->cell_report_flags = report_config->config->cc_report_type[0].cc_report_flags;
    }
    if (report_config->config->nr_ue > 0) {
      complete_stats->ue_report_flags = report_config->config->ue_report_type[0].ue_report_flags;
    }
    stats_request_msg->complete_stats_request = complete_stats;
    break;
287
288
289
290
  case  PROTOCOL__FLEX_STATS_TYPE__FLST_CELL_STATS:
    stats_request_msg->body_case = PROTOCOL__FLEX_STATS_REQUEST__BODY_CELL_STATS_REQUEST;
     Protocol__FlexCellStatsRequest *cell_stats;
     cell_stats = malloc(sizeof(Protocol__FlexCellStatsRequest));
291
292
    if(cell_stats == NULL)
      goto error;
293
    protocol__flex_cell_stats_request__init(cell_stats);
294
295
296
297
298
299
300
301
302
303
304
305
306
    cell_stats->n_cell = report_config->config->nr_cc;
    cell_stats->has_flags = 1;
    if (cell_stats->n_cell > 0) {
      uint32_t *cells;
      cells = (uint32_t *) malloc(sizeof(uint32_t)*cell_stats->n_cell);
      for (i = 0; i < cell_stats->n_cell; i++) {
	cells[i] = report_config->config->cc_report_type[i].cc_id;
      }
      cell_stats->cell = cells;
      cell_stats->flags = report_config->config->cc_report_type[i].cc_report_flags;
    }
    stats_request_msg->cell_stats_request = cell_stats;
    break;
307
308
309
310
  case PROTOCOL__FLEX_STATS_TYPE__FLST_UE_STATS:
    stats_request_msg->body_case = PROTOCOL__FLEX_STATS_REQUEST__BODY_UE_STATS_REQUEST;
     Protocol__FlexUeStatsRequest *ue_stats;
     ue_stats = malloc(sizeof(Protocol__FlexUeStatsRequest));
311
312
    if(ue_stats == NULL)
      goto error;
313
    protocol__flex_ue_stats_request__init(ue_stats);
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
    ue_stats->n_rnti = report_config->config->nr_ue;
    ue_stats->has_flags = 1;
    if (ue_stats->n_rnti > 0) {
      uint32_t *ues;
      ues = (uint32_t *) malloc(sizeof(uint32_t)*ue_stats->n_rnti);
      for (i = 0; i < ue_stats->n_rnti; i++) {
	ues[i] = report_config->config->ue_report_type[i].ue_rnti;
      }
      ue_stats->rnti = ues;
      ue_stats->flags = report_config->config->ue_report_type[i].ue_report_flags;
    }
    stats_request_msg->ue_stats_request = ue_stats;
    break;
  default:
    goto error;
  }
330
  *msg = malloc(sizeof(Protocol__FlexranMessage));
331
332
  if(*msg == NULL)
    goto error;
333
334
335
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REQUEST_MSG;
  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
336
337
  (*msg)->stats_request_msg = stats_request_msg;
  return 0;
338

339
340
341
342
343
344
345
346
347
348
349
350
 error:
  // TODO: Need to make proper error handling
  if (header != NULL)
    free(header);
  if (stats_request_msg != NULL)
    free(stats_request_msg);
  if(*msg != NULL)
    free(*msg);
  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
  return -1;
}

351
int flexran_agent_mac_destroy_stats_request(Protocol__FlexranMessage *msg) {
352
   if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REQUEST_MSG)
353
354
    goto error;
  free(msg->stats_request_msg->header);
355
  if (msg->stats_request_msg->body_case == PROTOCOL__FLEX_STATS_REQUEST__BODY_CELL_STATS_REQUEST) {
356
357
    free(msg->stats_request_msg->cell_stats_request->cell);
  }
358
  if (msg->stats_request_msg->body_case == PROTOCOL__FLEX_STATS_REQUEST__BODY_UE_STATS_REQUEST) {
359
360
361
362
363
    free(msg->stats_request_msg->ue_stats_request->rnti);
  }
  free(msg->stats_request_msg);
  free(msg);
  return 0;
364

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

370
371
372
373
int flexran_agent_mac_stats_reply(mid_t mod_id,
				  xid_t xid,
				  const report_config_t *report_config,
				  Protocol__FlexranMessage **msg) {
374
  Protocol__FlexHeader *header;
nikaeinn's avatar
nikaeinn committed
375
  int i, j, k;
376
377
378
  int enb_id = mod_id;
  //eNB_MAC_INST *eNB = &eNB_mac_inst[enb_id];
  //UE_list_t *eNB_UE_list=  &eNB->UE_list;
379

380
381
  Protocol__FlexStatsReply *stats_reply_msg;
  stats_reply_msg = malloc(sizeof(Protocol__FlexStatsReply));
nikaeinn's avatar
nikaeinn committed
382
383
  if (stats_reply_msg == NULL)
    goto error;
384
  protocol__flex_stats_reply__init(stats_reply_msg);
385
386
387
388

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

nikaeinn's avatar
nikaeinn committed
389
390
391
392
393
  stats_reply_msg->header = header;

  stats_reply_msg->n_ue_report = report_config->nr_ue;
  stats_reply_msg->n_cell_report = report_config->nr_cc;

394
395
  Protocol__FlexUeStatsReport **ue_report;
  Protocol__FlexCellStatsReport **cell_report;
nikaeinn's avatar
nikaeinn committed
396

397

nikaeinn's avatar
nikaeinn committed
398
399
  /* Allocate memory for list of UE reports */
  if (report_config->nr_ue > 0) {
400
    ue_report = malloc(sizeof(Protocol__FlexUeStatsReport *) * report_config->nr_ue);
nikaeinn's avatar
nikaeinn committed
401
402
403
    if (ue_report == NULL)
      goto error;
    for (i = 0; i < report_config->nr_ue; i++) {
404
405
      ue_report[i] = malloc(sizeof(Protocol__FlexUeStatsReport));
      protocol__flex_ue_stats_report__init(ue_report[i]);
nikaeinn's avatar
nikaeinn committed
406
407
408
409
410
411
412
      ue_report[i]->rnti = report_config->ue_report_type[i].ue_rnti;
      ue_report[i]->has_rnti = 1;
      ue_report[i]->flags = report_config->ue_report_type[i].ue_report_flags;
      ue_report[i]->has_flags = 1;
      /* Check the types of reports that need to be constructed based on flag values */

      /* Check flag for creation of buffer status report */
413
      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_BSR) {
nikaeinn's avatar
nikaeinn committed
414
415
416
417
418
	ue_report[i]->n_bsr = 4;
	uint32_t *elem;
	elem = (uint32_t *) malloc(sizeof(uint32_t)*ue_report[i]->n_bsr);
	if (elem == NULL)
	  goto error;
419
	for (j = 0; j < ue_report[i]->n_bsr; j++) {
nikaeinn's avatar
nikaeinn committed
420
	  // NN: we need to know the cc_id here, consider the first one
421
	  elem[j] = flexran_get_ue_bsr (enb_id, i, j); 
nikaeinn's avatar
nikaeinn committed
422
423
424
	}
	ue_report[i]->bsr = elem;
      }
425

nikaeinn's avatar
nikaeinn committed
426
      /* Check flag for creation of PRH report */
427
      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PRH) {
428
	ue_report[i]->phr = flexran_get_ue_phr (enb_id, i); // eNB_UE_list->UE_template[UE_PCCID(enb_id,i)][i].phr_info;
nikaeinn's avatar
nikaeinn committed
429
430
431
432
	ue_report[i]->has_phr = 1;
      }

      /* Check flag for creation of RLC buffer status report */
433
      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RLC_BS) {
434
	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
435
436
	Protocol__FlexRlcBsr ** rlc_reports;
	rlc_reports = malloc(sizeof(Protocol__FlexRlcBsr *) * ue_report[i]->n_rlc_report);
nikaeinn's avatar
nikaeinn committed
437
438
	if (rlc_reports == NULL)
	  goto error;
439

nikaeinn's avatar
nikaeinn committed
440
441
	// NN: see LAYER2/openair2_proc.c for rlc status
	for (j = 0; j < ue_report[i]->n_rlc_report; j++) {
442
	  rlc_reports[j] = malloc(sizeof(Protocol__FlexRlcBsr));
nikaeinn's avatar
nikaeinn committed
443
444
	  if (rlc_reports[j] == NULL)
	    goto error;
445
	  protocol__flex_rlc_bsr__init(rlc_reports[j]);
446
	  rlc_reports[j]->lc_id = j + 1;
nikaeinn's avatar
nikaeinn committed
447
	  rlc_reports[j]->has_lc_id = 1;
448
	  rlc_reports[j]->tx_queue_size = flexran_get_tx_queue_size(enb_id,i,j + 1);
nikaeinn's avatar
nikaeinn committed
449
	  rlc_reports[j]->has_tx_queue_size = 1;
450
	  
nikaeinn's avatar
nikaeinn committed
451
452
	  //TODO:Set tx queue head of line delay in ms
	  rlc_reports[j]->tx_queue_hol_delay = 100;
453
	  rlc_reports[j]->has_tx_queue_hol_delay = 0;
nikaeinn's avatar
nikaeinn committed
454
455
	  //TODO:Set retransmission queue size in bytes
	  rlc_reports[j]->retransmission_queue_size = 10;
456
	  rlc_reports[j]->has_retransmission_queue_size = 0;
nikaeinn's avatar
nikaeinn committed
457
458
	  //TODO:Set retransmission queue head of line delay in ms
	  rlc_reports[j]->retransmission_queue_hol_delay = 100;
459
	  rlc_reports[j]->has_retransmission_queue_hol_delay = 0;
nikaeinn's avatar
nikaeinn committed
460
461
	  //TODO:Set current size of the pending message in bytes
	  rlc_reports[j]->status_pdu_size = 100;
462
	  rlc_reports[j]->has_status_pdu_size = 0;
nikaeinn's avatar
nikaeinn committed
463
464
465
466
467
468
469
	}
	// Add RLC buffer status reports to the full report
	if (ue_report[i]->n_rlc_report > 0)
	  ue_report[i]->rlc_report = rlc_reports;
      }

      /* Check flag for creation of MAC CE buffer status report */
470
      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_CE_BS) {
nikaeinn's avatar
nikaeinn committed
471
	// TODO: Fill in the actual MAC CE buffer status report
472
	ue_report[i]->pending_mac_ces = (flexran_get_MAC_CE_bitmap_TA(enb_id,i,0) | (0 << 1) | (0 << 2) | (0 << 3)) & 15;  /* Use as bitmap. Set one or more of the
473
					       PROTOCOL__FLEX_CE_TYPE__FLPCET_ values
nikaeinn's avatar
nikaeinn committed
474
					       found in stats_common.pb-c.h. See
475
					       flex_ce_type in FlexRAN specification */
nikaeinn's avatar
nikaeinn committed
476
477
	ue_report[i]->has_pending_mac_ces = 1;
      }
478

nikaeinn's avatar
nikaeinn committed
479
      /* Check flag for creation of DL CQI report */
480
      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) {
nikaeinn's avatar
nikaeinn committed
481
	// TODO: Fill in the actual DL CQI report for the UE based on its configuration
482
483
	Protocol__FlexDlCqiReport * dl_report;
	dl_report = malloc(sizeof(Protocol__FlexDlCqiReport));
nikaeinn's avatar
nikaeinn committed
484
485
	if (dl_report == NULL)
	  goto error;
486
	protocol__flex_dl_cqi_report__init(dl_report);
487

488
	dl_report->sfn_sn = flexran_get_sfn_sf(enb_id);
nikaeinn's avatar
nikaeinn committed
489
	dl_report->has_sfn_sn = 1;
490
	//Set the number of DL CQI reports for this UE. One for each CC
491
	dl_report->n_csi_report = flexran_get_active_CC(enb_id,i);
492
493

	//Create the actual CSI reports.
494
495
	Protocol__FlexDlCsi **csi_reports;
	csi_reports = malloc(sizeof(Protocol__FlexDlCsi *)*dl_report->n_csi_report);
nikaeinn's avatar
nikaeinn committed
496
497
498
	if (csi_reports == NULL)
	  goto error;
	for (j = 0; j < dl_report->n_csi_report; j++) {
499
	  csi_reports[j] = malloc(sizeof(Protocol__FlexDlCsi));
nikaeinn's avatar
nikaeinn committed
500
501
	  if (csi_reports[j] == NULL)
	    goto error;
502
	  protocol__flex_dl_csi__init(csi_reports[j]);
503
	  //The servCellIndex for this report
504
	  csi_reports[j]->serv_cell_index = j;
nikaeinn's avatar
nikaeinn committed
505
	  csi_reports[j]->has_serv_cell_index = 1;
506
	  //The rank indicator value for this cc
507
	  csi_reports[j]->ri = flexran_get_current_RI(enb_id,i,j);
nikaeinn's avatar
nikaeinn committed
508
509
	  csi_reports[j]->has_ri = 1;
	  //TODO: the type of CSI report based on the configuration of the UE
510
	  //For now we only support type P10, which only needs a wideband value
nikaeinn's avatar
nikaeinn committed
511
	  //The full set of types can be found in stats_common.pb-c.h and
512
513
	  //in the FlexRAN specifications
    csi_reports[j]->type =  PROTOCOL__FLEX_CSI_TYPE__FLCSIT_P10;
514
		  csi_reports[j]->has_type = 1;
515
516
517
518
		  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));
519
520
			  if (csi10 == NULL)
				goto error;
521
			  protocol__flex_csi_p10__init(csi10);
522
523
			  //TODO: set the wideband value
			  // NN: this is also depends on cc_id
524
			  csi10->wb_cqi = flexran_get_ue_wcqi (enb_id, i); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].dl_cqi;
525
526
527
528
			  csi10->has_wb_cqi = 1;
			  //Add the type of measurements to the csi report in the proper union type
			  csi_reports[j]->p10csi = csi10;
		  }
529
		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI){
530
531

		  }
532
		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI){
533
534

		  }
535
		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI){
536
537

		  }
538
		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI){
539
540

		  }
541
		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI){
542
543

		  }
544
		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI){
545
546

		  }
547
		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI){
548
549

		  }
550
		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI){
551
552
553

		  }
		}
nikaeinn's avatar
nikaeinn committed
554
555
556
557
558
	//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;
      }
559

nikaeinn's avatar
nikaeinn committed
560
      /* Check flag for creation of paging buffer status report */
561
      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) {
nikaeinn's avatar
nikaeinn committed
562
563
	//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
564
565
	Protocol__FlexPagingBufferReport *paging_report;
	paging_report = malloc(sizeof(Protocol__FlexPagingBufferReport));
nikaeinn's avatar
nikaeinn committed
566
567
	if (paging_report == NULL)
	  goto error;
568
	protocol__flex_paging_buffer_report__init(paging_report);
nikaeinn's avatar
nikaeinn committed
569
570
571
	//Set the number of pending paging messages
	paging_report->n_paging_info = 1;
	//Provide a report for each pending paging message
572
573
	Protocol__FlexPagingInfo **p_info;
	p_info = malloc(sizeof(Protocol__FlexPagingInfo *) * paging_report->n_paging_info);
nikaeinn's avatar
nikaeinn committed
574
575
576
	if (p_info == NULL)
	  goto error;
	for (j = 0; j < paging_report->n_paging_info; j++) {
577
	  p_info[j] = malloc(sizeof(Protocol__FlexPagingInfo));
nikaeinn's avatar
nikaeinn committed
578
579
	  if(p_info[j] == NULL)
	    goto error;
580
	  protocol__flex_paging_info__init(p_info[j]);
nikaeinn's avatar
nikaeinn committed
581
582
583
	  //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;
584
	  p_info[j]->has_paging_index = 0;
nikaeinn's avatar
nikaeinn committed
585
586
	  //TODO:Set the paging message size
	  p_info[j]->paging_message_size = 100;
587
	  p_info[j]->has_paging_message_size = 0;
nikaeinn's avatar
nikaeinn committed
588
589
	  //TODO: Set the paging subframe
	  p_info[j]->paging_subframe = 10;
590
	  p_info[j]->has_paging_subframe = 0;
nikaeinn's avatar
nikaeinn committed
591
592
	  //TODO: Set the carrier index for the pending paging message
	  p_info[j]->carrier_index = 0;
593
	  p_info[j]->has_carrier_index = 0;
nikaeinn's avatar
nikaeinn committed
594
595
596
597
598
599
	}
	//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;
      }
600

nikaeinn's avatar
nikaeinn committed
601
      /* Check flag for creation of UL CQI report */
602
      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) {
nikaeinn's avatar
nikaeinn committed
603
	//Fill in the full UL CQI report of the UE
604
605
	Protocol__FlexUlCqiReport *full_ul_report;
	full_ul_report = malloc(sizeof(Protocol__FlexUlCqiReport));
nikaeinn's avatar
nikaeinn committed
606
607
	if(full_ul_report == NULL)
	  goto error;
608
	protocol__flex_ul_cqi_report__init(full_ul_report);
nikaeinn's avatar
nikaeinn committed
609
	//TODO:Set the SFN and SF of the generated report
610
	full_ul_report->sfn_sn = flexran_get_sfn_sf(enb_id);
nikaeinn's avatar
nikaeinn committed
611
612
613
614
	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;
615
616
	Protocol__FlexUlCqi **ul_report;
	ul_report = malloc(sizeof(Protocol__FlexUlCqi *) * full_ul_report->n_cqi_meas);
nikaeinn's avatar
nikaeinn committed
617
618
619
	if(ul_report == NULL)
	  goto error;
	//Fill each UL report of the UE for each of the configured report types
620
	for(j = 0; j < full_ul_report->n_cqi_meas; j++) {
621
	  ul_report[j] = malloc(sizeof(Protocol__FlexUlCqi));
nikaeinn's avatar
nikaeinn committed
622
623
	  if(ul_report[j] == NULL)
	  goto error;
624
	  protocol__flex_ul_cqi__init(ul_report[j]);
nikaeinn's avatar
nikaeinn committed
625
	  //TODO: Set the type of the UL report. As an example set it to SRS UL report
626
627
	  // See enum flex_ul_cqi_type in FlexRAN specification for more details
	  ul_report[j]->type = PROTOCOL__FLEX_UL_CQI_TYPE__FLUCT_SRS;
nikaeinn's avatar
nikaeinn committed
628
629
	  ul_report[j]->has_type = 1;
	  //TODO:Set the number of SINR measurements based on the report type
630
	  //See struct flex_ul_cqi in FlexRAN specification for more details
631
	  ul_report[j]->n_sinr = 0;
nikaeinn's avatar
nikaeinn committed
632
633
634
635
636
637
638
639
640
641
642
643
	  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;
644
	  
nikaeinn's avatar
nikaeinn committed
645
646
	  //Set the list of UL reports of this UE to the full UL report
	  full_ul_report->cqi_meas = ul_report;
647

648
	  full_ul_report->n_pucch_dbm = MAX_NUM_CCs;
649
	  full_ul_report->pucch_dbm = malloc(sizeof(Protocol__FlexPucchDbm *) * full_ul_report->n_pucch_dbm);
650
651

	  for (j = 0; j < MAX_NUM_CCs; j++) {
652
653
	    full_ul_report->pucch_dbm[j] = malloc(sizeof(Protocol__FlexPucchDbm));
	    protocol__flex_pucch_dbm__init(full_ul_report->pucch_dbm[j]);
654
655
	    full_ul_report->pucch_dbm[j]->has_serv_cell_index = 1;
	    full_ul_report->pucch_dbm[j]->serv_cell_index = j;
656
657
	    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);
658
659
	      full_ul_report->pucch_dbm[j]->has_p0_pucch_dbm = 1;
	    }
660
661
	    full_ul_report->pucch_dbm[j]->has_p0_pucch_updated = 1;
	    full_ul_report->pucch_dbm[j]->p0_pucch_updated = flexran_get_p0_pucch_status(enb_id, i, j);
662
663
	  }

nikaeinn's avatar
nikaeinn committed
664
665
666
667
668
669
670
671
672
673
674
	  //Add full UL CQI report to the UE report
	  ue_report[i]->ul_cqi_report = full_ul_report;
	}
      }
    }
    /* Add list of all UE reports to the message */
    stats_reply_msg->ue_report = ue_report;
  }

  /* Allocate memory for list of cell reports */
  if (report_config->nr_cc > 0) {
675
    cell_report = malloc(sizeof(Protocol__FlexCellStatsReport *) * report_config->nr_cc);
nikaeinn's avatar
nikaeinn committed
676
677
678
679
    if (cell_report == NULL)
      goto error;
    // Fill in the Cell reports
    for (i = 0; i < report_config->nr_cc; i++) {
680
      cell_report[i] = malloc(sizeof(Protocol__FlexCellStatsReport));
681
      if(cell_report[i] == NULL)
nikaeinn's avatar
nikaeinn committed
682
	goto error;
683
      protocol__flex_cell_stats_report__init(cell_report[i]);
nikaeinn's avatar
nikaeinn committed
684
685
686
687
688
689
      cell_report[i]->carrier_index = report_config->cc_report_type[i].cc_id;
      cell_report[i]->has_carrier_index = 1;
      cell_report[i]->flags = report_config->cc_report_type[i].cc_report_flags;
      cell_report[i]->has_flags = 1;

      /* Check flag for creation of noise and interference report */
690
      if(report_config->cc_report_type[i].cc_report_flags & PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE) {
nikaeinn's avatar
nikaeinn committed
691
	// TODO: Fill in the actual noise and interference report for this cell
692
693
	Protocol__FlexNoiseInterferenceReport *ni_report;
	ni_report = malloc(sizeof(Protocol__FlexNoiseInterferenceReport));
nikaeinn's avatar
nikaeinn committed
694
695
	if(ni_report == NULL)
	  goto error;
696
	protocol__flex_noise_interference_report__init(ni_report);
nikaeinn's avatar
nikaeinn committed
697
	// Current frame and subframe number
698
	ni_report->sfn_sf = flexran_get_sfn_sf(enb_id);
nikaeinn's avatar
nikaeinn committed
699
	ni_report->has_sfn_sf = 1;
700
	//TODO:Received interference power in dbm
nikaeinn's avatar
nikaeinn committed
701
	ni_report->rip = 0;
702
703
	ni_report->has_rip = 0;
	//TODO:Thermal noise power in dbm
nikaeinn's avatar
nikaeinn committed
704
	ni_report->tnp = 0;
705
	ni_report->has_tnp = 0;
706

707
	ni_report->p0_nominal_pucch = flexran_get_p0_nominal_pucch(enb_id, 0);
708
	ni_report->has_p0_nominal_pucch = 1;
nikaeinn's avatar
nikaeinn committed
709
710
711
712
713
714
	cell_report[i]->noise_inter_report = ni_report;
      }
    }
    /* Add list of all cell reports to the message */
    stats_reply_msg->cell_report = cell_report;
  }
715

716
  *msg = malloc(sizeof(Protocol__FlexranMessage));
nikaeinn's avatar
nikaeinn committed
717
718
  if(*msg == NULL)
    goto error;
719
720
721
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG;
  (*msg)->msg_dir =  PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
nikaeinn's avatar
nikaeinn committed
722
723
  (*msg)->stats_reply_msg = stats_reply_msg;
  return 0;
724

nikaeinn's avatar
nikaeinn committed
725
726
727
728
729
730
731
732
733
734
735
736
 error:
  // TODO: Need to make proper error handling
  if (header != NULL)
    free(header);
  if (stats_reply_msg != NULL)
    free(stats_reply_msg);
  if(*msg != NULL)
    free(*msg);
  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
  return -1;
}

737
int flexran_agent_mac_destroy_stats_reply(Protocol__FlexranMessage *msg) {
nikaeinn's avatar
nikaeinn committed
738
  //TODO: Need to deallocate memory for the stats reply message
739
  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG)
nikaeinn's avatar
nikaeinn committed
740
741
742
    goto error;
  free(msg->stats_reply_msg->header);
  int i, j, k;
743

744
745
746
747
  Protocol__FlexStatsReply *reply = msg->stats_reply_msg;
  Protocol__FlexDlCqiReport *dl_report;
  Protocol__FlexUlCqiReport *ul_report;
  Protocol__FlexPagingBufferReport *paging_report;
nikaeinn's avatar
nikaeinn committed
748
749
750
751
752
753
754
755
756

  // 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
757
    if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) {
nikaeinn's avatar
nikaeinn committed
758
759
760
761
762
      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) {
763
	case PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI:
nikaeinn's avatar
nikaeinn committed
764
765
	  free(dl_report->csi_report[j]->p10csi);
	  break;
766
	case PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI:
nikaeinn's avatar
nikaeinn committed
767
768
769
	  free(dl_report->csi_report[j]->p11csi->wb_cqi);
	  free(dl_report->csi_report[j]->p11csi);
	  break;
770
	case PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI:
nikaeinn's avatar
nikaeinn committed
771
772
	  free(dl_report->csi_report[j]->p20csi);
	  break;
773
	case PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI:
nikaeinn's avatar
nikaeinn committed
774
775
776
777
	  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;
778
	case PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI:
nikaeinn's avatar
nikaeinn committed
779
780
781
782
	  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;
783
	case PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI:
nikaeinn's avatar
nikaeinn committed
784
785
786
787
788
	  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;
789
	case PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI:
nikaeinn's avatar
nikaeinn committed
790
791
792
	  free(dl_report->csi_report[j]->a20csi->sb_list);
	  free(dl_report->csi_report[j]->a20csi);
	  break;
793
	case PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI:
nikaeinn's avatar
nikaeinn committed
794
795
796
	  free(dl_report->csi_report[j]->a30csi->sb_cqi);
	  free(dl_report->csi_report[j]->a30csi);
	  break;
797
	case PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI:
nikaeinn's avatar
nikaeinn committed
798
799
800
801
802
803
	  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;
804
805
	default:
	  break;
806
807
	}

nikaeinn's avatar
nikaeinn committed
808
809
810
811
812
813
	free(dl_report->csi_report[j]);
      }
      free(dl_report->csi_report);
      free(dl_report);
    }
    // If Paging buffer report flag was set
814
    if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) {
nikaeinn's avatar
nikaeinn committed
815
816
817
818
819
820
821
822
823
      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
824
    if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) {
nikaeinn's avatar
nikaeinn committed
825
826
827
828
829
830
      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);
831
832
833
834
      for (j = 0; j < ul_report->n_pucch_dbm; j++) {
	free(ul_report->pucch_dbm[j]);
      }
      free(ul_report->pucch_dbm);
nikaeinn's avatar
nikaeinn committed
835
836
837
838
839
840
841
842
843
844
845
    }
    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);
846

nikaeinn's avatar
nikaeinn committed
847
848
849
  free(reply);
  free(msg);
  return 0;
850

nikaeinn's avatar
nikaeinn committed
851
852
853
854
 error:
  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
  return -1;
}
855

856
int flexran_agent_mac_sr_info(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
857
  Protocol__FlexHeader *header;
858
859
860
  int i;
  const int xid = *((int *)params);

861
862
  Protocol__FlexUlSrInfo *ul_sr_info_msg;
  ul_sr_info_msg = malloc(sizeof(Protocol__FlexUlSrInfo));
863
864
865
  if (ul_sr_info_msg == NULL) {
    goto error;
  }
866
  protocol__flex_ul_sr_info__init(ul_sr_info_msg);
867

868
869
870
  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_UL_SR_INFO, &header) != 0)
    goto error;

871
872
  ul_sr_info_msg->header = header;
  ul_sr_info_msg->has_sfn_sf = 1;
873
  ul_sr_info_msg->sfn_sf = flexran_get_sfn_sf(mod_id);
874
875
876
877
878
879
880
881
882
883
884
  /*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;
  }
885

886
  *msg = malloc(sizeof(Protocol__FlexranMessage));
887
888
  if(*msg == NULL)
    goto error;
889
890
891
  protocol__flexran_message__init(*msg);
  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG;
  (*msg)->msg_dir =  PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
892
893
  (*msg)->ul_sr_info_msg = ul_sr_info_msg;
  return 0;
894

895
896
897
898
899
900
901
902
903
904
905
906
907
908
 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;
}

909
int flexran_agent_mac_destroy_sr_info(Protocol__FlexranMessage *msg) {
910
   if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG)
911
912
913
914
915
916
917
918
919
920
921
922
923
     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;
}

924
int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
925
  Protocol__FlexHeader *header;
926
927
928
929
  int i, j, UE_id;
  
  int available_harq[NUMBER_OF_UE_MAX];
  
930
931
  const int xid = *((int *)params);

932

933
934
  Protocol__FlexSfTrigger *sf_trigger_msg;
  sf_trigger_msg = malloc(sizeof(Protocol__FlexSfTrigger));
935
  if (sf_trigger_msg == NULL) {
936
937
    goto error;
  }
938
  protocol__flex_sf_trigger__init(sf_trigger_msg);
939

940
941
942
  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_SF_TRIGGER, &header) != 0)
    goto error;

943
944
945
  frame_t frame;
  sub_frame_t subframe;

946
947
948
949
950
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    available_harq[i] = -1;
  }

  int ahead_of_time = 0;
951
  
952
953
  frame = (frame_t) flexran_get_current_system_frame_num(mod_id);
  subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
954
955
956

  subframe = ((subframe + ahead_of_time) % 10);
  
957
  if (subframe < flexran_get_current_subframe(mod_id)) {
958
    frame = (frame + 1) % 1024;
959
960
  }

961
962
963
  int additional_frames = ahead_of_time / 10;
  frame = (frame + additional_frames) % 1024;

964
965
  sf_trigger_msg->header = header;
  sf_trigger_msg->has_sfn_sf = 1;
966
  sf_trigger_msg->sfn_sf = flexran_get_future_sfn_sf(mod_id, 3);
967

968
969
970
971
972
973
974
975
976
977
978
979
980
981
  sf_trigger_msg->n_dl_info = 0;

  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    for (j = 0; j < 8; j++) {
      if (harq_pid_updated[i][j] == 1) {
	available_harq[i] = j;
	sf_trigger_msg->n_dl_info++;
	break;
      }
    }
  }

  //  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);

982
983
984
  /*TODO: Fill in the number of dl HARQ related info, based on the number of currently
   *transmitting UEs
   */
985
  //  sf_trigger_msg->n_dl_info = flexran_get_num_ues(mod_id);
986

987
  Protocol__FlexDlInfo **dl_info = NULL;
988

989
  if (sf_trigger_msg->n_dl_info > 0) {
990
    dl_info = malloc(sizeof(Protocol__FlexDlInfo *) * sf_trigger_msg->n_dl_info);
991
992
    if(dl_info == NULL)
      goto error;
993
    i = -1;
994
    //Fill the status of the current HARQ process for each UE
995
996
997
998
999
1000
    for(UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
      if (available_harq[UE_id] < 0) {
	continue;
      } else {
	i++;
      }
1001
      dl_info[i] = malloc(sizeof(Protocol__FlexDlInfo));