From a47f3654f8c347838b46de3e01d5a4dad9d46af5 Mon Sep 17 00:00:00 2001 From: Xenofon Foukas <x.foukas@sms.ed.ac.uk> Date: Tue, 12 Apr 2016 13:00:20 +0100 Subject: [PATCH] Added basic support for policy reconfiguration using yaml parser --- openair2/ENB_APP/enb_agent_common.c | 37 +- openair2/ENB_APP/enb_agent_common.h | 3 + openair2/ENB_APP/enb_agent_common_internal.c | 400 ++++++++++++++++++ openair2/ENB_APP/enb_agent_common_internal.h | 64 +++ openair2/ENB_APP/enb_agent_handler.c | 3 +- openair2/ENB_APP/enb_agent_mac.c | 4 + openair2/ENB_APP/enb_agent_mac_defs.h | 2 + openair2/ENB_APP/enb_agent_mac_internal.c | 235 ++++++++++ openair2/ENB_APP/enb_agent_mac_internal.h | 15 +- .../MAC/eNB_agent_scheduler_dlsch_ue_remote.c | 18 + 10 files changed, 758 insertions(+), 23 deletions(-) create mode 100644 openair2/ENB_APP/enb_agent_common_internal.c create mode 100644 openair2/ENB_APP/enb_agent_common_internal.h diff --git a/openair2/ENB_APP/enb_agent_common.c b/openair2/ENB_APP/enb_agent_common.c index f06599e258..e21c180cec 100644 --- a/openair2/ENB_APP/enb_agent_common.c +++ b/openair2/ENB_APP/enb_agent_common.c @@ -35,10 +35,10 @@ */ #include<stdio.h> -#include <dlfcn.h> #include <time.h> #include "enb_agent_common.h" +#include "enb_agent_common_internal.h" #include "enb_agent_extern.h" #include "PHY/extern.h" #include "log.h" @@ -403,7 +403,6 @@ int enb_agent_control_delegation(mid_t mod_id, const void *params, Protocol__Pro uint32_t delegation_type = control_delegation_msg->delegation_type; - void *lib; int i; struct timespec vartime = timer_start(); @@ -411,7 +410,7 @@ int enb_agent_control_delegation(mid_t mod_id, const void *params, Protocol__Pro //Write the payload lib into a file in the cache and load the lib char lib_name[120]; char target[512]; - snprintf(lib_name, sizeof(lib_name), "/delegation_lib_%d.so", control_delegation_msg->header->xid); + snprintf(lib_name, sizeof(lib_name), "/%s.so", control_delegation_msg->name); strcpy(target, local_cache); strcat(target, lib_name); @@ -419,25 +418,7 @@ int enb_agent_control_delegation(mid_t mod_id, const void *params, Protocol__Pro f = fopen(target, "wb"); fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f); fclose(f); - lib = dlopen(target, RTLD_NOW); - if (lib == NULL) { - goto error; - } - i = 0; - //Check functions that need to be delegated - - //DL UE scheduler delegation - if (delegation_type & PROTOCOL__PRP_CONTROL_DELEGATION_TYPE__PRCDT_MAC_DL_UE_SCHEDULER) { - void *loaded_scheduler = dlsym(lib, control_delegation_msg->name[i]); - i++; - if (loaded_scheduler) { - if (mac_agent_registered[mod_id]) { - agent_mac_xface[mod_id]->enb_agent_schedule_ue_spec = loaded_scheduler; - LOG_D(ENB_APP,"Delegated control for DL UE scheduler successfully\n"); - } - } - } long time_elapsed_nanos = timer_end(vartime); *msg = NULL; return 0; @@ -450,6 +431,20 @@ int enb_agent_destroy_control_delegation(Protocol__ProgranMessage *msg) { /*TODO: Dealocate memory for a dynamically allocated control delegation message*/ } +int enb_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__ProgranMessage **msg) { + Protocol__ProgranMessage *input = (Protocol__ProgranMessage *)params; + Protocol__PrpAgentReconfiguration *agent_reconfiguration_msg = input->agent_reconfiguration_msg; + + apply_reconfiguration_policy(mod_id, agent_reconfiguration_msg->policy, strlen(agent_reconfiguration_msg->policy)); + + *msg = NULL; + return 0; +} + +int enb_agent_destroy_agent_reconfiguration(Protocol__ProgranMessage *msg) { + /*TODO: Dealocate memory for a dynamically allocated agent reconfiguration message*/ +} + /* * get generic info from RAN */ diff --git a/openair2/ENB_APP/enb_agent_common.h b/openair2/ENB_APP/enb_agent_common.h index 9b483ce4a0..18c9129989 100644 --- a/openair2/ENB_APP/enb_agent_common.h +++ b/openair2/ENB_APP/enb_agent_common.h @@ -114,6 +114,9 @@ int enb_agent_destroy_ue_state_change(Protocol__ProgranMessage *msg); int enb_agent_control_delegation(mid_t mod_id, const void *params, Protocol__ProgranMessage **msg); int enb_agent_destroy_control_delegation(Protocol__ProgranMessage *msg); +int enb_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__ProgranMessage **msg); +int enb_agent_destroy_agent_reconfiguration(Protocol__ProgranMessage *msg); + Protocol__ProgranMessage* enb_agent_handle_message (mid_t mod_id, uint8_t *data, uint32_t size); diff --git a/openair2/ENB_APP/enb_agent_common_internal.c b/openair2/ENB_APP/enb_agent_common_internal.c new file mode 100644 index 0000000000..ca61a96609 --- /dev/null +++ b/openair2/ENB_APP/enb_agent_common_internal.c @@ -0,0 +1,400 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see <http://www.gnu.org/licenses/>. + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. + + *******************************************************************************/ + +/*! \file enb_agent_common_internal.c + * \brief internal functions for common message primitves and utilities + * \author Xenofon Foukas + * \date 2016 + * \version 0.1 + */ + +#include <stdlib.h> +#include <string.h> + +#include "enb_agent_common_internal.h" +#include "enb_agent_mac_internal.h" + +int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length) { + + yaml_parser_t parser; + yaml_event_t event; + + int done = 0; + int mapping_started = 0; + + LOG_I(ENB_APP, "Time to apply a new policy \n"); + + yaml_parser_initialize(&parser); + + yaml_parser_set_input_string(&parser, policy, strlen(policy)); + + while (!done) { + if (!yaml_parser_parse(&parser, &event)) + goto error; + + switch (event.type) { + case YAML_STREAM_START_EVENT: + case YAML_STREAM_END_EVENT: + case YAML_DOCUMENT_START_EVENT: + case YAML_DOCUMENT_END_EVENT: + break; + case YAML_MAPPING_START_EVENT: + mapping_started = 1; + break; + case YAML_MAPPING_END_EVENT: + mapping_started = 0; + break; + case YAML_SCALAR_EVENT: + // Check the system name and call the proper handler + if (strcmp(event.data.scalar.value, "mac") == 0) { + LOG_D(ENB_APP, "This is intended for the mac system\n"); + // Call the mac handler + if (parse_mac_config(mod_id, &parser) == -1) { + goto error; + } + } else if (strcmp(event.data.scalar.value, "rlc") == 0) { + // Call the RLC handler + LOG_D(ENB_APP, "This is intended for the rlc system\n"); + // TODO : Just skip it for now + if (skip_system_section(&parser) == -1) { + goto error; + } + } else if (strcmp(event.data.scalar.value, "pdcp") == 0) { + // Call the PDCP handler + LOG_D(ENB_APP, "This is intended for the pdcp system\n"); + // TODO : Just skip it for now + if (skip_system_section(&parser) == -1) { + goto error; + } + } else if (strcmp(event.data.scalar.value, "rrc") == 0) { + // Call the RRC handler + LOG_D(ENB_APP, "This is intended for the rrc system\n"); + // TODO : Just skip it for now + if (skip_system_section(&parser) == -1) { + goto error; + } + } else { + goto error; + } + break; + default: + // We are not expecting to find any other type of event at this level + // of the hierarchy + yaml_event_delete(&event); + goto error; + } + + done = (event.type == YAML_STREAM_END_EVENT); + + yaml_event_delete(&event); + } + + return 0; + + error: + yaml_parser_delete(&parser); + return -1; + +} + +int skip_system_section(yaml_parser_t *parser) { + yaml_event_t event; + + int done = 0; + + int sequence_started = 0; + int mapping_started = 0; + + while (!done) { + if (!yaml_parser_parse(parser, &event)) + goto error; + + switch (event.type) { + + case YAML_SEQUENCE_START_EVENT: + LOG_D(ENB_APP, "A sequence just started as expected\n"); + sequence_started = 1; + break; + case YAML_SEQUENCE_END_EVENT: + LOG_D(ENB_APP, "A sequence ended\n"); + sequence_started = 0; + break; + case YAML_MAPPING_START_EVENT: + if (!sequence_started) { + goto error; + } + LOG_D(ENB_APP, "A mapping started\n"); + mapping_started = 1; + break; + case YAML_MAPPING_END_EVENT: + if (!mapping_started) { + goto error; + } + LOG_D(ENB_APP, "A mapping ended\n"); + mapping_started = 0; + break; + case YAML_SCALAR_EVENT: + if (!mapping_started) { + goto error; + } + // Entered a subsystem section. Let's skip it + if (skip_subsystem_section(parser) == -1) { + goto error; + } + } + + done = (event.type == YAML_SEQUENCE_END_EVENT); + + yaml_event_delete(&event); + + } + + return 0; + + error: + yaml_event_delete(&event); + return -1; +} + +int skip_subsystem_section(yaml_parser_t *parser) { + + yaml_event_t event; + + int done = 0; + int mapping_started = 0; + + while (!done) { + if (!yaml_parser_parse(parser, &event)) + goto error; + + switch (event.type) { + case YAML_MAPPING_START_EVENT: + LOG_D(ENB_APP, "The mapping of the subsystem started\n"); + mapping_started = 1; + break; + case YAML_MAPPING_END_EVENT: + LOG_D(ENB_APP, "The mapping of the subsystem ended\n"); + mapping_started = 0; + break; + case YAML_SCALAR_EVENT: + if (!mapping_started) { + goto error; + } + // Check what key needs to be set + if (strcmp(event.data.scalar.value, "behavior") == 0) { + LOG_D(ENB_APP, "Skipping the behavior attribute\n"); + yaml_event_delete(&event); + if (!yaml_parser_parse(parser, &event)) { + goto error; + } + if (event.type == YAML_SCALAR_EVENT) { + break; + } else { + goto error; + } + } else if (strcmp(event.data.scalar.value, "parameters") == 0) { + LOG_D(ENB_APP, "Skipping the parameters for this subsystem\n"); + if (skip_subsystem_parameters_config(parser) == -1) { + goto error; + } + } + break; + default: + goto error; + } + + done = (event.type == YAML_MAPPING_END_EVENT); + yaml_event_delete(&event); + } + + return 0; + + error: + yaml_event_delete(&event); + return -1; +} + +int skip_subsystem_parameters_config(yaml_parser_t *parser) { + yaml_event_t event; + + void *param; + + int done = 0; + int mapping_started = 0; + + while (!done) { + + if (!yaml_parser_parse(parser, &event)) + goto error; + + switch (event.type) { + // We are expecting a mapping of parameters + case YAML_MAPPING_START_EVENT: + LOG_D(ENB_APP, "The mapping of the parameters started\n"); + mapping_started = 1; + break; + case YAML_MAPPING_END_EVENT: + LOG_D(ENB_APP, "The mapping of the parameters ended\n"); + mapping_started = 0; + break; + case YAML_SCALAR_EVENT: + if (!mapping_started) { + goto error; + } + // Check what key needs to be set + LOG_D(ENB_APP, "Skipping parameter %s\n", event.data.scalar.value); + if (skip_parameter_modification(parser) == -1 ) { + goto error; + } + break; + default: + goto error; + } + + done = (event.type == YAML_MAPPING_END_EVENT); + yaml_event_delete(&event); + } + + return 0; + + error: + yaml_event_delete(&event); + return -1; +} + + +int skip_parameter_modification(yaml_parser_t *parser) { + yaml_event_t event; + + int done = 0; + int is_array = 0; + int i = 0; + + while (!done) { + if (!yaml_parser_parse(parser, &event)) { + goto error; + } + + // Expecting either a scalar or a sequence + switch (event.type) { + case YAML_SEQUENCE_START_EVENT: + is_array = 1; + break; + case YAML_SCALAR_EVENT: + if ((strcmp(event.data.scalar.tag, YAML_INT_TAG) == 0) || + (strcmp(event.data.scalar.tag, YAML_FLOAT_TAG) == 0) || + (strcmp(event.data.scalar.tag, YAML_STR_TAG) == 0) || + (strcmp(event.data.scalar.tag, YAML_BOOL_TAG) == 0)) { + // Do nothing + } else { + // No other type is supported at the moment, so it should be considered an error + // if we reach here + goto error; + } + if (is_array) { + i++; + } else { + done = 1; + } + break; + case YAML_SEQUENCE_END_EVENT: + done = 1; + break; + default: + goto error; + } + yaml_event_delete(&event); + } + + return 0; + + error: + yaml_event_delete(&event); + return -1; +} + +int apply_parameter_modification(void *parameter, yaml_parser_t *parser) { + yaml_event_t event; + + int done = 0; + int is_array = 0; + int i = 0; + + char *endptr; + + while (!done) { + if (!yaml_parser_parse(parser, &event)) { + goto error; + } + + // Expecting either a scalar or a sequence + switch (event.type) { + case YAML_SEQUENCE_START_EVENT: + is_array = 1; + break; + case YAML_SCALAR_EVENT: + if (strcmp(event.data.scalar.tag, YAML_INT_TAG) == 0) { + ((int *) parameter)[i] = strtol(event.data.scalar.value, &endptr, 10); + } else if (strcmp(event.data.scalar.tag, YAML_FLOAT_TAG) == 0) { + ((float *) parameter)[i] = strtof(event.data.scalar.value, &endptr); + } else if (strcmp(event.data.scalar.tag, YAML_STR_TAG) == 0) { + strncpy(&((char *) parameter)[i], event.data.scalar.value, event.data.scalar.length); + } else if (strcmp(event.data.scalar.tag, YAML_BOOL_TAG) == 0) { + if (strcmp(event.data.scalar.value, "true") == 0) { + ((int *) parameter)[i] = 1; + } else { + ((int *) parameter)[i] = 0; + } + } else { + // No other type is supported at the moment, so it should be considered an error + // if we reach here + goto error; + } + if (is_array) { + i++; + } else { + done = 1; + } + break; + case YAML_SEQUENCE_END_EVENT: + done = 1; + break; + default: + goto error; + } + yaml_event_delete(&event); + } + + return 0; + + error: + yaml_event_delete(&event); + return -1; + +} diff --git a/openair2/ENB_APP/enb_agent_common_internal.h b/openair2/ENB_APP/enb_agent_common_internal.h new file mode 100644 index 0000000000..30fd51c5c8 --- /dev/null +++ b/openair2/ENB_APP/enb_agent_common_internal.h @@ -0,0 +1,64 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see <http://www.gnu.org/licenses/>. + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. + + *******************************************************************************/ + +/*! \file enb_agent_common_internal.h + * \brief internal agent functions for common message primitves and utilities + * \author Xenofon Foukas + * \date 2016 + * \version 0.1 + */ + +#ifndef ENB_AGENT_COMMON_INTERNAL_H_ +#define ENB_AGENT_COMMON_INTERNAL_H_ + +#include <yaml.h> + +#include "enb_agent_defs.h" + +int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length); + +int apply_parameter_modification(void *parameter, yaml_parser_t *parser); + +// This can be used when parsing for a specific system that is not yet implmeneted +// in order to skip its configuration, without affecting the rest +int skip_system_section(yaml_parser_t *parser); + +// This can be used when parsing for a specific subsystem that is not yet implmeneted +// in order to skip its configuration, without affecting the rest +int skip_subsystem_section(yaml_parser_t *parser); + +// This can be used when parsing for the parameters of a specific subsystem +//that is not yet implmeneted in order to skip its configuration, without affecting the rest +int skip_subsystem_parameters_config(yaml_parser_t *parser); + +// This can be used when configuring the parameters of a specific subsystem +//that is not yet implmeneted in order to skip its configuration, without affecting the rest +int skip_parameter_modification(yaml_parser_t *parser); + +#endif diff --git a/openair2/ENB_APP/enb_agent_handler.c b/openair2/ENB_APP/enb_agent_handler.c index 721b3678f8..da53343818 100644 --- a/openair2/ENB_APP/enb_agent_handler.c +++ b/openair2/ENB_APP/enb_agent_handler.c @@ -58,7 +58,7 @@ enb_agent_message_decoded_callback agent_messages_callback[][3] = { {enb_agent_mac_handle_dl_mac_config, 0, 0}, /*PROTOCOL__PROGRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG*/ {0, 0, 0}, /*PROTOCOL__PROGRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG*/ {enb_agent_control_delegation, 0, 0}, /*PROTOCOL__PROGRAN_MESSAGE__MSG_CONTROL_DELEGATION_MSG*/ - + {enb_agent_reconfiguration, 0, 0}, /*PROTOCOL__PROGRAN_MESSAGE__MSG_AGENT_RECONFIGURATION_MSG*/ }; enb_agent_message_destruction_callback message_destruction_callback[] = { @@ -78,6 +78,7 @@ enb_agent_message_destruction_callback message_destruction_callback[] = { enb_agent_mac_destroy_dl_config, enb_agent_destroy_ue_state_change, enb_agent_destroy_control_delegation, + enb_agent_destroy_agent_reconfiguration, }; static const char *enb_agent_direction2String[] = { diff --git a/openair2/ENB_APP/enb_agent_mac.c b/openair2/ENB_APP/enb_agent_mac.c index fb9ae7322f..744768135e 100644 --- a/openair2/ENB_APP/enb_agent_mac.c +++ b/openair2/ENB_APP/enb_agent_mac.c @@ -1391,6 +1391,8 @@ int enb_agent_register_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) { xface->enb_agent_schedule_ue_spec = schedule_ue_spec_remote; xface->enb_agent_get_pending_dl_mac_config = enb_agent_get_pending_dl_mac_config; xface->enb_agent_notify_ue_state_change = enb_agent_ue_state_change; + + xface->dl_scheduler_loaded_lib = NULL; mac_agent_registered[mod_id] = 1; agent_mac_xface[mod_id] = xface; @@ -1408,6 +1410,8 @@ int enb_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) { xface->enb_agent_get_pending_dl_mac_config = NULL; xface->enb_agent_notify_ue_state_change = NULL; + xface->dl_scheduler_loaded_lib = NULL; + mac_agent_registered[mod_id] = 0; agent_mac_xface[mod_id] = NULL; diff --git a/openair2/ENB_APP/enb_agent_mac_defs.h b/openair2/ENB_APP/enb_agent_mac_defs.h index c5a3204f0c..1511ee7262 100644 --- a/openair2/ENB_APP/enb_agent_mac_defs.h +++ b/openair2/ENB_APP/enb_agent_mac_defs.h @@ -74,6 +74,8 @@ typedef struct { void (*enb_agent_notify_ue_state_change)(mid_t mod_id, uint32_t rnti, uint32_t state_change); + + void *dl_scheduler_loaded_lib; /*TODO: Fill in with the rest of the MAC layer technology specific callbacks (UL/DL scheduling, RACH info etc)*/ } AGENT_MAC_xface; diff --git a/openair2/ENB_APP/enb_agent_mac_internal.c b/openair2/ENB_APP/enb_agent_mac_internal.c index c3cc584bcd..aa7482bd90 100644 --- a/openair2/ENB_APP/enb_agent_mac_internal.c +++ b/openair2/ENB_APP/enb_agent_mac_internal.c @@ -34,6 +34,9 @@ * \version 0.1 */ +#include <string.h> +#include <dlfcn.h> + #include "enb_agent_mac_internal.h" Protocol__ProgranMessage * enb_agent_generate_diff_mac_stats_report(Protocol__ProgranMessage *new_message, @@ -558,3 +561,235 @@ Protocol__PrpNoiseInterferenceReport * copy_noise_inter_report(Protocol__PrpNois error: return NULL; } + + +int parse_mac_config(mid_t mod_id, yaml_parser_t *parser) { + + yaml_event_t event; + + int done = 0; + + int sequence_started = 0; + int mapping_started = 0; + + while (!done) { + + if (!yaml_parser_parse(parser, &event)) + goto error; + + switch (event.type) { + case YAML_SEQUENCE_START_EVENT: + LOG_I(ENB_APP, "A sequence just started as expected\n"); + sequence_started = 1; + break; + case YAML_SEQUENCE_END_EVENT: + LOG_I(ENB_APP, "A sequence ended\n"); + sequence_started = 0; + break; + case YAML_MAPPING_START_EVENT: + if (!sequence_started) { + goto error; + } + LOG_I(ENB_APP, "A mapping started\n"); + mapping_started = 1; + break; + case YAML_MAPPING_END_EVENT: + if (!mapping_started) { + goto error; + } + LOG_I(ENB_APP, "A mapping ended\n"); + mapping_started = 0; + break; + case YAML_SCALAR_EVENT: + if (!mapping_started) { + goto error; + } + // Check the types of subsystems offered and handle their values accordingly + if (strcmp(event.data.scalar.value, "dl_scheduler") == 0) { + LOG_I(ENB_APP, "This is for the dl_scheduler subsystem\n"); + // Call the proper handler + if (parse_dl_scheduler_config(mod_id, parser) == -1) { + LOG_I(ENB_APP, "An error occured\n"); + goto error; + } + } else if (strcmp(event.data.scalar.value, "ul_scheduler") == 0) { + // Call the proper handler + LOG_I(ENB_APP, "This is for the ul_scheduler subsystem\n"); + goto error; + // TODO + } else if (strcmp(event.data.scalar.value, "ra_scheduler") == 0) { + // Call the proper handler + // TODO + } else if (strcmp(event.data.scalar.value, "page_scheduler") == 0) { + // Call the proper handler + // TODO + } else { + // Unknown subsystem + goto error; + } + break; + default: // We expect nothing else at this level of the hierarchy + goto error; + } + + done = (event.type == YAML_SEQUENCE_END_EVENT); + + yaml_event_delete(&event); + + } + + return 0; + + error: + yaml_event_delete(&event); + return -1; + +} + +int parse_dl_scheduler_config(mid_t mod_id, yaml_parser_t *parser) { + + yaml_event_t event; + + int done = 0; + int mapping_started = 0; + + while (!done) { + + if (!yaml_parser_parse(parser, &event)) + goto error; + + switch (event.type) { + // We are expecting a mapping (behavior and parameters) + case YAML_MAPPING_START_EVENT: + LOG_D(ENB_APP, "The mapping of the subsystem started\n"); + mapping_started = 1; + break; + case YAML_MAPPING_END_EVENT: + LOG_D(ENB_APP, "The mapping of the subsystem ended\n"); + mapping_started = 0; + break; + case YAML_SCALAR_EVENT: + if (!mapping_started) { + goto error; + } + // Check what key needs to be set + if (strcmp(event.data.scalar.value, "behavior") == 0) { + LOG_D(ENB_APP, "Time to set the behavior attribute\n"); + yaml_event_delete(&event); + if (!yaml_parser_parse(parser, &event)) { + goto error; + } + if (event.type == YAML_SCALAR_EVENT) { + if (load_dl_scheduler_function(mod_id, event.data.scalar.value) == -1) { + goto error; + } + } else { + goto error; + } + } else if (strcmp(event.data.scalar.value, "parameters") == 0) { + LOG_D(ENB_APP, "Now it is time to set the parameters for this subsystem\n"); + if (parse_dl_scheduler_parameters(mod_id, parser) == -1) { + goto error; + } + } + break; + default: + goto error; + } + + done = (event.type == YAML_MAPPING_END_EVENT); + yaml_event_delete(&event); + } + + return 0; + + error: + yaml_event_delete(&event); + return -1; +} + +int parse_dl_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser) { + yaml_event_t event; + + void *param; + + int done = 0; + int mapping_started = 0; + + while (!done) { + + if (!yaml_parser_parse(parser, &event)) + goto error; + + switch (event.type) { + // We are expecting a mapping of parameters + case YAML_MAPPING_START_EVENT: + LOG_D(ENB_APP, "The mapping of the parameters started\n"); + mapping_started = 1; + break; + case YAML_MAPPING_END_EVENT: + LOG_D(ENB_APP, "The mapping of the parameters ended\n"); + mapping_started = 0; + break; + case YAML_SCALAR_EVENT: + if (!mapping_started) { + goto error; + } + // Check what key needs to be set + if (mac_agent_registered[mod_id]) { + LOG_D(ENB_APP, "Setting parameter %s\n", event.data.scalar.value); + param = dlsym(agent_mac_xface[mod_id]->dl_scheduler_loaded_lib, + event.data.scalar.value); + if (param == NULL) { + goto error; + } + apply_parameter_modification(param, parser); + } else { + goto error; + } + break; + default: + goto error; + } + + done = (event.type == YAML_MAPPING_END_EVENT); + yaml_event_delete(&event); + } + + return 0; + + error: + yaml_event_delete(&event); + return -1; +} + +int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { + void *lib; + + char lib_name[120]; + char target[512]; + sprintf(lib_name, sizeof(lib_name), "/%s.so", function_name); + strcpy(target, local_cache); + strcat(target, lib_name); + + lib = dlopen(target, RTLD_NOW); + if (lib == NULL) { + goto error; + } + + void *loaded_scheduler = dlsym(lib, function_name); + if (loaded_scheduler) { + if (mac_agent_registered[mod_id]) { + agent_mac_xface[mod_id]->enb_agent_schedule_ue_spec = loaded_scheduler; + dlclose(agent_mac_xface[mod_id]->dl_scheduler_loaded_lib); + agent_mac_xface[mod_id]->dl_scheduler_loaded_lib = lib; + LOG_D(ENB_APP, "Delegated control for DL UE scheduler succesfully\n"); + } + } + + return 0; + + error: + return -1; + +} diff --git a/openair2/ENB_APP/enb_agent_mac_internal.h b/openair2/ENB_APP/enb_agent_mac_internal.h index 394d3e7730..4a76f0ed38 100644 --- a/openair2/ENB_APP/enb_agent_mac_internal.h +++ b/openair2/ENB_APP/enb_agent_mac_internal.h @@ -39,9 +39,11 @@ #include <pthread.h> +#include <yaml.h> + #include "enb_agent_mac.h" #include "enb_agent_common.h" - +#include "enb_agent_defs.h" /*This will be used for producing continuous status updates for the MAC *Needs to be thread-safe @@ -98,4 +100,15 @@ int compare_ue_stats_reports(Protocol__PrpUeStatsReport *rep1, int compare_cell_stats_reports(Protocol__PrpCellStatsReport *rep1, Protocol__PrpCellStatsReport *rep2); + +/* Functions for parsing the MAC agent policy reconfiguration command */ + +int parse_mac_config(mid_t mod_id, yaml_parser_t *parser); + +int parse_dl_scheduler_config(mid_t mod_id, yaml_parser_t *parser); + +int parse_dl_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser); + +int load_dl_scheduler_function(mid_t mod_id, const char *function_name); + #endif /*ENB_AGENT_MAC_INTERNAL_H_*/ diff --git a/openair2/LAYER2/MAC/eNB_agent_scheduler_dlsch_ue_remote.c b/openair2/LAYER2/MAC/eNB_agent_scheduler_dlsch_ue_remote.c index ad8b130584..d8d2373332 100644 --- a/openair2/LAYER2/MAC/eNB_agent_scheduler_dlsch_ue_remote.c +++ b/openair2/LAYER2/MAC/eNB_agent_scheduler_dlsch_ue_remote.c @@ -37,6 +37,8 @@ */ +#include "enb_agent_common_internal.h" + #include "eNB_agent_scheduler_dlsch_ue_remote.h" #include "LAYER2/MAC/defs.h" @@ -46,9 +48,25 @@ struct DlMacConfigHead queue_head; int queue_initialized = 0; +//uint32_t skip_subframe = 1; +//uint32_t period = 10; +//uint32_t sched [] = {1, 2, 3}; + void schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag, Protocol__ProgranMessage **dl_info) { + + //if ((subframe == skip_subframe) && (frame % period == 0)) { + // LOG_I(MAC, "Will skip subframe %d %d\n", subframe, frame); + // for (int i = 0; i < 3; i++) { + // LOG_I(MAC, "%d\n", sched[i]); + // } + //} + + /* if (frame == 500 && subframe == 1) { */ + /* char policy[] = "rrc: \n - ul_scheduler: \n behavior : tester_function\n parameters:\n period: !!int 3\nmac: \n - dl_scheduler: \n parameters: \n period : !!int 40\n skip_subframe : !!int 3\n sched : [!!int 4, !!int 5, !!int 6]"; */ + /* apply_reconfiguration_policy(mod_id, policy, strlen(policy)); */ + /* } */ eNB_MAC_INST *eNB; -- GitLab