/* * 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.0 (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" extern volatile int node_control_state; 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) { goto error; } else { // succeful parse and setting node_control_state= ENB_NORMAL_OPERATION; LOG_I(ENB_APP, "Successful parsed config for enb system, entering normal state\n"); } } 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 (mac_agent_registered[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 goto error; } break; default: goto error; } done = (event.type == YAML_MAPPING_END_EVENT); yaml_event_delete(&event); } /* reflect in RAN API */ flexran_set_enb_vars(mod_id, RAN_LTE_OAI); 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; }