Commit 639d957e authored by hardy's avatar hardy

Merge remote-tracking branch 'origin/flexran-apps' into integration_2020_wk42

parents 13cf8284 8cb530d2
...@@ -1095,9 +1095,22 @@ add_library(FLEXRAN_AGENT ...@@ -1095,9 +1095,22 @@ add_library(FLEXRAN_AGENT
${OPENAIR2_DIR}/ENB_APP/flexran_agent_async.c ${OPENAIR2_DIR}/ENB_APP/flexran_agent_async.c
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c
${OPENAIR2_DIR}/ENB_APP/flexran_agent_app.c
) )
add_dependencies(FLEXRAN_AGENT rrc_flag) add_dependencies(FLEXRAN_AGENT rrc_flag)
set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT) set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT)
add_library(flapp_sample SHARED
${OPENAIR2_DIR}/ENB_APP/flexran_apps/sample.c
)
set_target_properties(flapp_sample PROPERTIES C_VISIBILITY_PRESET hidden)
add_library(flapp_imsi SHARED
${OPENAIR2_DIR}/ENB_APP/flexran_apps/imsi.c
)
set_target_properties(flapp_imsi PROPERTIES C_VISIBILITY_PRESET hidden)
add_custom_target(flapp_all DEPENDS
flapp_sample
flapp_imsi
)
#include_directories(${OPENAIR2_DIR}/ENB_APP) #include_directories(${OPENAIR2_DIR}/ENB_APP)
set(PROTOBUF_LIB "protobuf-c") set(PROTOBUF_LIB "protobuf-c")
......
...@@ -39,6 +39,12 @@ ...@@ -39,6 +39,12 @@
// for flexran_agent_get_mac_xface() // for flexran_agent_get_mac_xface()
#include "flexran_agent_extern.h" #include "flexran_agent_extern.h"
/* Type for a list of shared objects used in the user plane (schedulers) */
typedef struct flexran_agent_so_handle_s {
char *name; // name of the object
void *dl_handle; // handle of associated objects
SLIST_ENTRY (flexran_agent_so_handle_s) entries;
} flexran_agent_so_handle_t;
/* Initialization function for the agent structures etc */ /* Initialization function for the agent structures etc */
void flexran_agent_init_mac_agent(mid_t mod_id); void flexran_agent_init_mac_agent(mid_t mod_id);
...@@ -117,7 +123,9 @@ void flexran_agent_slice_update(mid_t mod_id); ...@@ -117,7 +123,9 @@ void flexran_agent_slice_update(mid_t mod_id);
/* marks slice_config so that it can be applied later. Takes ownership of the /* marks slice_config so that it can be applied later. Takes ownership of the
* FlexSliceConfig message */ * FlexSliceConfig message */
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice); void prepare_update_slice_config(mid_t mod_id,
Protocol__FlexSliceConfig **slice,
int request_objects);
/* inserts a new ue_config into the structure keeping ue to slice association /* inserts a new ue_config into the structure keeping ue to slice association
* updates and marks so it can be applied. Takes ownership of the FlexUeConfig message */ * updates and marks so it can be applied. Takes ownership of the FlexUeConfig message */
...@@ -127,4 +135,13 @@ void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_con ...@@ -127,4 +135,13 @@ void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_con
* flexran_agent_fill_mac_cell_config() */ * flexran_agent_fill_mac_cell_config() */
void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf); void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf);
/* information about a new (potentially relevant) control delegation message */
void flexran_agent_mac_inform_delegation(mid_t mod_id,
Protocol__FlexControlDelegation *cdm);
/* fill the enb_config_reply with the shared objects in use by the MAC sublayer */
void flexran_agent_mac_fill_loaded_mac_objects(
mid_t mod_id,
Protocol__FlexEnbConfigReply *reply);
#endif #endif
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
#include "flexran_agent_mac_internal.h" #include "flexran_agent_mac_internal.h"
#include "flexran_agent_mac_slice_verification.h" #include "flexran_agent_mac_slice_verification.h"
extern SLIST_HEAD(flexran_so_handle,
flexran_agent_so_handle_s) flexran_handles[NUM_MAX_ENB];
Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message, Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message,
Protocol__FlexranMessage *old_message) { Protocol__FlexranMessage *old_message) {
...@@ -1025,6 +1028,19 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { ...@@ -1025,6 +1028,19 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
} }
void *search_so(mid_t mod_id, char *name) {
if (!name) // no name -> nothing to return, so use NULL for executable
return NULL;
if (dlsym(NULL, name)) // found it in executable
return NULL;
flexran_agent_so_handle_t *so = NULL;
SLIST_FOREACH(so, &flexran_handles[mod_id], entries) {
if (strcmp(so->name, name) == 0)
return so->dl_handle;
}
return NULL;
}
void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) { void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) {
if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET
&& !s->label && !s->scheduler) { && !s->label && !s->scheduler) {
...@@ -1033,8 +1049,12 @@ void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) { ...@@ -1033,8 +1049,12 @@ void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) {
if (!rc) if (!rc)
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
} else { } else {
LOG_I(FLEXRAN_AGENT, "updating DL slice ID %d\n", s->id); void *lib = search_so(mod_id, s->scheduler);
const int rc = flexran_create_dl_slice(mod_id, s); LOG_I(FLEXRAN_AGENT,
"updating DL slice ID %d (library handle %p)\n",
s->id,
lib);
const int rc = flexran_create_dl_slice(mod_id, s, lib);
if (rc < 0) if (rc < 0)
LOG_W(FLEXRAN_AGENT, LOG_W(FLEXRAN_AGENT,
"error while update slice ID %d: flexran_create_dl_slice() -> %d\n", "error while update slice ID %d: flexran_create_dl_slice() -> %d\n",
...@@ -1050,8 +1070,12 @@ void update_or_remove_ul(mid_t mod_id, Protocol__FlexSlice *s) { ...@@ -1050,8 +1070,12 @@ void update_or_remove_ul(mid_t mod_id, Protocol__FlexSlice *s) {
if (!rc) if (!rc)
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
} else { } else {
LOG_I(FLEXRAN_AGENT, "updating UL slice ID %d\n", s->id); void *lib = search_so(mod_id, s->scheduler);
const int rc = flexran_create_ul_slice(mod_id, s); LOG_I(FLEXRAN_AGENT,
"updating UL slice ID %d (library handle %p)\n",
s->id,
lib);
const int rc = flexran_create_ul_slice(mod_id, s, lib);
if (rc < 0) if (rc < 0)
LOG_W(FLEXRAN_AGENT, LOG_W(FLEXRAN_AGENT,
"error while updating slice ID %d: flexran_create_ul_slice() -> %d)\n", "error while updating slice ID %d: flexran_create_ul_slice() -> %d)\n",
...@@ -1099,8 +1123,12 @@ void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *d ...@@ -1099,8 +1123,12 @@ void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *d
LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n");
return; return;
} }
LOG_I(FLEXRAN_AGENT, "loading DL new scheduling algorithm '%s'\n", dl->scheduler); void *lib = search_so(mod_id, dl->scheduler);
const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler); LOG_I(FLEXRAN_AGENT,
"loading DL new scheduling algorithm '%s' (library handle %p)\n",
dl->scheduler,
lib);
const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler, lib);
if (rc < 0) { if (rc < 0) {
LOG_E(FLEXRAN_AGENT, LOG_E(FLEXRAN_AGENT,
"error while updating scheduling algorithm: " "error while updating scheduling algorithm: "
...@@ -1147,8 +1175,12 @@ void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *u ...@@ -1147,8 +1175,12 @@ void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *u
LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n");
return; return;
} }
LOG_I(FLEXRAN_AGENT, "loading new UL scheduling algorithm '%s'\n", ul->scheduler); void *lib = search_so(mod_id, ul->scheduler);
const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler); LOG_I(FLEXRAN_AGENT,
"loading new UL scheduling algorithm '%s' (library handle %p)\n",
ul->scheduler,
lib);
const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler, lib);
if (rc < 0) { if (rc < 0) {
LOG_E(FLEXRAN_AGENT, LOG_E(FLEXRAN_AGENT,
"error while updating scheduling algorithm: " "error while updating scheduling algorithm: "
......
...@@ -3,4 +3,25 @@ package protocol; ...@@ -3,4 +3,25 @@ package protocol;
enum flex_control_delegation_type { enum flex_control_delegation_type {
FLCDT_MAC_DL_UE_SCHEDULER = 1; // DL UE scheduler delegation FLCDT_MAC_DL_UE_SCHEDULER = 1; // DL UE scheduler delegation
FLCDT_AGENT_CONTROL_APP = 2; // Generic control application
}
message flex_agent_reconfiguration_system {
optional string system = 1;
repeated flex_agent_reconfiguration_subsystem subsystems = 2;
}
message flex_agent_reconfiguration_subsystem {
optional string name = 1; // Name of the object (app name or user plane object)
optional string behavior = 2; // For an app: a callback in a shared library. For any other subsystem: an object name (shared library) with defined syntax.
map<string, flex_agent_reconfiguration_param> params = 3; // Param configurations depending on callback/shared library above.
}
message flex_agent_reconfiguration_param {
oneof param {
int32 integer = 1;
float floating = 2;
bool boolean = 3;
string str = 4;
}
} }
...@@ -7,6 +7,7 @@ import "time_common.proto"; ...@@ -7,6 +7,7 @@ import "time_common.proto";
import "config_messages.proto"; import "config_messages.proto";
import "controller_commands.proto"; import "controller_commands.proto";
import "config_common.proto"; import "config_common.proto";
import "control_delegation.proto";
message flexran_message { message flexran_message {
optional flexran_direction msg_dir = 100; optional flexran_direction msg_dir = 100;
...@@ -32,6 +33,7 @@ message flexran_message { ...@@ -32,6 +33,7 @@ message flexran_message {
flex_ul_mac_config ul_mac_config_msg = 19; flex_ul_mac_config ul_mac_config_msg = 19;
flex_disconnect disconnect_msg = 20; flex_disconnect disconnect_msg = 20;
flex_ho_command ho_command_msg = 21; flex_ho_command ho_command_msg = 21;
flex_control_delegation_request control_del_req_msg = 22;
} }
} }
...@@ -157,6 +159,8 @@ message flex_enb_config_reply { ...@@ -157,6 +159,8 @@ message flex_enb_config_reply {
repeated flex_cell_config cell_config = 3; repeated flex_cell_config cell_config = 3;
optional uint32 device_spec = 4; optional uint32 device_spec = 4;
optional flex_s1ap_config s1ap = 5; optional flex_s1ap_config s1ap = 5;
repeated string loadedApps = 6;
repeated string loadedMacObjects = 7;
} }
message flex_ue_config_request { message flex_ue_config_request {
...@@ -225,11 +229,17 @@ message flex_ue_state_change { ...@@ -225,11 +229,17 @@ message flex_ue_state_change {
message flex_control_delegation { message flex_control_delegation {
optional flex_header header = 1; optional flex_header header = 1;
optional uint32 delegation_type = 2; // Bitmap of FLCDT_* flags optional flex_control_delegation_type delegation_type = 2; // The delegated object type, decides about further processing
optional bytes payload = 3; // Byte array of shared lib containing the delegated functions optional bytes payload = 3; // Byte array of shared lib containing the delegated functions
optional string name = 4; // The delegated functions names ordered based on bitmap flags optional string name = 4; // The delegated functions names ordered based on bitmap flags
} }
message flex_control_delegation_request {
optional flex_header header = 1;
optional flex_control_delegation_type delegation_type = 2;
optional string name = 4;
}
// //
// Agent reconfiguration message // Agent reconfiguration message
// //
...@@ -237,6 +247,7 @@ message flex_control_delegation { ...@@ -237,6 +247,7 @@ message flex_control_delegation {
message flex_agent_reconfiguration { message flex_agent_reconfiguration {
optional flex_header header = 1; optional flex_header header = 1;
optional string policy = 2; // The policy changes using YAML syntax in string format optional string policy = 2; // The policy changes using YAML syntax in string format
repeated flex_agent_reconfiguration_system systems = 3; // The policy changes.
} }
// Extensions of the echo request and reply // Extensions of the echo request and reply
......
...@@ -44,5 +44,6 @@ enum flex_type { ...@@ -44,5 +44,6 @@ enum flex_type {
FLPT_RECONFIGURE_AGENT = 16; FLPT_RECONFIGURE_AGENT = 16;
FLPT_RRC_TRIGGERING = 17; FLPT_RRC_TRIGGERING = 17;
FLPT_UL_MAC_CONFIG = 18; FLPT_UL_MAC_CONFIG = 18;
FLPT_DELEGATE_REQUEST = 22;
} }
...@@ -115,7 +115,6 @@ error: ...@@ -115,7 +115,6 @@ error:
return NULL; return NULL;
} }
int channel_container_init = 0; int channel_container_init = 0;
int flexran_agent_start(mid_t mod_id) int flexran_agent_start(mid_t mod_id)
{ {
...@@ -233,6 +232,9 @@ int flexran_agent_start(mid_t mod_id) ...@@ -233,6 +232,9 @@ int flexran_agent_start(mid_t mod_id)
agent_task_created = 1; agent_task_created = 1;
} }
/* Init the app sublayer */
flexran_agent_app_init(mod_id);
pthread_mutex_init(&flexran->mutex_node_ctrl, NULL); pthread_mutex_init(&flexran->mutex_node_ctrl, NULL);
pthread_cond_init(&flexran->cond_node_ctrl, NULL); pthread_cond_init(&flexran->cond_node_ctrl, NULL);
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "flexran_agent_rrc.h" #include "flexran_agent_rrc.h"
#include "flexran_agent_pdcp.h" #include "flexran_agent_pdcp.h"
#include "flexran_agent_s1ap.h" #include "flexran_agent_s1ap.h"
#include "flexran_agent_app.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "assertions.h" #include "assertions.h"
......
/*
* 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_app.c
* \brief CM for handling of applications
* \author Robert Schmidt
* \date 2020
* \version 0.1
*/
#include "flexran_agent_app.h"
#include "queue.h"
#include <dlfcn.h>
/* app definition */
typedef struct flexran_agent_app_internal_s {
char *name;
void *dl_handle;
flexran_agent_app_t *app;
SLIST_ENTRY (flexran_agent_app_internal_s) entries;
} flexran_agent_app_internal_t;
/* a list of all apps */
SLIST_HEAD(flexran_apps_s, flexran_agent_app_internal_s) flexran_apps[NUM_MAX_ENB];
void flexran_agent_app_init(mid_t mod_id) {
//flexran_apps[mod_id] = SLIST_HEAD_INITIALIZER(flexran_apps[mod_id]);
SLIST_INIT(&flexran_apps[mod_id]);
}
int flexran_agent_start_app_direct(mid_t mod_id, flexran_agent_app_t *app, char *name) {
app->start(mod_id, NULL, 0);
flexran_agent_app_internal_t *so = malloc(sizeof(flexran_agent_app_internal_t));
DevAssert(so);
so->name = strdup(name);
DevAssert(so->name);
so->dl_handle = NULL;
so->app = app;
SLIST_INSERT_HEAD(&flexran_apps[mod_id], so, entries);
return 0;
}
int flexran_agent_start_app(mid_t mod_id, Protocol__FlexAgentReconfigurationSubsystem *sub) {
char s[512];
int rc = flexran_agent_map_name_to_delegated_object(mod_id, sub->name, s, 512);
if (rc < 0) {
LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", sub->name);
return -1;
}
void *h = dlopen(s, RTLD_NOW);
if (!h) {
LOG_E(FLEXRAN_AGENT, "cannot open shared object %s\n", s);
return -1;
}
flexran_agent_app_t *app = dlsym(h, "app");
if (!app) {
LOG_E(FLEXRAN_AGENT, "cannot locate app inside of shared object %s\n", s);
return -1;
}
app->start(mod_id, sub->params, sub->n_params);
flexran_agent_app_internal_t *so = malloc(sizeof(flexran_agent_app_internal_t));
DevAssert(so);
so->name = strdup(sub->name);
DevAssert(so->name);
so->dl_handle = h;
so->app = app;
SLIST_INSERT_HEAD(&flexran_apps[mod_id], so, entries);
return 0;
}
int flexran_agent_stop_app(mid_t mod_id, char *name) {
flexran_agent_app_internal_t *so = NULL;
SLIST_FOREACH(so, &flexran_apps[mod_id], entries) {
if (strcmp(so->name, name) == 0) {
LOG_I(FLEXRAN_AGENT, "application %s seems to be running\n", name);
break;
}
}
if (!so) {
LOG_E(FLEXRAN_AGENT, "no such application %s found\n", name);
return -1;
}
flexran_agent_app_t *app = so->app;
app->stop(mod_id);
SLIST_REMOVE(&flexran_apps[mod_id], so, flexran_agent_app_internal_s, entries);
free(so->name);
if (so->dl_handle)
dlclose(so->dl_handle);
free(so);
so = NULL;
return 0;
}
int flexran_agent_reconfig_app(
mid_t mod_id,
Protocol__FlexAgentReconfigurationSubsystem *sub)
{
flexran_agent_app_internal_t *so = NULL;
SLIST_FOREACH(so, &flexran_apps[mod_id], entries) {
if (strcmp(so->name, sub->name) == 0) {
LOG_I(FLEXRAN_AGENT, "application %s is running\n", sub->name);
break;
}
}
if (!so) {
LOG_E(FLEXRAN_AGENT, "no such application %s found\n", sub->name);
return -1;
}
flexran_agent_app_t *app = so->app;
LOG_I(FLEXRAN_AGENT, "reconfiguring app %s\n", so->name);
app->reconfig(mod_id, sub->params, sub->n_params);
return 0;
}
int flexran_agent_custom_command_app(
mid_t mod_id,
Protocol__FlexAgentReconfigurationSubsystem *sub)
{
flexran_agent_app_internal_t *so = NULL;
SLIST_FOREACH(so, &flexran_apps[mod_id], entries) {
if (strcmp(so->name, sub->name) == 0) {
LOG_I(FLEXRAN_AGENT, "application %s is running\n", sub->name);
break;
}
}
if (!so) {
LOG_E(FLEXRAN_AGENT, "no such application %s found\n", sub->name);
return -1;
}
void (*cmd)(mid_t, Protocol__FlexAgentReconfigurationSubsystem *) = dlsym(so->dl_handle, sub->behavior);
if (!cmd) {
LOG_E(FLEXRAN_AGENT,
"cannot locate command %s inside of app %s\n",
sub->behavior,
so->name);
return -1;
}
LOG_I(FLEXRAN_AGENT,
"calling command %s inside of app %s\n",
sub->behavior,
so->name);
(*cmd)(mod_id, sub);
return 0;
}
void flexran_agent_handle_apps(
mid_t mod_id,
Protocol__FlexAgentReconfigurationSubsystem **subs,
int n_subs) {
for (int i = 0; i < n_subs; ++i) {
Protocol__FlexAgentReconfigurationSubsystem *s = subs[i];
if (strcmp(s->behavior, "start") == 0) {
int rc = flexran_agent_start_app(mod_id, s);
if (rc == 0)
LOG_I(FLEXRAN_AGENT, "application \"%s\" started\n", s->name);
} else if (strcmp(s->behavior, "stop") == 0) {
int rc = flexran_agent_stop_app(mod_id, s->name);
if (rc == 0)
LOG_I(FLEXRAN_AGENT, "application \"%s\" stopped\n", s->name);
} else if (strcmp(s->behavior, "reconfig") == 0) {
flexran_agent_reconfig_app(mod_id, s);
} else {
flexran_agent_custom_command_app(mod_id, s);
}
}
}
void flexran_agent_fill_loaded_apps(mid_t mod_id,
Protocol__FlexEnbConfigReply *reply) {
int n = 0;
flexran_agent_app_internal_t *so = NULL;
SLIST_FOREACH(so, &flexran_apps[mod_id], entries)
++n;
reply->n_loadedapps = n;
reply->loadedapps = calloc(n, sizeof(char *));
if (!reply->loadedapps) {
reply->n_loadedapps = 0;
return;
}
n = 0;
SLIST_FOREACH(so, &flexran_apps[mod_id], entries)
reply->loadedapps[n++] = so->name;
}
/*
* 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_app.h
* \brief Common app definitions
* \author Robert Schmidt
* \date 2020
* \version 0.1
*/
#ifndef BURST_ANALYSIS_LL_H_
#define BURST_ANALYSIS_LL_H_
#include "flexran_agent_common.h"
#include "flexran_agent_async.h"
#include "flexran_agent_extern.h"
#include "flexran_agent_timer.h"
#include "flexran_agent_defs.h"
#include "flexran_agent_net_comm.h"
#include "flexran_agent_ran_api.h"
#include "flexran_agent_phy.h"
#include "flexran_agent_mac.h"
#include "flexran_agent_rrc.h"
#include "flexran_agent_pdcp.h"
#include "flexran_agent_s1ap.h"
#include "common/utils/LOG/log.h"
#include "assertions.h"
/* App type: to be implemented by shared libraries */
typedef struct {
int (*start)(mid_t mod_id,
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
int n_p);
int (*reconfig)(mid_t mod_id,
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
int n_p);
int (* stop)(mid_t mod_id);
} flexran_agent_app_t;
/* FlexRAN agent app handling init */
void flexran_agent_app_init(mid_t mod_id);
/* Start an app from within the agent */
int flexran_agent_start_app_direct(mid_t mod_id, flexran_agent_app_t *app, char *name);
/* FlexRAN agent handler to setup/teardown apps */
void flexran_agent_handle_apps(
mid_t mod_id,
Protocol__FlexAgentReconfigurationSubsystem **subs,
int n_subs);
/* Fills the enb_config_reply with the currently loaded (started) apps */
void flexran_agent_fill_loaded_apps(mid_t mod_id,
Protocol__FlexEnbConfigReply *reply);
#endif
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <errno.h>
#include "flexran_agent_common.h" #include "flexran_agent_common.h"
#include "flexran_agent_common_internal.h" #include "flexran_agent_common_internal.h"
...@@ -39,6 +42,7 @@ ...@@ -39,6 +42,7 @@
#include "flexran_agent_mac.h" #include "flexran_agent_mac.h"
#include "flexran_agent_rrc.h" #include "flexran_agent_rrc.h"
#include "flexran_agent_s1ap.h" #include "flexran_agent_s1ap.h"
#include "flexran_agent_app.h"
//#include "PHY/extern.h" //#include "PHY/extern.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "flexran_agent_mac_internal.h" #include "flexran_agent_mac_internal.h"
...@@ -326,6 +330,12 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { ...@@ -326,6 +330,12 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
if (reply->s1ap) if (reply->s1ap)
flexran_agent_free_s1ap_cell_config(&reply->s1ap); flexran_agent_free_s1ap_cell_config(&reply->s1ap);
if (reply->loadedapps)
free(reply->loadedapps);
if (reply->loadedmacobjects)
free(reply->loadedmacobjects);
free(reply->cell_config); free(reply->cell_config);
free(reply); free(reply);
free(msg); free(msg);
...@@ -424,26 +434,65 @@ long timer_end(struct timespec start_time) { ...@@ -424,26 +434,65 @@ long timer_end(struct timespec start_time) {
int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
Protocol__FlexControlDelegation *control_delegation_msg = input->control_delegation_msg; Protocol__FlexControlDelegation *control_delegation_msg = input->control_delegation_msg;
// struct timespec vartime = timer_start(); *msg = NULL;
//Write the payload lib into a file in the cache and load the lib
char lib_name[120];
char target[512]; char target[512];
snprintf(lib_name, sizeof(lib_name), "/%s.so", control_delegation_msg->name); int len = snprintf(target, sizeof(target), "%s/libflex.%s.so",
strcpy(target, RC.flexran[mod_id]->cache_name); RC.flexran[mod_id]->cache_name,
strcat(target, lib_name); control_delegation_msg->name);
FILE *f; if (len >= sizeof(target)) {
f = fopen(target, "wb"); LOG_E(FLEXRAN_AGENT, "target has been truncated, cannot write file name\n");
return 0;
if (f) { }
fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f);
fclose(f); if (control_delegation_msg->has_payload) {
/* use low-level API: check whether exists while creating so we can abort if
* it exists to not overwrite anything */
int fd = open(target, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR);
if (fd >= 0) {
ssize_t l = write(fd,
control_delegation_msg->payload.data,
control_delegation_msg->payload.len);
close(fd);
if (l < control_delegation_msg->payload.len) {
LOG_E(FLEXRAN_AGENT,
"could not write complete control delegation to %s: only %ld out of "
"%ld bytes\n",
target,
l,
control_delegation_msg->payload.len);
return 0;
} else if (l < 0) {
LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n",
target, strerror(errno));
return 0;
}
LOG_I(FLEXRAN_AGENT, "wrote shared object %s\n", target);
} else {
if (errno == EEXIST) {
LOG_W(FLEXRAN_AGENT, "file %s already exists, remove it first\n", target);
} else {
LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n",
target, strerror(errno));
}
return 0;
}
} else { } else {
LOG_W(FLEXRAN_AGENT, "[%d] can not write control delegation data to %s\n", LOG_W(FLEXRAN_AGENT, "remove file %s\n", target);
mod_id, target); int rc = remove(target);
if (rc < 0)
LOG_E(FLEXRAN_AGENT, "cannot remove file %s: %s\n", target, strerror(errno));
}
if (control_delegation_msg->has_delegation_type
&& control_delegation_msg->delegation_type == PROTOCOL__FLEX_CONTROL_DELEGATION_TYPE__FLCDT_MAC_DL_UE_SCHEDULER
&& control_delegation_msg->header
&& control_delegation_msg->header->has_xid) {
/* Inform the MAC subsystem that a control delegation for it has arrived */
/* TODO this should be triggered by an agent reconfiguration? */
flexran_agent_mac_inform_delegation(mod_id, control_delegation_msg);
} }
// long time_elapsed_nanos = timer_end(vartime);
*msg = NULL;
return 0; return 0;
} }
...@@ -452,10 +501,44 @@ int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg) { ...@@ -452,10 +501,44 @@ int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg) {
return 0; return 0;
} }
int flexran_agent_map_name_to_delegated_object(mid_t mod_id, const char *name,
char *path, int maxlen) {
int len = snprintf(path, maxlen, "%s/libflex.%s.so",
RC.flexran[mod_id]->cache_name, name);
if (len >= maxlen) {
LOG_E(FLEXRAN_AGENT, "path has been truncated, cannot read object\n");
return -1;
}
struct stat buf;
int status = stat(path, &buf);
if (status < 0) {
LOG_E(FLEXRAN_AGENT, "Could not stat object %s: %s\n", path, strerror(errno));
return -1;
}
return 0;
}
int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
Protocol__FlexAgentReconfiguration *agent_reconfiguration_msg = input->agent_reconfiguration_msg; Protocol__FlexAgentReconfiguration *agent_reconfiguration_msg = input->agent_reconfiguration_msg;
apply_reconfiguration_policy(mod_id, agent_reconfiguration_msg->policy, strlen(agent_reconfiguration_msg->policy)); if (agent_reconfiguration_msg->policy) {
/* for compatibility: call old YAML configuration code, although we don't
* use it anymore */
apply_reconfiguration_policy(mod_id,
agent_reconfiguration_msg->policy,
strlen(agent_reconfiguration_msg->policy));
}
for (int i = 0; i < agent_reconfiguration_msg->n_systems; ++i) {
const Protocol__FlexAgentReconfigurationSystem *sys = agent_reconfiguration_msg->systems[i];
if (strcmp(sys->system, "app") == 0) {
flexran_agent_handle_apps(mod_id, sys->subsystems, sys->n_subsystems);
} else {
LOG_E(FLEXRAN_AGENT,
"unknown system name %s in flex_agent_reconfiguration message\n",
sys->system);
}
}
*msg = NULL; *msg = NULL;
return 0; return 0;
} }
...@@ -465,6 +548,15 @@ int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg) { ...@@ -465,6 +548,15 @@ int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg) {
return 0; return 0;
} }
int flexran_agent_destroy_control_delegation_request(Protocol__FlexranMessage *msg) {
if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DEL_REQ_MSG)
return -1;
free(msg->control_del_req_msg->header);
free(msg->control_del_req_msg->name);
free(msg);
return 0;
}
int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
xid_t xid; xid_t xid;
...@@ -750,6 +842,10 @@ int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__F ...@@ -750,6 +842,10 @@ int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__F
if (flexran_agent_get_s1ap_xface(mod_id)) if (flexran_agent_get_s1ap_xface(mod_id))
flexran_agent_fill_s1ap_cell_config(mod_id, &enb_config_reply_msg->s1ap); flexran_agent_fill_s1ap_cell_config(mod_id, &enb_config_reply_msg->s1ap);
flexran_agent_fill_loaded_apps(mod_id, enb_config_reply_msg);
flexran_agent_mac_fill_loaded_mac_objects(mod_id, enb_config_reply_msg);
*msg = malloc(sizeof(Protocol__FlexranMessage)); *msg = malloc(sizeof(Protocol__FlexranMessage));
if(*msg == NULL) { if(*msg == NULL) {
...@@ -880,7 +976,9 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot ...@@ -880,7 +976,9 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot
if (enb_config->n_cell_config > 0) { if (enb_config->n_cell_config > 0) {
if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) { if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) {
prepare_update_slice_config(mod_id, &enb_config->cell_config[0]->slice_config); prepare_update_slice_config(mod_id,
&enb_config->cell_config[0]->slice_config,
1 /* request objects if necessary */);
} }
if (enb_config->cell_config[0]->has_eutra_band if (enb_config->cell_config[0]->has_eutra_band
&& enb_config->cell_config[0]->has_dl_freq && enb_config->cell_config[0]->has_dl_freq
......
...@@ -131,11 +131,20 @@ int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg); ...@@ -131,11 +131,20 @@ int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg);
/* Control delegation message constructor and destructor */ /* Control delegation message constructor and destructor */
int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg); int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg);
/* Map a name from a control_delegation message to a file name. The function
* stat()s the file to check existence and returns the complete path name in
* path. The length in path needs to be maxlen, the maximum length the path may
* have. */
int flexran_agent_map_name_to_delegated_object(mid_t mod_id, const char *name,
char *path, int maxlen);
/* Policy reconfiguration message constructor and destructor */ /* Policy reconfiguration message constructor and destructor */
int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg); int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg);
/* Policy reconfiguration request message destructor */
int flexran_agent_destroy_control_delegation_request(Protocol__FlexranMessage *msg);
/* rrc triggering measurement message constructor and destructor */ /* rrc triggering measurement message constructor and destructor */
int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg); int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg);
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "flexran_agent_rrc.h" #include "flexran_agent_rrc.h"
#include "flexran_agent_pdcp.h" #include "flexran_agent_pdcp.h"
#include "flexran_agent_s1ap.h" #include "flexran_agent_s1ap.h"
#include "flexran_agent_app.h"
#include "flexran_agent_timer.h" #include "flexran_agent_timer.h"
#include "flexran_agent_ran_api.h" #include "flexran_agent_ran_api.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
...@@ -80,6 +81,11 @@ flexran_agent_message_destruction_callback message_destruction_callback[] = { ...@@ -80,6 +81,11 @@ flexran_agent_message_destruction_callback message_destruction_callback[] = {
flexran_agent_destroy_ue_state_change, flexran_agent_destroy_ue_state_change,
flexran_agent_destroy_control_delegation, flexran_agent_destroy_control_delegation,
flexran_agent_destroy_agent_reconfiguration, flexran_agent_destroy_agent_reconfiguration,
NULL, /* flex_rrc_triggering */
NULL, /* flex_ul_mac_config */
NULL, /* flex_disconnect */
NULL, /* flex_ho_command */
flexran_agent_destroy_control_delegation_request,
}; };
/* static const char *flexran_agent_direction2String[] = { */ /* static const char *flexran_agent_direction2String[] = { */
......
...@@ -3092,12 +3092,13 @@ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { ...@@ -3092,12 +3092,13 @@ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
return slices->s[idx]->id; return slices->s[idx]->id;
} }
void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { int flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
if (!mac_is_present(mod_id)) return; if (!mac_is_present(mod_id)) return 0;
int idx = flexran_find_dl_slice(mod_id, slice_id); int idx = flexran_find_dl_slice(mod_id, slice_id);
if (idx < 0) return; if (idx < 0) return 0;
pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
dl->move_UE(dl->slices, ue_id, idx); dl->move_UE(dl->slices, ue_id, idx);
return 1;
} }
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) {
...@@ -3108,15 +3109,16 @@ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { ...@@ -3108,15 +3109,16 @@ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) {
return slices->s[idx]->id; return slices->s[idx]->id;
} }
void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { int flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
if (!mac_is_present(mod_id)) return; if (!mac_is_present(mod_id)) return 0;
int idx = flexran_find_ul_slice(mod_id, slice_id); int idx = flexran_find_ul_slice(mod_id, slice_id);
if (idx < 0) return; if (idx < 0) return 0;
pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
ul->move_UE(ul->slices, ue_id, idx); ul->move_UE(ul->slices, ue_id, idx);
return 1;
} }
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object) {
if (!mac_is_present(mod_id)) return 0; if (!mac_is_present(mod_id)) return 0;
void *params = NULL; void *params = NULL;
switch (s->params_case) { switch (s->params_case) {
...@@ -3133,7 +3135,7 @@ int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { ...@@ -3133,7 +3135,7 @@ int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
char *l = s->label ? strdup(s->label) : NULL; char *l = s->label ? strdup(s->label) : NULL;
void *algo = &dl->dl_algo; // default scheduler void *algo = &dl->dl_algo; // default scheduler
if (s->scheduler) { if (s->scheduler) {
algo = dlsym(NULL, s->scheduler); algo = dlsym(object, s->scheduler);
if (!algo) { if (!algo) {
free(params); free(params);
LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
...@@ -3193,7 +3195,7 @@ int flexran_get_num_dl_slices(mid_t mod_id) { ...@@ -3193,7 +3195,7 @@ int flexran_get_num_dl_slices(mid_t mod_id) {
return RC.mac[mod_id]->pre_processor_dl.slices->num; return RC.mac[mod_id]->pre_processor_dl.slices->num;
} }
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object) {
if (!mac_is_present(mod_id)) return -1; if (!mac_is_present(mod_id)) return -1;
void *params = NULL; void *params = NULL;
switch (s->params_case) { switch (s->params_case) {
...@@ -3210,7 +3212,7 @@ int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { ...@@ -3210,7 +3212,7 @@ int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
char *l = s->label ? strdup(s->label) : NULL; char *l = s->label ? strdup(s->label) : NULL;
void *algo = &ul->ul_algo; // default scheduler void *algo = &ul->ul_algo; // default scheduler
if (s->scheduler) { if (s->scheduler) {
algo = dlsym(NULL, s->scheduler); algo = dlsym(object, s->scheduler);
if (!algo) { if (!algo) {
free(params); free(params);
LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
...@@ -3276,9 +3278,9 @@ char *flexran_get_dl_scheduler_name(mid_t mod_id) { ...@@ -3276,9 +3278,9 @@ char *flexran_get_dl_scheduler_name(mid_t mod_id) {
return RC.mac[mod_id]->pre_processor_dl.dl_algo.name; return RC.mac[mod_id]->pre_processor_dl.dl_algo.name;
} }
int flexran_set_dl_scheduler(mid_t mod_id, char *sched) { int flexran_set_dl_scheduler(mid_t mod_id, char *sched, void *object) {
if (!mac_is_present(mod_id)) return -1; if (!mac_is_present(mod_id)) return -1;
void *d = dlsym(NULL, sched); void *d = dlsym(object, sched);
if (!d) return -2; if (!d) return -2;
pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl; pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl;
dl_pp->dl_algo.unset(&dl_pp->dl_algo.data); dl_pp->dl_algo.unset(&dl_pp->dl_algo.data);
...@@ -3292,9 +3294,9 @@ char *flexran_get_ul_scheduler_name(mid_t mod_id) { ...@@ -3292,9 +3294,9 @@ char *flexran_get_ul_scheduler_name(mid_t mod_id) {
return RC.mac[mod_id]->pre_processor_ul.ul_algo.name; return RC.mac[mod_id]->pre_processor_ul.ul_algo.name;
} }
int flexran_set_ul_scheduler(mid_t mod_id, char *sched) { int flexran_set_ul_scheduler(mid_t mod_id, char *sched, void *object) {
if (!mac_is_present(mod_id)) return -1; if (!mac_is_present(mod_id)) return -1;
void *d = dlsym(NULL, sched); void *d = dlsym(object, sched);
if (!d) return -2; if (!d) return -2;
pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul; pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul;
ul_pp->ul_algo.unset(&ul_pp->ul_algo.data); ul_pp->ul_algo.unset(&ul_pp->ul_algo.data);
......
...@@ -669,15 +669,16 @@ int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo); ...@@ -669,15 +669,16 @@ int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo);
/* Get the DL slice ID for a UE */ /* Get the DL slice ID for a UE */
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id); int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id);
/* Set the DL slice for a UE */ /* Set the DL slice for a UE */
void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); int flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id);
/* Get the UL slice ID for a UE */ /* Get the UL slice ID for a UE */
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id); int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id);
/* Set the UL slice for a UE */ /* Set the UL slice for a UE */
void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); int flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id);
/* Create slice in DL, returns the new slice index */ /* Create slice in DL, returns the new slice index, object can be shared
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); * library for the scheduler or NULL */
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object);
/* Remove slice in DL, returns new number of slices or -1 on error */ /* Remove slice in DL, returns new number of slices or -1 on error */
int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s);
...@@ -691,8 +692,9 @@ void flexran_get_dl_slice(mid_t mod_id, ...@@ -691,8 +692,9 @@ void flexran_get_dl_slice(mid_t mod_id,
/* Get the number of slices in DL */ /* Get the number of slices in DL */
int flexran_get_num_dl_slices(mid_t mod_id); int flexran_get_num_dl_slices(mid_t mod_id);
/* Create slice in UL, returns the new slice index */ /* Create slice in UL, returns the new slice index, object can be shared library
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); * for the scheduler or NULL */
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object);
/* Remove slice in UL */ /* Remove slice in UL */
int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s);
...@@ -708,14 +710,14 @@ int flexran_get_num_ul_slices(mid_t mod_id); ...@@ -708,14 +710,14 @@ int flexran_get_num_ul_slices(mid_t mod_id);
/* Get the name of/Set the DL scheduling algorithm. If slicing is active, this /* Get the name of/Set the DL scheduling algorithm. If slicing is active, this
* corresponds to the default algorithm for slices, otherwise the currently * corresponds to the default algorithm for slices, otherwise the currently
* used one. */ * used one. object is a shared object in which to find the scheduler */
char *flexran_get_dl_scheduler_name(mid_t mod_id); char *flexran_get_dl_scheduler_name(mid_t mod_id);
int flexran_set_dl_scheduler(mid_t mod_id, char *sched); int flexran_set_dl_scheduler(mid_t mod_id, char *sched, void *object);
/* Get the name of/Set the UL scheduler algorithm. Same applies as for the DL /* Get the name of/Set the UL scheduler algorithm. Same applies as for the DL
* case */ * case. object is a shared object in which to find the scheduler */
char *flexran_get_ul_scheduler_name(mid_t mod_id); char *flexran_get_ul_scheduler_name(mid_t mod_id);
int flexran_set_ul_scheduler(mid_t mod_id, char *sched); int flexran_set_ul_scheduler(mid_t mod_id, char *sched, void *object);
/************************** S1AP **************************/ /************************** S1AP **************************/
/* Get the number of MMEs to be connected */ /* Get the number of MMEs to be connected */
......
...@@ -58,6 +58,11 @@ struct timesync { ...@@ -58,6 +58,11 @@ struct timesync {
int timer_num; int timer_num;
flexran_agent_timer_element_t *timer[MAX_NUM_TIMERS]; flexran_agent_timer_element_t *timer[MAX_NUM_TIMERS];
int add_num;
flexran_agent_timer_element_t *add_list[MAX_NUM_TIMERS];
int remove_num;
int remove_list[MAX_NUM_TIMERS];
pthread_mutex_t mutex_timer; pthread_mutex_t mutex_timer;
int exit; int exit;
...@@ -76,8 +81,12 @@ err_code_t flexran_agent_timer_init(mid_t mod_id) { ...@@ -76,8 +81,12 @@ err_code_t flexran_agent_timer_init(mid_t mod_id) {
sync->current = 0; sync->current = 0;
sync->next = 0; sync->next = 0;
sync->timer_num = 0; sync->timer_num = 0;
for (int i = 0; i < MAX_NUM_TIMERS; ++i) sync->add_num = 0;
sync->remove_num = 0;
for (int i = 0; i < MAX_NUM_TIMERS; ++i) {
sync->timer[i] = NULL; sync->timer[i] = NULL;
sync->add_list[i] = NULL;
}
pthread_mutex_init(&sync->mutex_timer, NULL); pthread_mutex_init(&sync->mutex_timer, NULL);
sync->exit = 0; sync->exit = 0;
...@@ -170,12 +179,19 @@ void *flexran_agent_timer_thread(void *args) { ...@@ -170,12 +179,19 @@ void *flexran_agent_timer_thread(void *args) {
break; break;
pthread_mutex_lock(&sync->mutex_timer); pthread_mutex_lock(&sync->mutex_timer);
sync->current++; for (int i = 0; i < sync->add_num; ++i) {
sync->timer[sync->timer_num] = sync->add_list[i];
sync->timer_num++;
}
sync->add_num = 0;
for (int i = 0; i < sync->remove_num; ++i)
flexran_agent_timer_remove_internal(sync, sync->remove_list[i]);
sync->remove_num = 0;
pthread_mutex_unlock(&sync->mutex_timer);
if (sync->current < sync->next) { sync->current++;
pthread_mutex_unlock(&sync->mutex_timer); if (sync->current < sync->next)
continue; continue;
}
for (int i = 0; i < sync->timer_num; ++i) { for (int i = 0; i < sync->timer_num; ++i) {
flexran_agent_timer_element_t *t = sync->timer[i]; flexran_agent_timer_element_t *t = sync->timer[i];
...@@ -186,7 +202,6 @@ void *flexran_agent_timer_thread(void *args) { ...@@ -186,7 +202,6 @@ void *flexran_agent_timer_thread(void *args) {
if (sync->next == sync->current || t->next < sync->next) if (sync->next == sync->current || t->next < sync->next)
sync->next = t->next; sync->next = t->next;
} }
pthread_mutex_unlock(&sync->mutex_timer);
} }
LOG_W(FLEXRAN_AGENT, "terminated timer thread\n"); LOG_W(FLEXRAN_AGENT, "terminated timer thread\n");
return NULL; return NULL;
...@@ -230,45 +245,35 @@ err_code_t flexran_agent_create_timer(mid_t mod_id, ...@@ -230,45 +245,35 @@ err_code_t flexran_agent_create_timer(mid_t mod_id,
struct timesync *sync = &timesync[mod_id]; struct timesync *sync = &timesync[mod_id];
pthread_mutex_lock(&sync->mutex_timer); pthread_mutex_lock(&sync->mutex_timer);
if (sync->timer_num >= MAX_NUM_TIMERS) { if (sync->timer_num + sync->add_num >= MAX_NUM_TIMERS) {
pthread_mutex_unlock(&sync->mutex_timer); pthread_mutex_unlock(&sync->mutex_timer);
LOG_E(FLEXRAN_AGENT, "maximum number of timers (%d) reached while adding timer %d\n", LOG_E(FLEXRAN_AGENT, "maximum number of timers (%d) reached while adding timer %d\n",
sync->timer_num, xid); sync->timer_num + sync->add_num, xid);
free(t); free(t);
return TIMER_SETUP_FAILED; return TIMER_SETUP_FAILED;
} }
/* TODO check that xid does not exist? */ /* TODO check that xid does not exist? */
t->next = sync->current + 1; t->next = sync->current + sf;
if (sync->next <= sync->current || t->next < sync->next) if (sync->next <= sync->current || t->next < sync->next)
sync->next = t->next; sync->next = t->next;
sync->timer[sync->timer_num] = t; sync->add_list[sync->add_num] = t;
sync->timer_num++; sync->add_num++;
pthread_mutex_unlock(&sync->mutex_timer);
LOG_D(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id);
return 0;
}
err_code_t flexran_agent_destroy_timers(mid_t mod_id) {
struct timesync *sync = &timesync[mod_id];
pthread_mutex_lock(&sync->mutex_timer);
for (int i = sync->timer_num - 1; i < 0; --i) {
flexran_agent_timer_remove_internal(sync, i);
}
pthread_mutex_unlock(&sync->mutex_timer); pthread_mutex_unlock(&sync->mutex_timer);
LOG_I(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id);
return 0; return 0;
} }
err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) { err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) {
struct timesync *sync = &timesync[mod_id]; struct timesync *sync = &timesync[mod_id];
pthread_mutex_lock(&sync->mutex_timer);
for (int i = 0; i < sync->timer_num; ++i) { for (int i = 0; i < sync->timer_num; ++i) {
if (sync->timer[i]->xid == xid) { if (sync->timer[i]->xid == xid) {
flexran_agent_timer_remove_internal(sync, i); pthread_mutex_lock(&sync->mutex_timer);
sync->remove_list[sync->remove_num] = i;
sync->remove_num++;
pthread_mutex_unlock(&sync->mutex_timer); pthread_mutex_unlock(&sync->mutex_timer);
return 0; return 0;
} }
} }
pthread_mutex_unlock(&sync->mutex_timer);
LOG_E(FLEXRAN_AGENT, "could not find timer %d\n", xid); LOG_E(FLEXRAN_AGENT, "could not find timer %d\n", xid);
return TIMER_ELEMENT_NOT_FOUND; return TIMER_ELEMENT_NOT_FOUND;
} }
...@@ -277,7 +282,8 @@ err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) { ...@@ -277,7 +282,8 @@ err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) {
void flexran_agent_timer_remove_internal(struct timesync *sync, int index) { void flexran_agent_timer_remove_internal(struct timesync *sync, int index) {
LOG_I(FLEXRAN_AGENT, "remove timer xid %d (index %d) for agent %d\n", LOG_I(FLEXRAN_AGENT, "remove timer xid %d (index %d) for agent %d\n",
sync->timer[index]->xid, index, sync->timer[index]->mod_id); sync->timer[index]->xid, index, sync->timer[index]->mod_id);
flexran_agent_destroy_flexran_message(sync->timer[index]->msg); if (sync->timer[index]->msg)
flexran_agent_destroy_flexran_message(sync->timer[index]->msg);
free(sync->timer[index]); free(sync->timer[index]);
for (int i = index + 1; i < sync->timer_num; ++i) for (int i = index + 1; i < sync->timer_num; ++i)
sync->timer[i - 1] = sync->timer[i]; sync->timer[i - 1] = sync->timer[i];
......
...@@ -61,9 +61,6 @@ err_code_t flexran_agent_create_timer(mid_t mod_id, ...@@ -61,9 +61,6 @@ err_code_t flexran_agent_create_timer(mid_t mod_id,
flexran_agent_timer_callback_t cb, flexran_agent_timer_callback_t cb,
Protocol__FlexranMessage *msg); Protocol__FlexranMessage *msg);
/* Destroy all existing timers */
err_code_t flexran_agent_destroy_timers(mid_t mod_id);
/* Destroy the timer for task with id xid */ /* Destroy the timer for task with id xid */
err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid); err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid);
......
/*
* 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 imsi.c
* \brief flexran IMSI UE-slice association app
* \author Robert Schmidt, Firas Abdeljelil
* \date 2020
* \version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
#include "flexran_agent_common.h"
#include "flexran_agent_async.h"
#include "flexran_agent_extern.h"
#include "flexran_agent_timer.h"
#include "flexran_agent_defs.h"
#include "flexran_agent_net_comm.h"
#include "flexran_agent_ran_api.h"
#include "flexran_agent_phy.h"
#include "flexran_agent_mac.h"
#include "flexran_agent_rrc.h"
#include "flexran_agent_pdcp.h"
#include "flexran_agent_s1ap.h"
#include "flexran_agent_app.h"
#include "common/utils/LOG/log.h"
#include "assertions.h"
#include "queue.h"
typedef struct Map_regex_slice slist_data_t;
struct Map_regex_slice {
char regex_[30] ;
int slice_dl;
int slice_ul;
regex_t regex;
SLIST_ENTRY (Map_regex_slice) entries;
};
bool reconfig = false;
int ue[MAX_MOBILES_PER_ENB]={ [0 ... MAX_MOBILES_PER_ENB - 1] = -1 };
SLIST_HEAD(slisthead, Map_regex_slice) head;
int dump_list(void) {
int len = 1;
slist_data_t *datap = NULL;
SLIST_FOREACH(datap, &head, entries) {
LOG_W(FLEXRAN_AGENT, "%d: regex %s DL %d UL %d\n", len++, datap->regex_,
datap->slice_dl, datap->slice_ul);
}
return len;
}
void add(char *regex, int dl, int ul) {
slist_data_t *datap = malloc(sizeof(slist_data_t));
if (!datap) {
LOG_E(FLEXRAN_AGENT, "cannot allocate memory for slist_data_t\n");
return;
}
strcpy(datap->regex_, regex);
datap->slice_dl = dl;
datap->slice_ul = ul;
regcomp(&datap->regex, datap->regex_, 0);
SLIST_INSERT_HEAD(&head, datap, entries);
if (ul==-1)
LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice DL %d\n" ,regex, dl);
else if (dl==-1)
LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice UL %d\n" ,regex, ul);
else
LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice DL %d UL %d\n",
regex, dl, ul);
}
void remove_(char *regex) {
slist_data_t *datap = NULL;
SLIST_FOREACH(datap, &head, entries) {
if (strcmp(datap->regex_, regex) == 0) {
SLIST_REMOVE(&head, datap, Map_regex_slice, entries);
if (datap->slice_dl==-1)
LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice UL %d\n",datap->regex_, datap->slice_ul);
else if (datap->slice_ul==-1)
LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice DL %d\n",datap->regex_, datap->slice_dl);
else
LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice DL %d UL %d\n",
datap->regex_, datap->slice_dl, datap->slice_ul);
regfree(&datap->regex);
free(datap);
return;
}
}
LOG_E(FLEXRAN_AGENT, "no regex %s found in list\n", regex);
}
Protocol__FlexranMessage *matching_tick(
mid_t mod_id,
const Protocol__FlexranMessage *msg) {
const int num = flexran_get_mac_num_ues(mod_id);
for (int i = 0; i < num; i++) {
int ue_id = flexran_get_mac_ue_id(mod_id, i);
if (ue[ue_id] >= 0 && !reconfig)
continue;
rnti_t rnti = flexran_get_mac_ue_crnti(mod_id, ue_id);
uint64_t imsi = flexran_get_ue_imsi(mod_id, rnti);
char snum[20];
sprintf(snum, "%" PRIu64, imsi);
slist_data_t *datap = NULL;
SLIST_FOREACH(datap, &head, entries) {
if (regexec(&datap->regex, snum, 0, NULL, 0) == 0) {
int dl = datap->slice_dl;
if (dl >= 0 && dl != flexran_get_ue_dl_slice_id(mod_id, ue_id)) {
int ra = flexran_set_ue_dl_slice_id(mod_id, ue_id, dl);
if (ra)
LOG_I(FLEXRAN_AGENT,
"RNTI %04x/IMSI %s in the slice_dl %d\n",
rnti,
snum,
dl);
else
LOG_W(FLEXRAN_AGENT, "No such DL slice %d\n", dl);
}
int ul = datap->slice_ul;
if (ul >= 0 && ul != flexran_get_ue_ul_slice_id(mod_id, ue_id)) {
int rb = flexran_set_ue_ul_slice_id(mod_id, ue_id, ul);
if (rb)
LOG_I(FLEXRAN_AGENT,
"RNTI %04x/IMSI %s in the slice_ul %d\n",
rnti,
snum,
ul);
else
LOG_W(FLEXRAN_AGENT, "No such DL slice %d\n", dl);
}
}
}
ue[ue_id] = ue_id;
}
reconfig = false;
return NULL;
}
void add_param(Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, int n_p) {
char s[30];
reconfig = true;
bool supp=false;
bool sl_E=false;
int dl=-1;
int ul=-1;
slist_data_t *datap = NULL;
for (int i = 0; i < n_p; ++i) {
switch (p[i]->value->param_case) {
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM__NOT_SET:
LOG_I(FLEXRAN_AGENT, " param %s is not set\n", p[i]->key);
break;
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_INTEGER:
if( strcmp(p[i]->key, "slice_dl")==0)
dl= p[i]->value->integer;
else
ul= p[i]->value->integer;
sl_E=true;
break;
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_STR:
strcpy(s,p[i]->value->str);
break;
default:
LOG_W(FLEXRAN_AGENT, " type of param %s is unknown\n", p[i]->key);
break;
};
}
if (!SLIST_EMPTY(&head)){
SLIST_FOREACH(datap, &head, entries) {
if (strcmp(datap->regex_, s) == 0) {
if (datap->slice_dl!=dl || datap->slice_ul!=ul)
supp=true;
}
}
}
if (sl_E==false)
remove_(s);
else {
if (supp==true)
remove_(s);
add(s,dl,ul);
}
/* re-verify all UEs again */
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i)
ue[i] = -1;
}
/* imsi_start: entry point for imsi app. Installs a callback using the timer
* API to have function imsi_tick() called every 5s */
#define TIMER 32
int imsi_start(mid_t mod_id,
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
int n_p)
{
LOG_W(FLEXRAN_AGENT, "%s(): enable IMSI app timer\n", __func__);
flexran_agent_create_timer(mod_id,
500,
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC,
TIMER,
matching_tick,
NULL);
SLIST_INIT(&head);
return 0;
}
int imsi_reconfig(mid_t mod_id,
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
int n_p)
{
add_param(p, n_p);
return 0;
}
/* stop function: cleans up before app can be unloaded. Here: stop the timer */
int imsi_stop(mid_t mod_id) {
LOG_W(FLEXRAN_AGENT, "%s(): disable IMSI app timer\n", __func__);
flexran_agent_destroy_timer(mod_id, TIMER);
return 0;
}
/* app definition. visibility should be set to default so this symbol is
* reachable from outside */
flexran_agent_app_t __attribute__ ((visibility ("default"))) app = {
.start = imsi_start,
.reconfig = imsi_reconfig,
.stop = imsi_stop
};
/*
* 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 sample.c
* \brief flexran sample app
* \author Robert Schmidt
* \date 2020
* \version 0.1
*/
#include "flexran_agent_common.h"
#include "flexran_agent_async.h"
#include "flexran_agent_extern.h"
#include "flexran_agent_timer.h"
#include "flexran_agent_defs.h"
#include "flexran_agent_net_comm.h"
#include "flexran_agent_ran_api.h"
#include "flexran_agent_phy.h"
#include "flexran_agent_mac.h"
#include "flexran_agent_rrc.h"
#include "flexran_agent_pdcp.h"
#include "flexran_agent_s1ap.h"
#include "flexran_agent_app.h"
#include "common/utils/LOG/log.h"
#include "assertions.h"
/* callback to be called for event: shows exemplary variable use and use of RAN
* API */
int tick;
Protocol__FlexranMessage *sample_tick(
mid_t mod_id,
const Protocol__FlexranMessage *msg) {
tick++;
const int num = flexran_get_mac_num_ues(mod_id);
LOG_I(FLEXRAN_AGENT, "%s(): tick %d number UEs %d\n", __func__, tick, num);
return NULL;
}
void print_param(Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, int n_p) {
LOG_I(FLEXRAN_AGENT, "%s(): received %d parameters\n", __func__, n_p);
for (int i = 0; i < n_p; ++i) {
switch (p[i]->value->param_case) {
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM__NOT_SET:
LOG_I(FLEXRAN_AGENT, " param %s is not set\n", p[i]->key);
break;
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_INTEGER:
LOG_I(FLEXRAN_AGENT, " param %s is %d\n", p[i]->key, p[i]->value->integer);
break;
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_FLOATING:
LOG_I(FLEXRAN_AGENT, " param %s is %f\n", p[i]->key, p[i]->value->floating);
break;
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_BOOLEAN:
LOG_I(FLEXRAN_AGENT, " param %s is %s\n", p[i]->key, p[i]->value->boolean ? "true" : "false");
break;
case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_STR:
LOG_I(FLEXRAN_AGENT, " param %s is %s\n", p[i]->key, p[i]->value->str);
break;
default:
LOG_W(FLEXRAN_AGENT, " type of param %s is unknown\n", p[i]->key);
break;
};
}
}
/* sa_start: entry point for sample app. Installs a callback using the timer
* API to have function sample_tick() called every 5s */
#define TIMER 22
int sa_start(mid_t mod_id,
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
int n_p) {
LOG_W(FLEXRAN_AGENT, "%s(): enable sample app timer\n", __func__);
flexran_agent_create_timer(mod_id,
5000,
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC,
TIMER,
sample_tick,
NULL);
print_param(p, n_p);
return 0;
}
int sa_reconfig(mid_t mod_id,
Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p,
int n_p)
{
print_param(p, n_p);
return 0;
}
/* stop function: cleans up before app can be unloaded. Here: stop the timer */
int sa_stop(mid_t mod_id) {
LOG_W(FLEXRAN_AGENT, "%s(): disable sample app timer\n", __func__);
flexran_agent_destroy_timer(mod_id, TIMER);
return 0;
}
/* app definition. visibility should be set to default so this symbol is
* reachable from outside */
flexran_agent_app_t __attribute__ ((visibility ("default"))) app = {
.start = sa_start,
.reconfig = sa_reconfig,
.stop = sa_stop
};
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