Merge remote-tracking branch 'origin/flexran-apps' into integration_2020_wk42
This commit is contained in:
@@ -1095,9 +1095,22 @@ add_library(FLEXRAN_AGENT
|
||||
${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_slice_verification.c
|
||||
${OPENAIR2_DIR}/ENB_APP/flexran_agent_app.c
|
||||
)
|
||||
add_dependencies(FLEXRAN_AGENT rrc_flag)
|
||||
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)
|
||||
|
||||
set(PROTOBUF_LIB "protobuf-c")
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
/*Array containing the Agent-MAC interfaces*/
|
||||
AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];
|
||||
|
||||
@@ -53,10 +55,20 @@ struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_element *slice_config_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state slice_config_ringbuffer_state[NUM_MAX_ENB];
|
||||
|
||||
/* Ringbuffer related to slice configuration if we need to wait for additional
|
||||
* controller information */
|
||||
struct lfds700_ringbuffer_element *store_slice_config_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state store_slice_config_ringbuffer_state[NUM_MAX_ENB];
|
||||
/* stores the (increasing) xid for messages to prevent double use */
|
||||
int xid = 50;
|
||||
|
||||
/* Ringbuffer-related to slice configuration */
|
||||
struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB];
|
||||
|
||||
/* a list of shared objects that are loaded into the user plane */
|
||||
SLIST_HEAD(flexran_so_handle, flexran_agent_so_handle_s) flexran_handles[NUM_MAX_ENB];
|
||||
|
||||
int flexran_agent_mac_stats_reply_ue(mid_t mod_id,
|
||||
Protocol__FlexUeStatsReport **ue_report,
|
||||
int n_ue,
|
||||
@@ -1363,6 +1375,19 @@ void flexran_agent_init_mac_agent(mid_t mod_id) {
|
||||
&scrng,
|
||||
NULL);
|
||||
|
||||
struct lfds700_misc_prng_state sscrng;
|
||||
i = posix_memalign((void **) &store_slice_config_array[mod_id],
|
||||
LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES,
|
||||
sizeof(struct lfds700_ringbuffer_element) * num_elements);
|
||||
AssertFatal(i == 0,
|
||||
"posix_memalign(): could not allocate aligned memory\n");
|
||||
lfds700_ringbuffer_init_valid_on_current_logical_core(
|
||||
&store_slice_config_ringbuffer_state[mod_id],
|
||||
store_slice_config_array[mod_id],
|
||||
num_elements,
|
||||
&sscrng,
|
||||
NULL);
|
||||
|
||||
struct lfds700_misc_prng_state uarng;
|
||||
i = posix_memalign((void **) &ue_assoc_array[mod_id],
|
||||
LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES,
|
||||
@@ -1382,6 +1407,8 @@ void flexran_agent_init_mac_agent(mid_t mod_id) {
|
||||
RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SLIST_INIT(&flexran_handles[mod_id]);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
@@ -1659,6 +1686,8 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id)
|
||||
free(dl_mac_config_array[mod_id]);
|
||||
lfds700_ringbuffer_cleanup(&slice_config_ringbuffer_state[mod_id], NULL );
|
||||
free(slice_config_array[mod_id]);
|
||||
lfds700_ringbuffer_cleanup(&store_slice_config_ringbuffer_state[mod_id], NULL );
|
||||
free(store_slice_config_array[mod_id]);
|
||||
lfds700_ringbuffer_cleanup(&ue_assoc_ringbuffer_state[mod_id], NULL );
|
||||
free(ue_assoc_array[mod_id]);
|
||||
lfds700_misc_library_cleanup();
|
||||
@@ -1698,7 +1727,81 @@ void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) {
|
||||
flexran_agent_destroy_mac_slice_config(&helper);
|
||||
}
|
||||
|
||||
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) {
|
||||
int check_scheduler(mid_t mod_id, char *s) {
|
||||
if (!s)
|
||||
return 1;
|
||||
if (dlsym(NULL, s))
|
||||
return 1;
|
||||
flexran_agent_so_handle_t *so = NULL;
|
||||
SLIST_FOREACH(so, &flexran_handles[mod_id], entries) {
|
||||
if (strcmp(so->name, s) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void request_scheduler(mid_t mod_id, char *s, int xid) {
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"unknown scheduler %s, requesting controller to send it\n",
|
||||
s);
|
||||
Protocol__FlexControlDelegationRequest *req = malloc(sizeof(Protocol__FlexControlDelegationRequest));
|
||||
DevAssert(req);
|
||||
protocol__flex_control_delegation_request__init(req);
|
||||
Protocol__FlexHeader *header = NULL;
|
||||
int rc = flexran_create_header(
|
||||
xid, PROTOCOL__FLEX_TYPE__FLPT_DELEGATE_REQUEST, &header);
|
||||
AssertFatal(rc == 0, "%s(): cannot create header\n", __func__);
|
||||
req->header = header;
|
||||
req->delegation_type = PROTOCOL__FLEX_CONTROL_DELEGATION_TYPE__FLCDT_MAC_DL_UE_SCHEDULER;
|
||||
req->name = strdup(s);
|
||||
|
||||
Protocol__FlexranMessage *msg = malloc(sizeof(Protocol__FlexranMessage));
|
||||
DevAssert(msg);
|
||||
protocol__flexran_message__init(msg);
|
||||
msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DEL_REQ_MSG;
|
||||
msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
|
||||
msg->control_del_req_msg = req;
|
||||
|
||||
int size = 0;
|
||||
void *data = flexran_agent_pack_message(msg, &size);
|
||||
if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_DEFAULT, data, size, 0) < 0)
|
||||
LOG_E(FLEXRAN_AGENT, "%s(): error while sending message\n", __func__);
|
||||
}
|
||||
|
||||
Protocol__FlexranMessage *request_scheduler_timeout(
|
||||
mid_t mod_id,
|
||||
const Protocol__FlexranMessage *msg) {
|
||||
const Protocol__FlexEnbConfigReply *ecr = msg->enb_config_reply_msg;
|
||||
|
||||
struct lfds700_misc_prng_state ls;
|
||||
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
||||
lfds700_misc_prng_init(&ls);
|
||||
|
||||
Protocol__FlexranMessage *smsg = NULL;
|
||||
struct lfds700_ringbuffer_state *state = &store_slice_config_ringbuffer_state[mod_id];
|
||||
if (lfds700_ringbuffer_read(state, NULL, (void **) &smsg, &ls)) {
|
||||
AssertFatal(msg == smsg,
|
||||
"expected and returned enb_config_reply are not the same\n");
|
||||
AssertFatal(ecr->header->xid == smsg->enb_config_reply_msg->header->xid,
|
||||
"expected and returned enb_config_reply are not the same\n");
|
||||
} else {
|
||||
LOG_E(FLEXRAN_AGENT, "%s(): could not read config from ringbuffer\n", __func__);
|
||||
}
|
||||
/* call the helper so that scheduler names are correctly freed */
|
||||
helper_destroy_mac_slice_config(ecr->cell_config[0]->slice_config);
|
||||
ecr->cell_config[0]->slice_config = NULL;
|
||||
/* we should not call flexran_agent_destroy_enb_config_reply(smsg); since
|
||||
* upon timer removal, this is automatically done */
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"remove stored slice config (xid %d) after timeout\n",
|
||||
ecr->header->xid);
|
||||
flexran_agent_destroy_timer(mod_id, ecr->header->xid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void prepare_update_slice_config(mid_t mod_id,
|
||||
Protocol__FlexSliceConfig **slice_config,
|
||||
int request_objects) {
|
||||
if (!*slice_config) return;
|
||||
/* just use the memory and set to NULL in original */
|
||||
Protocol__FlexSliceConfig *sc = *slice_config;
|
||||
@@ -1709,6 +1812,63 @@ void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice
|
||||
lfds700_misc_prng_init(&ls);
|
||||
enum lfds700_misc_flag overwrite_occurred_flag;
|
||||
|
||||
int put_on_hold = 0;
|
||||
if (request_objects
|
||||
&& sc->dl->scheduler
|
||||
&& !check_scheduler(mod_id, sc->dl->scheduler)) {
|
||||
request_scheduler(mod_id, sc->dl->scheduler, xid++);
|
||||
put_on_hold = 1;
|
||||
}
|
||||
for (int i = 0; request_objects && i < sc->dl->n_slices; ++i) {
|
||||
Protocol__FlexSlice *sl = sc->dl->slices[i];
|
||||
if (sl->scheduler && !check_scheduler(mod_id, sl->scheduler)) {
|
||||
request_scheduler(mod_id, sl->scheduler, xid++);
|
||||
put_on_hold = 1;
|
||||
}
|
||||
}
|
||||
if (put_on_hold) {
|
||||
Protocol__FlexEnbConfigReply *reply = malloc(sizeof(Protocol__FlexEnbConfigReply));
|
||||
DevAssert(reply);
|
||||
protocol__flex_enb_config_reply__init(reply);
|
||||
/* use the last used xid so we can correlate answer and waiting config */
|
||||
int rc = flexran_create_header(
|
||||
xid - 1, PROTOCOL__FLEX_TYPE__FLPT_GET_ENB_CONFIG_REPLY, &reply->header);
|
||||
AssertFatal(rc == 0, "%s(): cannot create header\n", __func__);
|
||||
reply->n_cell_config = 1;
|
||||
reply->cell_config = malloc(sizeof(Protocol__FlexCellConfig *));
|
||||
DevAssert(reply->cell_config);
|
||||
reply->cell_config[0] = malloc(sizeof(Protocol__FlexCellConfig));
|
||||
DevAssert(reply->cell_config[0]);
|
||||
protocol__flex_cell_config__init(reply->cell_config[0]);
|
||||
reply->cell_config[0]->slice_config = sc;
|
||||
|
||||
Protocol__FlexranMessage *msg = malloc(sizeof(Protocol__FlexranMessage));
|
||||
DevAssert(msg);
|
||||
protocol__flexran_message__init(msg);
|
||||
msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG;
|
||||
msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
|
||||
msg->enb_config_reply_msg = reply;
|
||||
|
||||
Protocol__FlexEnbConfigReply *o;
|
||||
lfds700_ringbuffer_write(&store_slice_config_ringbuffer_state[mod_id],
|
||||
NULL,
|
||||
(void *)msg,
|
||||
&overwrite_occurred_flag,
|
||||
NULL,
|
||||
(void **) &o,
|
||||
&ls);
|
||||
AssertFatal(overwrite_occurred_flag == LFDS700_MISC_FLAG_LOWERED,
|
||||
"unhandled: stored slice config for controller has been overwritten\n");
|
||||
|
||||
flexran_agent_create_timer(mod_id,
|
||||
3000,
|
||||
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC,
|
||||
xid - 1,
|
||||
request_scheduler_timeout,
|
||||
msg); /* need reply for xid */
|
||||
return;
|
||||
}
|
||||
|
||||
Protocol__FlexSliceConfig *overwritten_sc;
|
||||
lfds700_ringbuffer_write(&slice_config_ringbuffer_state[mod_id],
|
||||
NULL,
|
||||
@@ -1756,6 +1916,69 @@ void flexran_agent_slice_update(mid_t mod_id) {
|
||||
apply_update_dl_slice_config(mod_id, sc->dl);
|
||||
apply_update_ul_slice_config(mod_id, sc->ul);
|
||||
helper_destroy_mac_slice_config(sc);
|
||||
|
||||
flexran_agent_so_handle_t *so = NULL;
|
||||
flexran_agent_so_handle_t *prev = NULL; // the previous to current element, if we delete in order to go back
|
||||
//SLIST_FOREACH(so, &flexran_handles[mod_id], entries)
|
||||
for(so = flexran_handles[mod_id].slh_first; so;) {
|
||||
char *name = so->name;
|
||||
int in_use = strcmp(flexran_get_dl_scheduler_name(mod_id), name) == 0
|
||||
|| strcmp(flexran_get_ul_scheduler_name(mod_id), name) == 0;
|
||||
Protocol__FlexSliceAlgorithm dl_algo = flexran_get_dl_slice_algo(mod_id);
|
||||
if (!in_use && dl_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
int n = flexran_get_num_dl_slices(mod_id);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
Protocol__FlexSlice s;
|
||||
/* NONE so it won't do any allocations */
|
||||
flexran_get_dl_slice(mod_id, i, &s, PROTOCOL__FLEX_SLICE_ALGORITHM__None);
|
||||
if (strcmp(s.scheduler, name) == 0) {
|
||||
in_use = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Protocol__FlexSliceAlgorithm ul_algo = flexran_get_ul_slice_algo(mod_id);
|
||||
if (!in_use && ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
int n = flexran_get_num_ul_slices(mod_id);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
Protocol__FlexSlice s;
|
||||
/* NONE so it won't do any allocations */
|
||||
flexran_get_ul_slice(mod_id, i, &s, PROTOCOL__FLEX_SLICE_ALGORITHM__None);
|
||||
if (strcmp(s.scheduler, name) == 0) {
|
||||
in_use = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!in_use) {
|
||||
char s[512];
|
||||
int rc = flexran_agent_map_name_to_delegated_object(mod_id, so->name, s, 512);
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"removing %s (library handle %p) since it is not used in the user "
|
||||
"plane anymore\n",
|
||||
s,
|
||||
so->dl_handle);
|
||||
dlclose(so->dl_handle);
|
||||
if (rc < 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", so->name);
|
||||
} else {
|
||||
int rc = remove(s);
|
||||
if (rc < 0)
|
||||
LOG_E(FLEXRAN_AGENT, "cannot remove file %s: %s\n", s, strerror(errno));
|
||||
}
|
||||
free (so->name);
|
||||
if (!prev) { //it's the head, start over
|
||||
SLIST_REMOVE_HEAD(&flexran_handles[mod_id], entries);
|
||||
so = flexran_handles[mod_id].slh_first;
|
||||
} else {
|
||||
SLIST_REMOVE(&flexran_handles[mod_id], so, flexran_agent_so_handle_s, entries);
|
||||
so = prev->entries.sle_next;
|
||||
}
|
||||
} else {
|
||||
prev = so;
|
||||
so = so->entries.sle_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Protocol__FlexUeConfig *ue_config = NULL;
|
||||
@@ -1765,3 +1988,92 @@ void flexran_agent_slice_update(mid_t mod_id) {
|
||||
free(ue_config);
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_agent_mac_inform_delegation(mid_t mod_id,
|
||||
Protocol__FlexControlDelegation *cdm) {
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"received FlexControlDelegation message for object '%s' xid %d\n",
|
||||
cdm->name,
|
||||
cdm->header->xid);
|
||||
if (cdm->header->xid < xid - 1) {
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"waiting for %d more messages (up to xid %d)\n",
|
||||
xid - 1 - cdm->header->xid,
|
||||
xid - 1);
|
||||
return;
|
||||
}
|
||||
/* should receive up to xid - 1, otherwise it means there was no request */
|
||||
AssertFatal(xid > cdm->header->xid,
|
||||
"received control delegation with xid %d that we never requested "
|
||||
"(last request %d)\n",
|
||||
cdm->header->xid,
|
||||
xid - 1);
|
||||
|
||||
/* Load the library so the user plane can search it */
|
||||
char s[512];
|
||||
int rc = flexran_agent_map_name_to_delegated_object(mod_id, cdm->name, s, 512);
|
||||
if (rc < 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", cdm->name);
|
||||
return;
|
||||
}
|
||||
/* TODO where to unload/save handle?? */
|
||||
void *h = dlopen(s, RTLD_NOW);
|
||||
if (!h) {
|
||||
LOG_E(FLEXRAN_AGENT, "dlopen(): %s\n", dlerror());
|
||||
return;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "library handle %p\n", h);
|
||||
|
||||
struct lfds700_misc_prng_state ls;
|
||||
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
||||
lfds700_misc_prng_init(&ls);
|
||||
|
||||
Protocol__FlexranMessage *msg = NULL;
|
||||
struct lfds700_ringbuffer_state *state = &store_slice_config_ringbuffer_state[mod_id];
|
||||
if (lfds700_ringbuffer_read(state, NULL, (void **) &msg, &ls) == 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "%s(): could not read config from ringbuffer\n", __func__);
|
||||
return;
|
||||
}
|
||||
AssertFatal(cdm->header->xid == msg->enb_config_reply_msg->header->xid,
|
||||
"expected and retrieved xid of stored slice configuration does "
|
||||
"not match (expected %d, retrieved %d)\n",
|
||||
cdm->header->xid,
|
||||
msg->enb_config_reply_msg->header->xid);
|
||||
|
||||
/* Since we recover, stop the timeout */
|
||||
rc = flexran_agent_destroy_timer(mod_id, cdm->header->xid);
|
||||
|
||||
prepare_update_slice_config(
|
||||
mod_id,
|
||||
&msg->enb_config_reply_msg->cell_config[0]->slice_config,
|
||||
0 /* don't do a request */);
|
||||
/* we should not call flexran_agent_destroy_enb_config_reply(smsg); since
|
||||
* upon timer removal, this is automatically done.
|
||||
* prepare_update_slice_config() takes ownership of the slice config, it is
|
||||
* freed inside */
|
||||
|
||||
flexran_agent_so_handle_t *so = malloc(sizeof(flexran_agent_so_handle_t));
|
||||
DevAssert(so);
|
||||
so->name = strdup(cdm->name);
|
||||
DevAssert(so->name);
|
||||
so->dl_handle = h;
|
||||
SLIST_INSERT_HEAD(&flexran_handles[mod_id], so, entries);
|
||||
}
|
||||
|
||||
void flexran_agent_mac_fill_loaded_mac_objects(
|
||||
mid_t mod_id,
|
||||
Protocol__FlexEnbConfigReply *reply) {
|
||||
int n = 0;
|
||||
flexran_agent_so_handle_t *so = NULL;
|
||||
SLIST_FOREACH(so, &flexran_handles[mod_id], entries)
|
||||
++n;
|
||||
reply->n_loadedmacobjects = n;
|
||||
reply->loadedmacobjects = calloc(n, sizeof(char *));
|
||||
if (!reply->loadedmacobjects) {
|
||||
reply->n_loadedmacobjects = 0;
|
||||
return;
|
||||
}
|
||||
n = 0;
|
||||
SLIST_FOREACH(so, &flexran_handles[mod_id], entries)
|
||||
reply->loadedmacobjects[n++] = so->name;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,12 @@
|
||||
// for flexran_agent_get_mac_xface()
|
||||
#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 */
|
||||
void flexran_agent_init_mac_agent(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
|
||||
* 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
|
||||
* 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
|
||||
* flexran_agent_fill_mac_cell_config() */
|
||||
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
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
#include "flexran_agent_mac_internal.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 *old_message) {
|
||||
|
||||
@@ -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) {
|
||||
if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET
|
||||
&& !s->label && !s->scheduler) {
|
||||
@@ -1033,8 +1049,12 @@ void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) {
|
||||
if (!rc)
|
||||
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
|
||||
} else {
|
||||
LOG_I(FLEXRAN_AGENT, "updating DL slice ID %d\n", s->id);
|
||||
const int rc = flexran_create_dl_slice(mod_id, s);
|
||||
void *lib = search_so(mod_id, s->scheduler);
|
||||
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)
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"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) {
|
||||
if (!rc)
|
||||
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
|
||||
} else {
|
||||
LOG_I(FLEXRAN_AGENT, "updating UL slice ID %d\n", s->id);
|
||||
const int rc = flexran_create_ul_slice(mod_id, s);
|
||||
void *lib = search_so(mod_id, s->scheduler);
|
||||
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)
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"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
|
||||
LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n");
|
||||
return;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "loading DL new scheduling algorithm '%s'\n", dl->scheduler);
|
||||
const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler);
|
||||
void *lib = search_so(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) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"error while updating scheduling algorithm: "
|
||||
@@ -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");
|
||||
return;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "loading new UL scheduling algorithm '%s'\n", ul->scheduler);
|
||||
const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler);
|
||||
void *lib = search_so(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) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"error while updating scheduling algorithm: "
|
||||
|
||||
@@ -3,4 +3,25 @@ package protocol;
|
||||
|
||||
enum flex_control_delegation_type {
|
||||
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";
|
||||
import "config_messages.proto";
|
||||
import "controller_commands.proto";
|
||||
import "config_common.proto";
|
||||
import "control_delegation.proto";
|
||||
|
||||
message flexran_message {
|
||||
optional flexran_direction msg_dir = 100;
|
||||
@@ -32,6 +33,7 @@ message flexran_message {
|
||||
flex_ul_mac_config ul_mac_config_msg = 19;
|
||||
flex_disconnect disconnect_msg = 20;
|
||||
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 {
|
||||
repeated flex_cell_config cell_config = 3;
|
||||
optional uint32 device_spec = 4;
|
||||
optional flex_s1ap_config s1ap = 5;
|
||||
repeated string loadedApps = 6;
|
||||
repeated string loadedMacObjects = 7;
|
||||
}
|
||||
|
||||
message flex_ue_config_request {
|
||||
@@ -225,11 +229,17 @@ message flex_ue_state_change {
|
||||
|
||||
message flex_control_delegation {
|
||||
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 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
|
||||
//
|
||||
@@ -237,6 +247,7 @@ message flex_control_delegation {
|
||||
message flex_agent_reconfiguration {
|
||||
optional flex_header header = 1;
|
||||
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
|
||||
|
||||
@@ -44,5 +44,6 @@ enum flex_type {
|
||||
FLPT_RECONFIGURE_AGENT = 16;
|
||||
FLPT_RRC_TRIGGERING = 17;
|
||||
FLPT_UL_MAC_CONFIG = 18;
|
||||
FLPT_DELEGATE_REQUEST = 22;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,6 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int channel_container_init = 0;
|
||||
int flexran_agent_start(mid_t mod_id)
|
||||
{
|
||||
@@ -233,6 +232,9 @@ int flexran_agent_start(mid_t mod_id)
|
||||
agent_task_created = 1;
|
||||
}
|
||||
|
||||
/* Init the app sublayer */
|
||||
flexran_agent_app_init(mod_id);
|
||||
|
||||
pthread_mutex_init(&flexran->mutex_node_ctrl, NULL);
|
||||
pthread_cond_init(&flexran->cond_node_ctrl, NULL);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#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"
|
||||
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "flexran_agent_common.h"
|
||||
#include "flexran_agent_common_internal.h"
|
||||
@@ -39,6 +42,7 @@
|
||||
#include "flexran_agent_mac.h"
|
||||
#include "flexran_agent_rrc.h"
|
||||
#include "flexran_agent_s1ap.h"
|
||||
#include "flexran_agent_app.h"
|
||||
//#include "PHY/extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "flexran_agent_mac_internal.h"
|
||||
@@ -326,6 +330,12 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
|
||||
if (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);
|
||||
free(msg);
|
||||
@@ -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) {
|
||||
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
|
||||
Protocol__FlexControlDelegation *control_delegation_msg = input->control_delegation_msg;
|
||||
// struct timespec vartime = timer_start();
|
||||
//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), "/%s.so", control_delegation_msg->name);
|
||||
strcpy(target, RC.flexran[mod_id]->cache_name);
|
||||
strcat(target, lib_name);
|
||||
FILE *f;
|
||||
f = fopen(target, "wb");
|
||||
*msg = NULL;
|
||||
|
||||
if (f) {
|
||||
fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f);
|
||||
fclose(f);
|
||||
char target[512];
|
||||
int len = snprintf(target, sizeof(target), "%s/libflex.%s.so",
|
||||
RC.flexran[mod_id]->cache_name,
|
||||
control_delegation_msg->name);
|
||||
if (len >= sizeof(target)) {
|
||||
LOG_E(FLEXRAN_AGENT, "target has been truncated, cannot write file name\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] can not write control delegation data to %s\n",
|
||||
mod_id, target);
|
||||
LOG_W(FLEXRAN_AGENT, "remove file %s\n", 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;
|
||||
}
|
||||
|
||||
@@ -452,10 +501,44 @@ int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg) {
|
||||
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) {
|
||||
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
@@ -465,6 +548,15 @@ int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg) {
|
||||
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) {
|
||||
xid_t xid;
|
||||
@@ -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))
|
||||
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));
|
||||
|
||||
if(*msg == NULL) {
|
||||
@@ -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 (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
|
||||
&& enb_config->cell_config[0]->has_dl_freq
|
||||
|
||||
@@ -131,11 +131,20 @@ int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg);
|
||||
/* Control delegation message constructor and destructor */
|
||||
int flexran_agent_control_delegation(mid_t mod_id, const void *params, 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 */
|
||||
int flexran_agent_reconfiguration(mid_t mod_id, const void *params, 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 */
|
||||
int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
|
||||
int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "flexran_agent_rrc.h"
|
||||
#include "flexran_agent_pdcp.h"
|
||||
#include "flexran_agent_s1ap.h"
|
||||
#include "flexran_agent_app.h"
|
||||
#include "flexran_agent_timer.h"
|
||||
#include "flexran_agent_ran_api.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
@@ -80,6 +81,11 @@ flexran_agent_message_destruction_callback message_destruction_callback[] = {
|
||||
flexran_agent_destroy_ue_state_change,
|
||||
flexran_agent_destroy_control_delegation,
|
||||
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[] = { */
|
||||
|
||||
@@ -3092,12 +3092,13 @@ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_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) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
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 0;
|
||||
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;
|
||||
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) {
|
||||
@@ -3108,15 +3109,16 @@ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_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) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
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 0;
|
||||
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;
|
||||
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;
|
||||
void *params = NULL;
|
||||
switch (s->params_case) {
|
||||
@@ -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;
|
||||
void *algo = &dl->dl_algo; // default scheduler
|
||||
if (s->scheduler) {
|
||||
algo = dlsym(NULL, s->scheduler);
|
||||
algo = dlsym(object, s->scheduler);
|
||||
if (!algo) {
|
||||
free(params);
|
||||
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) {
|
||||
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;
|
||||
void *params = NULL;
|
||||
switch (s->params_case) {
|
||||
@@ -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;
|
||||
void *algo = &ul->ul_algo; // default scheduler
|
||||
if (s->scheduler) {
|
||||
algo = dlsym(NULL, s->scheduler);
|
||||
algo = dlsym(object, s->scheduler);
|
||||
if (!algo) {
|
||||
free(params);
|
||||
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) {
|
||||
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;
|
||||
void *d = dlsym(NULL, sched);
|
||||
void *d = dlsym(object, sched);
|
||||
if (!d) return -2;
|
||||
pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl;
|
||||
dl_pp->dl_algo.unset(&dl_pp->dl_algo.data);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
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;
|
||||
void *d = dlsym(NULL, sched);
|
||||
void *d = dlsym(object, sched);
|
||||
if (!d) return -2;
|
||||
pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul;
|
||||
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);
|
||||
/* Get the DL slice ID for a UE */
|
||||
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id);
|
||||
/* 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 */
|
||||
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id);
|
||||
/* 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 */
|
||||
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s);
|
||||
/* Create slice in DL, returns the new slice index, object can be shared
|
||||
* 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 */
|
||||
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,
|
||||
/* Get the number of slices in DL */
|
||||
int flexran_get_num_dl_slices(mid_t mod_id);
|
||||
|
||||
/* Create slice in UL, returns the new slice index */
|
||||
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s);
|
||||
/* Create slice in UL, returns the new slice index, object can be shared library
|
||||
* for the scheduler or NULL */
|
||||
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object);
|
||||
/* Remove slice in UL */
|
||||
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);
|
||||
|
||||
/* Get the name of/Set the DL scheduling algorithm. If slicing is active, this
|
||||
* 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);
|
||||
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
|
||||
* case */
|
||||
* case. object is a shared object in which to find the scheduler */
|
||||
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 **************************/
|
||||
/* Get the number of MMEs to be connected */
|
||||
|
||||
@@ -58,6 +58,11 @@ struct timesync {
|
||||
|
||||
int timer_num;
|
||||
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;
|
||||
|
||||
int exit;
|
||||
@@ -76,8 +81,12 @@ err_code_t flexran_agent_timer_init(mid_t mod_id) {
|
||||
sync->current = 0;
|
||||
sync->next = 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->add_list[i] = NULL;
|
||||
}
|
||||
pthread_mutex_init(&sync->mutex_timer, NULL);
|
||||
sync->exit = 0;
|
||||
|
||||
@@ -170,12 +179,19 @@ void *flexran_agent_timer_thread(void *args) {
|
||||
break;
|
||||
|
||||
pthread_mutex_lock(&sync->mutex_timer);
|
||||
sync->current++;
|
||||
|
||||
if (sync->current < sync->next) {
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
continue;
|
||||
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);
|
||||
|
||||
sync->current++;
|
||||
if (sync->current < sync->next)
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < sync->timer_num; ++i) {
|
||||
flexran_agent_timer_element_t *t = sync->timer[i];
|
||||
@@ -186,7 +202,6 @@ void *flexran_agent_timer_thread(void *args) {
|
||||
if (sync->next == sync->current || t->next < sync->next)
|
||||
sync->next = t->next;
|
||||
}
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
}
|
||||
LOG_W(FLEXRAN_AGENT, "terminated timer thread\n");
|
||||
return NULL;
|
||||
@@ -230,45 +245,35 @@ err_code_t flexran_agent_create_timer(mid_t mod_id,
|
||||
|
||||
struct timesync *sync = ×ync[mod_id];
|
||||
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);
|
||||
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);
|
||||
return TIMER_SETUP_FAILED;
|
||||
}
|
||||
/* 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)
|
||||
sync->next = t->next;
|
||||
sync->timer[sync->timer_num] = t;
|
||||
sync->timer_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 = ×ync[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);
|
||||
}
|
||||
sync->add_list[sync->add_num] = t;
|
||||
sync->add_num++;
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
LOG_I(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) {
|
||||
struct timesync *sync = ×ync[mod_id];
|
||||
pthread_mutex_lock(&sync->mutex_timer);
|
||||
for (int i = 0; i < sync->timer_num; ++i) {
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&sync->mutex_timer);
|
||||
LOG_E(FLEXRAN_AGENT, "could not find timer %d\n", xid);
|
||||
return TIMER_ELEMENT_NOT_FOUND;
|
||||
}
|
||||
@@ -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) {
|
||||
LOG_I(FLEXRAN_AGENT, "remove timer xid %d (index %d) for agent %d\n",
|
||||
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]);
|
||||
for (int i = index + 1; i < sync->timer_num; ++i)
|
||||
sync->timer[i - 1] = sync->timer[i];
|
||||
|
||||
@@ -61,9 +61,6 @@ err_code_t flexran_agent_create_timer(mid_t mod_id,
|
||||
flexran_agent_timer_callback_t cb,
|
||||
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 */
|
||||
err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid);
|
||||
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* 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
|
||||
};
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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
|
||||
};
|
||||
Reference in New Issue
Block a user