Commit 11b2f829 authored by Xenofon Foukas's avatar Xenofon Foukas

Integrated timer to work with periodic report messages and agent tasks

parent e88779c4
......@@ -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;
}
......@@ -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;
}
......
......@@ -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);
......
......@@ -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");
......
......@@ -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,
......
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment