Added basic support for policy reconfiguration using yaml parser
This commit is contained in:
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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_*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user