Files
openairinterface5g/openair2/ENB_APP/flexran_agent_common_internal.c
T

571 lines
15 KiB
C

/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file flexran_agent_common_internal.c
* \brief internal functions for common message primitves and utilities
* \author Xenofon Foukas and N. Nikaein
* \date 2017
* \version 0.1
*/
#include <stdlib.h>
#include <string.h>
#include "flexran_agent_common_internal.h"
#include "flexran_agent_mac_internal.h"
#include "enb_app.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;
LOG_I(ENB_APP, "Time to apply a new policy \n");
yaml_parser_initialize(&parser);
yaml_parser_set_input_string(&parser, (unsigned char *) policy, strlen(policy));
while (!done) {
if (!yaml_parser_parse(&parser, &event))
goto error;
switch (event.type) {
case YAML_STREAM_START_EVENT:
break;
case YAML_STREAM_END_EVENT:
break;
case YAML_DOCUMENT_START_EVENT:
break;
case YAML_DOCUMENT_END_EVENT:
break;
case YAML_MAPPING_START_EVENT:
break;
case YAML_MAPPING_END_EVENT:
break;
case YAML_SCALAR_EVENT:
// Check the system name and call the proper handler
// Check the system name and call the proper handler
if (strcmp((char *) event.data.scalar.value, "enb") == 0) {
LOG_I(ENB_APP, "This is intended for the enb system\n");
// Call the enb handler
if (parse_enb_id(mod_id, &parser) == -1) {
LOG_E(ENB_APP, "cannot parse data for eNB\n");
goto error;
} else { // succeful parse and setting
handle_reconfiguration(mod_id);
}
} else if (strcmp((char *) 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((char *) 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((char *) 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((char *) 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 parse_enb_id(mid_t mod_id, yaml_parser_t *parser) {
yaml_event_t event;
char *endptr;
// int is_array;
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_SEQUENCE_START_EVENT:
// is_array = 1;
break;
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
// use eNB egistered
if (flexran_agent_get_mac_xface(mod_id)) {
LOG_I(ENB_APP, "Setting parameter for eNB %s\n", event.data.scalar.value);
if (strcmp((char *) event.data.scalar.tag, YAML_INT_TAG) == 0) { // if int
if ((strtol((char *) event.data.scalar.value, &endptr, 10))== mod_id ) { // enb_id == mod_id: right enb instance to be configured
if (parse_enb_config_parameters(mod_id, parser) == -1) {
goto error;
}
}
else{
goto error; // not the expected type
}
}
}
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_enb_config_parameters(mid_t mod_id, yaml_parser_t *parser) {
yaml_event_t event;
char *endptr;
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 (strcmp((char *) event.data.scalar.value, "dl_freq") == 0) {
if (!yaml_parser_parse(parser, &event))
goto error;
flexran_agent_set_operating_dl_freq(mod_id,
0,
strtol((char *) event.data.scalar.value, &endptr, 10));
LOG_I(ENB_APP, "Setting dl_freq to %s\n", event.data.scalar.value);
} else if (strcmp((char *) event.data.scalar.value, "ul_freq_offset") == 0) {
if (!yaml_parser_parse(parser, &event))
goto error;
flexran_agent_set_operating_ul_freq(mod_id,
0,
strtol((char *) event.data.scalar.value, &endptr, 10));
LOG_I(ENB_APP, "Setting ul_freq_offset to %s\n", event.data.scalar.value);
} else if (strcmp((char *) event.data.scalar.value, "bandwidth") == 0) {
if (!yaml_parser_parse(parser, &event))
goto error;
flexran_agent_set_operating_bandwidth(mod_id,
0,
strtol((char *) event.data.scalar.value, &endptr, 10));
LOG_I(ENB_APP, "Setting bandwidth to %s\n", event.data.scalar.value);
} else if (strcmp((char *) event.data.scalar.value, "frame_type") == 0) {
if (!yaml_parser_parse(parser, &event))
goto error;
flexran_agent_set_operating_frame_type (mod_id,
0,
strtol((char *) event.data.scalar.value, &endptr, 10));
LOG_I(ENB_APP, "Setting frame_type to %s\n", event.data.scalar.value);
}else { // not supported tag
LOG_E(FLEXRAN_AGENT, "Unsupported tag %s\n", event.data.scalar.value);
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_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;
}
default:
break;
}
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((char *) 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((char *) 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;
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((char *) event.data.scalar.tag, YAML_INT_TAG) == 0) ||
(strcmp((char *) event.data.scalar.tag, YAML_FLOAT_TAG) == 0) ||
(strcmp((char *) event.data.scalar.tag, YAML_STR_TAG) == 0) ||
(strcmp((char *) 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((char *) event.data.scalar.tag, YAML_INT_TAG) == 0) {
((int *) parameter)[i] = strtol((char *) event.data.scalar.value, &endptr, 10);
} else if (strcmp((char *) event.data.scalar.tag, YAML_FLOAT_TAG) == 0) {
((float *) parameter)[i] = strtof((char *) event.data.scalar.value, &endptr);
} else if (strcmp((char *) event.data.scalar.tag, YAML_STR_TAG) == 0) {
strncpy(&((char *) parameter)[i], (char *) event.data.scalar.value, event.data.scalar.length);
} else if (strcmp((char *) event.data.scalar.tag, YAML_BOOL_TAG) == 0) {
if (strcmp((char *) 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;
}
void initiate_soft_restart(module_id_t mod_id, Protocol__FlexCellConfig *c)
{
const uint8_t cc_id = 0;
if (c->has_eutra_band) {
flexran_agent_set_operating_eutra_band(mod_id, cc_id, c->eutra_band);
LOG_I(ENB_APP, "Setting eutra_band to %d\n", c->eutra_band);
}
if (c->has_dl_freq && c->has_ul_freq) {
flexran_agent_set_operating_dl_freq(mod_id, cc_id, c->dl_freq);
LOG_I(ENB_APP, "Setting dl_freq to %d\n", c->dl_freq);
int32_t ul_freq_offset = c->ul_freq - c->dl_freq;
flexran_agent_set_operating_ul_freq(mod_id, cc_id, ul_freq_offset);
LOG_I(ENB_APP, "Setting ul_freq to %d\n", c->ul_freq);
}
if (c->has_dl_bandwidth) {
flexran_agent_set_operating_bandwidth(mod_id, cc_id, c->dl_bandwidth);
LOG_I(ENB_APP, "Setting bandwidth to %d\n", c->dl_bandwidth);
if (c->has_ul_bandwidth && c->ul_bandwidth != c->dl_bandwidth)
LOG_W(ENB_APP, "UL/DL bandwidth mismatch, applied DL bandwidth\n");
} else if (c->has_ul_bandwidth) {
flexran_agent_set_operating_bandwidth(mod_id, cc_id, c->ul_bandwidth);
LOG_I(ENB_APP, "Setting bandwidth to %d\n", c->ul_bandwidth);
}
MessageDef *msg;
msg = itti_alloc_new_message(TASK_FLEXRAN_AGENT, 0, SOFT_RESTART_MESSAGE);
itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}