From 11b2f829367c39ab7479a0b410cd62e773d24117 Mon Sep 17 00:00:00 2001 From: Xenofon Foukas <x.foukas@sms.ed.ac.uk> Date: Thu, 7 Jan 2016 17:41:51 +0200 Subject: [PATCH] Integrated timer to work with periodic report messages and agent tasks --- openair2/ENB_APP/enb_agent.c | 116 ++++++++++-------- openair2/ENB_APP/enb_agent_common.c | 2 +- openair2/ENB_APP/enb_agent_common.h | 16 +-- openair2/ENB_APP/enb_agent_handler.c | 22 +++- openair2/ENB_APP/enb_agent_mac.c | 169 +++++++++++++++++++++++++-- openair2/ENB_APP/enb_agent_mac.h | 13 +++ 6 files changed, 268 insertions(+), 70 deletions(-) diff --git a/openair2/ENB_APP/enb_agent.c b/openair2/ENB_APP/enb_agent.c index e8a4466b26..dbefc60502 100644 --- a/openair2/ENB_APP/enb_agent.c +++ b/openair2/ENB_APP/enb_agent.c @@ -53,7 +53,7 @@ static uint16_t in_port; void *send_thread(void *args); void *receive_thread(void *args); pthread_t new_thread(void *(*f)(void *), void *b); -err_code_t enb_agent_timeout(void* args); +Protocol__ProgranMessage *enb_agent_timeout(void* args); /* * enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller @@ -61,6 +61,13 @@ err_code_t enb_agent_timeout(void* args); */ void *enb_agent_task(void *args){ + msg_context_t *d = (msg_context_t *) args; + Protocol__ProgranMessage *msg; + void *data; + int size; + err_code_t err_code; + int priority; + MessageDef *msg_p = NULL; const char *msg_name = NULL; instance_t instance; @@ -86,7 +93,15 @@ void *enb_agent_task(void *args){ break; case TIMER_HAS_EXPIRED: - enb_agent_process_timeout(msg_p->ittiMsg.timer_has_expired.timer_id, &msg_p->ittiMsg.timer_has_expired.arg); + msg = enb_agent_process_timeout(msg_p->ittiMsg.timer_has_expired.timer_id, msg_p->ittiMsg.timer_has_expired.arg); + if (msg != NULL){ + data=enb_agent_send_message(msg,&size); + if (message_put(d->tx_mq, data, size, priority)){ + err_code = PROTOCOL__PROGRAN_ERR__MSG_ENQUEUING; + goto error; + } + LOG_D(ENB_AGENT,"sent message with size %d\n", size); + } break; default: @@ -96,46 +111,49 @@ void *enb_agent_task(void *args){ result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + continue; + error: + LOG_E(ENB_AGENT,"enb_agent_task: error %d occured\n",err_code); } while (1); return NULL; } -void *send_thread(void *args) { - -#ifdef TEST_TIMER - - msg_context_t *d = args; - void *data; - int size; - int priority; - - struct timeval t1, t2; - long long t; - struct timespec ts; - unsigned int delay = 250*1000; - while(1) { - gettimeofday(&t1, NULL); - enb_agent_sleep_until(&ts, delay); - gettimeofday(&t2, NULL); - t = ((t2.tv_sec * 1000000) + t2.tv_usec) - ((t1.tv_sec * 1000000) + t1.tv_usec); - LOG_I(ENB_AGENT, "Call to sleep_until(%d) took %lld us\n", delay, t); - sleep(1); - } - -#endif - /* while (1) { - // need logic for the timer, and - usleep(10); - if (message_put(d->tx_mq, data, size, priority)) goto error; - }*/ - - return NULL; - -error: - printf("receive_thread: there was an error\n"); - return NULL; -} +/* void *send_thread(void *args) { */ + +/* #ifdef TEST_TIMER */ + +/* msg_context_t *d = args; */ +/* void *data; */ +/* int size; */ +/* int priority; */ + +/* struct timeval t1, t2; */ +/* long long t; */ +/* struct timespec ts; */ +/* unsigned int delay = 250*1000; */ +/* while(1) { */ +/* gettimeofday(&t1, NULL); */ +/* enb_agent_sleep_until(&ts, delay); */ +/* gettimeofday(&t2, NULL); */ +/* t = ((t2.tv_sec * 1000000) + t2.tv_usec) - ((t1.tv_sec * 1000000) + t1.tv_usec); */ +/* LOG_I(ENB_AGENT, "Call to sleep_until(%d) took %lld us\n", delay, t); */ +/* sleep(1); */ +/* } */ + +/* #endif */ +/* /\* while (1) { */ +/* // need logic for the timer, and */ +/* usleep(10); */ +/* if (message_put(d->tx_mq, data, size, priority)) goto error; */ +/* }*\/ */ + +/* return NULL; */ + +/* error: */ +/* printf("receive_thread: there was an error\n"); */ +/* return NULL; */ +/* } */ void *receive_thread(void *args) { @@ -290,25 +308,25 @@ int enb_agent_start(mid_t mod_id, const Enb_properties_array_t* enb_properties){ * start the enb agent task for tx and interaction with the underlying network function */ - if (itti_create_task (TASK_ENB_AGENT, enb_agent_task, NULL) < 0) { + if (itti_create_task (TASK_ENB_AGENT, enb_agent_task, (void *) &shared_ctxt[mod_id]) < 0) { LOG_E(ENB_AGENT, "Create task for eNB Agent failed\n"); return -1; } -#ifdef TEST_TIMER + //#ifdef TEST_TIMER long timer_id=0; enb_agent_timer_args_t timer_args; memset (&timer_args, 0, sizeof(enb_agent_timer_args_t)); timer_args.mod_id = mod_id; - timer_args.cc_actions= ENB_AGENT_ACTION_APPLY; - timer_args.cc_report_flags = PROTOCOL__PRP_CELL_STATS_TYPE__PRCST_NOISE_INTERFERENCE; - timer_args.ue_actions = ENB_AGENT_ACTION_SEND; - timer_args.ue_report_flags = PROTOCOL__PRP_UE_STATS_TYPE__PRUST_BSR | PROTOCOL__PRP_UE_STATS_TYPE__PRUST_DL_CQI; + //timer_args.cc_actions= ENB_AGENT_ACTION_APPLY; + //timer_args.cc_report_flags = PROTOCOL__PRP_CELL_STATS_TYPE__PRCST_NOISE_INTERFERENCE; + //timer_args.ue_actions = ENB_AGENT_ACTION_SEND; + //timer_args.ue_report_flags = PROTOCOL__PRP_UE_STATS_TYPE__PRUST_BSR | PROTOCOL__PRP_UE_STATS_TYPE__PRUST_DL_CQI; enb_agent_create_timer(1, 0, ENB_AGENT_DEFAULT, mod_id, ENB_AGENT_TIMER_TYPE_PERIODIC, enb_agent_timeout,(void*)&timer_args, &timer_id); -#endif + //#endif - new_thread(send_thread, &shared_ctxt); + //new_thread(send_thread, &shared_ctxt); //while (1) pause(); @@ -342,15 +360,15 @@ int enb_agent_stop(mid_t mod_id){ -err_code_t enb_agent_timeout(void* args){ +Protocol__ProgranMessage *enb_agent_timeout(void* args){ // enb_agent_timer_args_t *timer_args = calloc(1, sizeof(*timer_args)); //memcpy (timer_args, args, sizeof(*timer_args)); enb_agent_timer_args_t *timer_args = (enb_agent_timer_args_t *) args; LOG_I(ENB_AGENT, "enb_agent %d timeout\n", timer_args->mod_id); - LOG_I(ENB_AGENT, "eNB action %d ENB flags %d \n", timer_args->cc_actions,timer_args->cc_report_flags); - LOG_I(ENB_AGENT, "UE action %d UE flags %d \n", timer_args->ue_actions,timer_args->ue_report_flags); + //LOG_I(ENB_AGENT, "eNB action %d ENB flags %d \n", timer_args->cc_actions,timer_args->cc_report_flags); + //LOG_I(ENB_AGENT, "UE action %d UE flags %d \n", timer_args->ue_actions,timer_args->ue_report_flags); - return 0; + return NULL; } diff --git a/openair2/ENB_APP/enb_agent_common.c b/openair2/ENB_APP/enb_agent_common.c index 490658c671..0417f4956e 100644 --- a/openair2/ENB_APP/enb_agent_common.c +++ b/openair2/ENB_APP/enb_agent_common.c @@ -311,7 +311,7 @@ uint16_t get_sfn_sf (mid_t mod_id) { frame = (uint16_t) get_current_frame(mod_id); subframe = (uint16_t) get_current_subframe(mod_id); - sfn_sf = (frame << 12) | subframe; + sfn_sf = (subframe << 12) | frame; return sfn_sf; } diff --git a/openair2/ENB_APP/enb_agent_common.h b/openair2/ENB_APP/enb_agent_common.h index d12d3849ec..31d882d0c9 100644 --- a/openair2/ENB_APP/enb_agent_common.h +++ b/openair2/ENB_APP/enb_agent_common.h @@ -86,6 +86,8 @@ Protocol__ProgranMessage* enb_agent_handle_message (mid_t mod_id, uint8_t *data, uint32_t size); +Protocol__ProgranMessage *enb_agent_handle_timed_task(void *args); + void * enb_agent_send_message(Protocol__ProgranMessage *msg, uint32_t * size); @@ -107,7 +109,7 @@ int get_current_frame(mid_t mod_id); int get_current_subframe(mid_t mod_id); /*Return the frame and subframe number in compact 16-bit format. - Bits 0-3 frame, rest for subframe. Required by progRAN protocol*/ + Bits 0-3 subframe, rest for frame. Required by progRAN protocol*/ uint16_t get_sfn_sf (mid_t mod_id); int get_num_ues(mid_t mod_id); @@ -137,7 +139,7 @@ int get_ue_wcqi (mid_t mod_id, mid_t ue_id); /* Type of the callback executed when the timer expired */ -typedef err_code_t (*enb_agent_timer_callback_t)(void*); +typedef Protocol__ProgranMessage *(*enb_agent_timer_callback_t)(void*); typedef enum { /* oneshot timer: */ @@ -169,13 +171,7 @@ typedef enum { typedef struct enb_agent_timer_args_s{ mid_t mod_id; - - agent_action_t cc_actions; - uint32_t cc_report_flags; - - agent_action_t ue_actions; - uint32_t ue_report_flags; - + Protocol__ProgranMessage *msg; } enb_agent_timer_args_t; @@ -225,7 +221,7 @@ struct enb_agent_timer_element_s * get_timer_entry(long timer_id); -err_code_t enb_agent_process_timeout(long timer_id, void* timer_args); +Protocol__ProgranMessage * enb_agent_process_timeout(long timer_id, void* timer_args); int enb_agent_compare_timer(struct enb_agent_timer_element_s *a, struct enb_agent_timer_element_s *b); diff --git a/openair2/ENB_APP/enb_agent_handler.c b/openair2/ENB_APP/enb_agent_handler.c index 8c2b9e010a..2841f9b6e5 100644 --- a/openair2/ENB_APP/enb_agent_handler.c +++ b/openair2/ENB_APP/enb_agent_handler.c @@ -133,11 +133,28 @@ void * enb_agent_send_message(Protocol__ProgranMessage *msg, error : LOG_E(ENB_AGENT,"errno %d occured\n",err_code); - return NULL; + return NULL; +} + +Protocol__ProgranMessage *enb_agent_handle_timed_task(void *args) { + err_code_t err_code; + enb_agent_timer_args_t *timer_args = (enb_agent_timer_args_t *) args; + + Protocol__ProgranMessage *timed_task, *reply_message; + timed_task = timer_args->msg; + err_code = ((*messages_callback[timed_task->msg_case-1][timed_task->msg_dir-1])(timer_args->mod_id, (void *) timed_task, &reply_message)); + if ( err_code < 0 ){ + goto error; + } + + return reply_message; + error: + LOG_E(ENB_AGENT,"errno %d occured\n",err_code); + return NULL; } -err_code_t enb_agent_process_timeout(long timer_id, void* timer_args){ +Protocol__ProgranMessage* enb_agent_process_timeout(long timer_id, void* timer_args){ struct enb_agent_timer_element_s *found = get_timer_entry(timer_id); @@ -148,7 +165,6 @@ err_code_t enb_agent_process_timeout(long timer_id, void* timer_args){ LOG_W(ENB_AGENT,"null timer args\n"); return found->cb(timer_args); - error: LOG_E(ENB_AGENT, "can't get the timer element\n"); diff --git a/openair2/ENB_APP/enb_agent_mac.c b/openair2/ENB_APP/enb_agent_mac.c index d2504e4dec..1a21db5e15 100644 --- a/openair2/ENB_APP/enb_agent_mac.c +++ b/openair2/ENB_APP/enb_agent_mac.c @@ -48,6 +48,7 @@ int enb_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__Progr int size; err_code_t err_code; xid_t xid; + uint32_t usec_interval, sec_interval; //TODO: We do not deal with multiple CCs at the moment and eNB id is 0 int cc_id = 0; @@ -70,12 +71,13 @@ int enb_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__Progr switch(stats_req->body_case) { case PROTOCOL__PRP_STATS_REQUEST__BODY_COMPLETE_STATS_REQUEST: ; Protocol__PrpCompleteStatsRequest *comp_req = stats_req->complete_stats_request; - if (comp_req->report_frequency == PROTOCOL__PRP_STATS_REPORT_FREQ__PRSRF_PERIODICAL) { - //TODO: Must create a periodic report. Implement once the - // timer functionality is supported - *msg = NULL; - return 0; - } else if (comp_req->report_frequency == PROTOCOL__PRP_STATS_REPORT_FREQ__PRSRF_CONTINUOUS) { + /* if (comp_req->report_frequency == PROTOCOL__PRP_STATS_REPORT_FREQ__PRSRF_PERIODICAL) { */ + /* //TODO: Must create a periodic report. Implement once the */ + /* // timer functionality is supported */ + /* *msg = NULL; */ + /* return 0; */ + /* } else */ + if (comp_req->report_frequency == PROTOCOL__PRP_STATS_REPORT_FREQ__PRSRF_CONTINUOUS) { //TODO: Must create an event based report mechanism *msg = NULL; return 0; @@ -83,7 +85,7 @@ int enb_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__Progr //TODO: Must implement to deactivate the event based reporting *msg = NULL; return 0; - } else { //One-off reporting + } else { //One-off or periodical reporting //Set the proper flags ue_flags = comp_req->ue_report_flags; c_flags = comp_req->cell_report_flags; @@ -114,6 +116,33 @@ int enb_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__Progr report_config.cc_report_type[i].cc_id = i; report_config.cc_report_type[i].cc_report_flags = c_flags; } + /* Check if request was periodical */ + if (comp_req->report_frequency == PROTOCOL__PRP_STATS_REPORT_FREQ__PRSRF_PERIODICAL) { + /* Create a one off progran message as an argument for the periodical task */ + Protocol__ProgranMessage *timer_msg; + stats_request_config_t request_config; + request_config.report_type = PROTOCOL__PRP_STATS_TYPE__PRST_COMPLETE_STATS; + request_config.report_frequency = PROTOCOL__PRP_STATS_REPORT_FREQ__PRSRF_ONCE; + request_config.period = 0; + request_config.config = &report_config; + enb_agent_mac_stats_request(enb_id, xid, &request_config, &timer_msg); + /* Create a timer */ + long timer_id = 0; + enb_agent_timer_args_t *timer_args; + timer_args = malloc(sizeof(enb_agent_timer_args_t)); + memset (timer_args, 0, sizeof(enb_agent_timer_args_t)); + timer_args->mod_id = enb_id; + 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); + } + enb_agent_create_timer(sec_interval, usec_interval, ENB_AGENT_DEFAULT, enb_id, ENB_AGENT_TIMER_TYPE_PERIODIC, enb_agent_handle_timed_task,(void*) timer_args, &timer_id); + } } break; case PROTOCOL__PRP_STATS_REQUEST__BODY_CELL_STATS_REQUEST:; @@ -172,6 +201,132 @@ int enb_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__Progr return err_code; } +int enb_agent_mac_stats_request(mid_t mod_id, + xid_t xid, + const stats_request_config_t *report_config, + Protocol__ProgranMessage **msg) { + Protocol__PrpHeader *header; + int i; + + if (prp_create_header(xid, PROTOCOL__PRP_TYPE__PRPT_STATS_REQUEST, &header) != 0) + goto error; + + Protocol__PrpStatsRequest *stats_request_msg; + stats_request_msg = malloc(sizeof(Protocol__PrpStatsRequest)); + if(stats_request_msg == NULL) + goto error; + + protocol__prp_stats_request__init(stats_request_msg); + stats_request_msg->header = header; + + stats_request_msg->type = report_config->report_type; + stats_request_msg->has_type = 1; + + switch (report_config->report_type) { + case PROTOCOL__PRP_STATS_TYPE__PRST_COMPLETE_STATS: + stats_request_msg->body_case = PROTOCOL__PRP_STATS_REQUEST__BODY_COMPLETE_STATS_REQUEST; + Protocol__PrpCompleteStatsRequest *complete_stats; + complete_stats = malloc(sizeof(Protocol__PrpCompleteStatsRequest)); + if(complete_stats == NULL) + goto error; + protocol__prp_complete_stats_request__init(complete_stats); + 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; + case PROTOCOL__PRP_STATS_TYPE__PRST_CELL_STATS: + stats_request_msg->body_case = PROTOCOL__PRP_STATS_REQUEST__BODY_CELL_STATS_REQUEST; + Protocol__PrpCellStatsRequest *cell_stats; + cell_stats = malloc(sizeof(Protocol__PrpCellStatsRequest)); + if(cell_stats == NULL) + goto error; + protocol__prp_cell_stats_request__init(cell_stats); + 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; + case PROTOCOL__PRP_STATS_TYPE__PRST_UE_STATS: + stats_request_msg->body_case = PROTOCOL__PRP_STATS_REQUEST__BODY_UE_STATS_REQUEST; + Protocol__PrpUeStatsRequest *ue_stats; + ue_stats = malloc(sizeof(Protocol__PrpUeStatsRequest)); + if(ue_stats == NULL) + goto error; + protocol__prp_ue_stats_request__init(ue_stats); + 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; + } + *msg = malloc(sizeof(Protocol__ProgranMessage)); + if(*msg == NULL) + goto error; + protocol__progran_message__init(*msg); + (*msg)->msg_case = PROTOCOL__PROGRAN_MESSAGE__MSG_STATS_REQUEST_MSG; + (*msg)->msg_dir = PROTOCOL__PROGRAN_DIRECTION__INITIATING_MESSAGE; + (*msg)->stats_request_msg = stats_request_msg; + return 0; + + 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; +} + +int enb_agent_mac_destroy_stats_request(Protocol__ProgranMessage *msg) { + if(msg->msg_case != PROTOCOL__PROGRAN_MESSAGE__MSG_STATS_REQUEST_MSG) + goto error; + free(msg->stats_request_msg->header); + if (msg->stats_request_msg->body_case == PROTOCOL__PRP_STATS_REQUEST__BODY_CELL_STATS_REQUEST) { + free(msg->stats_request_msg->cell_stats_request->cell); + } + if (msg->stats_request_msg->body_case == PROTOCOL__PRP_STATS_REQUEST__BODY_UE_STATS_REQUEST) { + free(msg->stats_request_msg->ue_stats_request->rnti); + } + free(msg->stats_request_msg); + free(msg); + return 0; + + error: + //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__); + return -1; +} + int enb_agent_mac_stats_reply(mid_t mod_id, xid_t xid, const report_config_t *report_config, diff --git a/openair2/ENB_APP/enb_agent_mac.h b/openair2/ENB_APP/enb_agent_mac.h index 569eb51e5e..871d6e5ae2 100644 --- a/openair2/ENB_APP/enb_agent_mac.h +++ b/openair2/ENB_APP/enb_agent_mac.h @@ -69,11 +69,24 @@ typedef struct { cc_report_type_t *cc_report_type; } report_config_t; +typedef struct { + uint8_t report_type; + uint8_t report_frequency; + uint16_t period; /*In number of subframes*/ + report_config_t *config; +} stats_request_config_t; + int enb_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__ProgranMessage **msg); +int enb_agent_mac_stats_request(mid_t mod_id, xid_t xid, const stats_request_config_t *report_config, Protocol__ProgranMessage **msg); + +int enb_agent_mac_destroy_stats_request(Protocol__ProgranMessage *msg); + int enb_agent_mac_stats_reply(mid_t mod_id, xid_t xid, const report_config_t *report_config, Protocol__ProgranMessage **msg); int enb_agent_mac_destroy_stats_reply(Protocol__ProgranMessage *msg); + + #endif -- 2.26.2