Merge remote-tracking branch 'origin/develop' into fembms-enb-ue

This commit is contained in:
Javier Morgade
2020-07-29 10:54:38 +02:00
47 changed files with 3001 additions and 2523 deletions
@@ -49,18 +49,13 @@ struct lfds700_misc_prng_state ps[NUM_MAX_ENB];
struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB];
struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB];
/* the slice config as kept in the underlying system */
Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES];
/* a structure that keeps updates which will be reflected in slice_config later */
Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES];
/* indicates whether sc_update contains new data */
int perform_slice_config_update_count = 1;
/* queue of incoming new UE<>slice association commands */
Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES];
int n_ue_slice_assoc_updates = 0;
/* mutex for sc_update: do not receive new config and write it at the same time */
pthread_mutex_t sc_update_mtx = PTHREAD_MUTEX_INITIALIZER;
/* Ringbuffer-related to slice configuration */
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 */
struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB];
struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB];
int flexran_agent_mac_stats_reply_ue(mid_t mod_id,
Protocol__FlexUeStatsReport **ue_report,
@@ -1354,6 +1349,33 @@ void flexran_agent_init_mac_agent(mid_t mod_id) {
AssertFatal(i == 0, "posix_memalign(): could not allocate aligned memory for lfds library\n");
lfds700_ringbuffer_init_valid_on_current_logical_core(&ringbuffer_state[mod_id],
dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL);
struct lfds700_misc_prng_state scrng;
i = posix_memalign((void **) &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(
&slice_config_ringbuffer_state[mod_id],
slice_config_array[mod_id],
num_elements,
&scrng,
NULL);
struct lfds700_misc_prng_state uarng;
i = posix_memalign((void **) &ue_assoc_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(
&ue_assoc_ringbuffer_state[mod_id],
ue_assoc_array[mod_id],
num_elements,
&uarng,
NULL);
for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
for (j = 0; j < 8; j++) {
if (RC.mac && RC.mac[mod_id])
@@ -1465,9 +1487,74 @@ void flexran_agent_fill_mac_cell_config(mid_t mod_id, uint8_t cc_id,
conf->si_config->has_sfn = 1;
}
/* get a pointer to the config which is maintained in the agent throughout
* its lifetime */
conf->slice_config = flexran_agent_get_slice_config(mod_id);
conf->slice_config = malloc(sizeof(Protocol__FlexSliceConfig));
if (conf->slice_config) {
protocol__flex_slice_config__init(conf->slice_config);
Protocol__FlexSliceConfig *sc = conf->slice_config;
sc->dl = malloc(sizeof(Protocol__FlexSliceDlUlConfig));
DevAssert(sc->dl);
protocol__flex_slice_dl_ul_config__init(sc->dl);
sc->dl->algorithm = flexran_get_dl_slice_algo(mod_id);
sc->dl->has_algorithm = 1;
sc->dl->n_slices = flexran_get_num_dl_slices(mod_id);
if (sc->dl->n_slices > 0) {
sc->dl->slices = calloc(sc->dl->n_slices, sizeof(Protocol__FlexSlice *));
DevAssert(sc->dl->slices);
for (int i = 0; i < sc->dl->n_slices; ++i) {
sc->dl->slices[i] = malloc(sizeof(Protocol__FlexSlice));
DevAssert(sc->dl->slices[i]);
protocol__flex_slice__init(sc->dl->slices[i]);
flexran_get_dl_slice(mod_id, i, sc->dl->slices[i], sc->dl->algorithm);
}
} else {
sc->dl->scheduler = flexran_get_dl_scheduler_name(mod_id);
}
sc->ul = malloc(sizeof(Protocol__FlexSliceDlUlConfig));
DevAssert(sc->ul);
protocol__flex_slice_dl_ul_config__init(sc->ul);
sc->ul->algorithm = flexran_get_ul_slice_algo(mod_id);
sc->ul->has_algorithm = 1;
sc->ul->n_slices = flexran_get_num_ul_slices(mod_id);
if (sc->ul->n_slices > 0) {
sc->ul->slices = calloc(sc->ul->n_slices, sizeof(Protocol__FlexSlice *));
DevAssert(sc->ul->slices);
for (int i = 0; i < sc->ul->n_slices; ++i) {
sc->ul->slices[i] = malloc(sizeof(Protocol__FlexSlice));
DevAssert(sc->ul->slices[i]);
protocol__flex_slice__init(sc->ul->slices[i]);
flexran_get_ul_slice(mod_id, i, sc->ul->slices[i], sc->ul->algorithm);
}
} else {
sc->ul->scheduler = flexran_get_ul_scheduler_name(mod_id);
}
}
}
void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf) {
Protocol__FlexSliceConfig *sc = conf->slice_config;
for (int i = 0; i < sc->dl->n_slices; ++i) {
free(sc->dl->slices[i]);
sc->dl->slices[i] = NULL;
/* scheduler names are not freed: we assume we read them directly from the
* underlying memory and do not dispose it */
}
free(sc->dl->slices);
/* scheduler name is not freed */
free(sc->dl);
sc->dl = NULL;
for (int i = 0; i < sc->ul->n_slices; ++i) {
free(sc->ul->slices[i]);
sc->ul->slices[i] = NULL;
/* scheduler names are not freed */
}
free(sc->ul->slices);
/* scheduler name is not freed */
free(sc->ul);
sc->ul = NULL;
free(conf->slice_config);
conf->slice_config = NULL;
}
void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id,
@@ -1481,10 +1568,12 @@ void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id,
ue_conf->rnti = flexran_get_mac_ue_crnti(mod_id, ue_id);
ue_conf->has_rnti = 1;
ue_conf->dl_slice_id = flexran_get_ue_dl_slice_id(mod_id, ue_id);
ue_conf->has_dl_slice_id = 1;
ue_conf->ul_slice_id = flexran_get_ue_ul_slice_id(mod_id, ue_id);
ue_conf->has_ul_slice_id = 1;
int dl_id = flexran_get_ue_dl_slice_id(mod_id, ue_id);
ue_conf->dl_slice_id = dl_id;
ue_conf->has_dl_slice_id = dl_id >= 0;
int ul_id = flexran_get_ue_ul_slice_id(mod_id, ue_id);
ue_conf->ul_slice_id = ul_id;
ue_conf->has_ul_slice_id = ul_id >= 0;
ue_conf->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id, ue_id);
ue_conf->has_ue_aggregated_max_bitrate_ul = 1;
@@ -1565,6 +1654,15 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id)
LOG_E(FLEXRAN_AGENT, "MAC agent CM for eNB %d is not registered\n", mod_id);
return -1;
}
lfds700_ringbuffer_cleanup(&ringbuffer_state[mod_id], NULL );
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(&ue_assoc_ringbuffer_state[mod_id], NULL );
free(ue_assoc_array[mod_id]);
lfds700_misc_library_cleanup();
AGENT_MAC_xface *xface = agent_mac_xface[mod_id];
xface->flexran_agent_send_sr_info = NULL;
xface->flexran_agent_send_sf_trigger = NULL;
@@ -1579,230 +1677,91 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id)
return 0;
}
void flexran_create_config_structures(mid_t mod_id)
{
int i;
int n_dl = flexran_get_num_dl_slices(mod_id);
int m_ul = flexran_get_num_ul_slices(mod_id);
slice_config[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul);
sc_update[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul);
if (!slice_config[mod_id] || !sc_update[mod_id]) return;
flexran_agent_read_slice_config(mod_id, slice_config[mod_id]);
flexran_agent_read_slice_config(mod_id, sc_update[mod_id]);
for (i = 0; i < n_dl; i++) {
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
flexran_agent_read_slice_dl_config(mod_id, i, sc_update[mod_id]->dl[i]);
void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) {
if (slice_config->dl) {
if (slice_config->dl->scheduler)
free(slice_config->dl->scheduler);
for (int i = 0; i < slice_config->dl->n_slices; i++)
if (slice_config->dl->slices[i]->scheduler)
free(slice_config->dl->slices[i]->scheduler);
}
for (i = 0; i < m_ul; i++) {
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]);
if (slice_config->ul) {
if (slice_config->ul->scheduler)
free(slice_config->ul->scheduler);
for (int i = 0; i < slice_config->ul->n_slices; i++)
if (slice_config->ul->slices[i]->scheduler)
free(slice_config->ul->slices[i]->scheduler);
}
Protocol__FlexCellConfig helper;
helper.slice_config = slice_config;
flexran_agent_destroy_mac_slice_config(&helper);
}
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) {
if (!*slice_config) return;
/* just use the memory and set to NULL in original */
Protocol__FlexSliceConfig *sc = *slice_config;
*slice_config = NULL;
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);
enum lfds700_misc_flag overwrite_occurred_flag;
Protocol__FlexSliceConfig *overwritten_sc;
lfds700_ringbuffer_write(&slice_config_ringbuffer_state[mod_id],
NULL,
(void *)sc,
&overwrite_occurred_flag,
NULL,
(void **)&overwritten_sc,
&ls);
if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) {
helper_destroy_mac_slice_config(overwritten_sc);
LOG_E(FLEXRAN_AGENT, "lost slice config: too many reconfigurations at once\n");
}
}
void flexran_check_and_remove_slices(mid_t mod_id)
{
Protocol__FlexDlSlice **dl = sc_update[mod_id]->dl;
Protocol__FlexDlSlice **dlreal = slice_config[mod_id]->dl;
int i = 0;
while (i < sc_update[mod_id]->n_dl) {
/* remove slices whose percentage is zero */
if (dl[i]->percentage > 0) {
++i;
continue;
}
if (flexran_remove_dl_slice(mod_id, i) < 1) {
LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n",
mod_id, i, dl[i]->id);
++i;
continue;
}
LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n",
mod_id, i, dl[i]->id);
if (dl[i]->n_sorting > 0) free(dl[i]->sorting);
free(dl[i]->scheduler_name);
if (dlreal[i]->n_sorting > 0) {
dlreal[i]->n_sorting = 0;
free(dlreal[i]->sorting);
}
free(dlreal[i]->scheduler_name);
--sc_update[mod_id]->n_dl;
--slice_config[mod_id]->n_dl;
const size_t last = sc_update[mod_id]->n_dl;
/* we need to memcpy the higher slice to the position we just deleted */
memcpy(dl[i], dl[last], sizeof(*dl[last]));
memset(dl[last], 0, sizeof(*dl[last]));
memcpy(dlreal[i], dlreal[last], sizeof(*dlreal[last]));
memset(dlreal[last], 0, sizeof(*dlreal[last]));
/* dont increase i but recheck the slice which has been copied to here */
}
Protocol__FlexUlSlice **ul = sc_update[mod_id]->ul;
Protocol__FlexUlSlice **ulreal = slice_config[mod_id]->ul;
i = 0;
while (i < sc_update[mod_id]->n_ul) {
if (ul[i]->percentage > 0) {
++i;
continue;
}
if (flexran_remove_ul_slice(mod_id, i) < 1) {
LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n",
mod_id, i, ul[i]->id);
++i;
continue;
}
LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n",
mod_id, i, ul[i]->id);
free(ul[i]->scheduler_name);
free(ulreal[i]->scheduler_name);
--sc_update[mod_id]->n_ul;
--slice_config[mod_id]->n_ul;
const size_t last = sc_update[mod_id]->n_ul;
/* see DL remarks */
memcpy(ul[i], ul[last], sizeof(*ul[last]));
memset(ul[last], 0, sizeof(*ul[last]));
memcpy(ulreal[i], ulreal[last], sizeof(*ulreal[last]));
memset(ulreal[last], 0, sizeof(*ulreal[last]));
/* dont increase i but recheck the slice which has been copied to here */
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config) {
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);
enum lfds700_misc_flag overwrite_occurred_flag;
Protocol__FlexUeConfig *overwritten_ue_config;
lfds700_ringbuffer_write(&ue_assoc_ringbuffer_state[mod_id],
NULL,
(void *) *ue_config,
&overwrite_occurred_flag,
NULL,
(void **)&overwritten_ue_config,
&ls);
if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) {
free(overwritten_ue_config);
LOG_E(FLEXRAN_AGENT, "lost UE-slice association: too many UE-slice associations at once\n");
}
}
void flexran_agent_slice_update(mid_t mod_id)
{
int i;
int changes = 0;
void flexran_agent_slice_update(mid_t mod_id) {
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);
if (perform_slice_config_update_count <= 0) return;
perform_slice_config_update_count--;
pthread_mutex_lock(&sc_update_mtx);
if (!slice_config[mod_id]) {
/* if the configuration does not exist for agent, create from eNB structure
* and exit */
flexran_create_config_structures(mod_id);
pthread_mutex_unlock(&sc_update_mtx);
return;
Protocol__FlexSliceConfig *sc = NULL;
struct lfds700_ringbuffer_state *state = &slice_config_ringbuffer_state[mod_id];
if (lfds700_ringbuffer_read(state, NULL, (void **) &sc, &ls) != 0) {
apply_update_dl_slice_config(mod_id, sc->dl);
apply_update_ul_slice_config(mod_id, sc->ul);
helper_destroy_mac_slice_config(sc);
}
/********* read existing config *********/
/* simply update slice_config all the time and write new config
* (apply_new_slice_dl_config() only updates if changes are necessary) */
slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id);
slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id);
for (i = 0; i < slice_config[mod_id]->n_dl; i++) {
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
Protocol__FlexUeConfig *ue_config = NULL;
state = &ue_assoc_ringbuffer_state[mod_id];
if (lfds700_ringbuffer_read(state, NULL, (void **) &ue_config, &ls) != 0) {
apply_ue_slice_assoc_update(mod_id, ue_config);
free(ue_config);
}
for (i = 0; i < slice_config[mod_id]->n_ul; i++) {
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
}
/********* write new config *********/
/* check for removal (sc_update[X]->dl[Y].percentage == 0)
* and update sc_update & slice_config accordingly */
flexran_check_and_remove_slices(mod_id);
/* create new DL and UL slices if necessary */
for (i = slice_config[mod_id]->n_dl; i < sc_update[mod_id]->n_dl; i++) {
flexran_create_dl_slice(mod_id, sc_update[mod_id]->dl[i]->id);
}
for (i = slice_config[mod_id]->n_ul; i < sc_update[mod_id]->n_ul; i++) {
flexran_create_ul_slice(mod_id, sc_update[mod_id]->ul[i]->id);
}
slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id);
slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id);
changes += apply_new_slice_config(mod_id, slice_config[mod_id], sc_update[mod_id]);
for (i = 0; i < slice_config[mod_id]->n_dl; i++) {
changes += apply_new_slice_dl_config(mod_id,
slice_config[mod_id]->dl[i],
sc_update[mod_id]->dl[i]);
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
}
for (i = 0; i < slice_config[mod_id]->n_ul; i++) {
changes += apply_new_slice_ul_config(mod_id,
slice_config[mod_id]->ul[i],
sc_update[mod_id]->ul[i]);
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
}
flexran_agent_read_slice_config(mod_id, slice_config[mod_id]);
if (n_ue_slice_assoc_updates > 0) {
changes += apply_ue_slice_assoc_update(mod_id);
}
if (changes > 0)
LOG_I(FLEXRAN_AGENT, "[%d] slice configuration: applied %d changes\n", mod_id, changes);
pthread_mutex_unlock(&sc_update_mtx);
}
Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id)
{
if (!slice_config[mod_id]) return NULL;
Protocol__FlexSliceConfig *config = NULL;
pthread_mutex_lock(&sc_update_mtx);
config = flexran_agent_create_slice_config(slice_config[mod_id]->n_dl,
slice_config[mod_id]->n_ul);
if (!config) {
pthread_mutex_unlock(&sc_update_mtx);
return NULL;
}
config->has_intraslice_share_active = 1;
config->intraslice_share_active = slice_config[mod_id]->intraslice_share_active;
config->has_interslice_share_active = 1;
config->interslice_share_active = slice_config[mod_id]->interslice_share_active;
for (int i = 0; i < slice_config[mod_id]->n_dl; ++i) {
if (!config->dl[i]) continue;
config->dl[i]->has_id = 1;
config->dl[i]->id = slice_config[mod_id]->dl[i]->id;
config->dl[i]->has_label = 1;
config->dl[i]->label = slice_config[mod_id]->dl[i]->label;
config->dl[i]->has_percentage = 1;
config->dl[i]->percentage = slice_config[mod_id]->dl[i]->percentage;
config->dl[i]->has_isolation = 1;
config->dl[i]->isolation = slice_config[mod_id]->dl[i]->isolation;
config->dl[i]->has_priority = 1;
config->dl[i]->priority = slice_config[mod_id]->dl[i]->priority;
config->dl[i]->has_position_low = 1;
config->dl[i]->position_low = slice_config[mod_id]->dl[i]->position_low;
config->dl[i]->has_position_high = 1;
config->dl[i]->position_high = slice_config[mod_id]->dl[i]->position_high;
config->dl[i]->has_maxmcs = 1;
config->dl[i]->maxmcs = slice_config[mod_id]->dl[i]->maxmcs;
config->dl[i]->n_sorting = slice_config[mod_id]->dl[i]->n_sorting;
config->dl[i]->sorting = calloc(config->dl[i]->n_sorting, sizeof(Protocol__FlexDlSorting));
if (!config->dl[i]->sorting) config->dl[i]->n_sorting = 0;
for (int j = 0; j < config->dl[i]->n_sorting; ++j)
config->dl[i]->sorting[j] = slice_config[mod_id]->dl[i]->sorting[j];
config->dl[i]->has_accounting = 1;
config->dl[i]->accounting = slice_config[mod_id]->dl[i]->accounting;
config->dl[i]->scheduler_name = strdup(slice_config[mod_id]->dl[i]->scheduler_name);
}
for (int i = 0; i < slice_config[mod_id]->n_ul; ++i) {
if (!config->ul[i]) continue;
config->ul[i]->has_id = 1;
config->ul[i]->id = slice_config[mod_id]->ul[i]->id;
config->ul[i]->has_label = 1;
config->ul[i]->label = slice_config[mod_id]->ul[i]->label;
config->ul[i]->has_percentage = 1;
config->ul[i]->percentage = slice_config[mod_id]->ul[i]->percentage;
config->ul[i]->has_isolation = 1;
config->ul[i]->isolation = slice_config[mod_id]->ul[i]->isolation;
config->ul[i]->has_priority = 1;
config->ul[i]->priority = slice_config[mod_id]->ul[i]->priority;
config->ul[i]->has_first_rb = 1;
config->ul[i]->first_rb = slice_config[mod_id]->ul[i]->first_rb;
config->ul[i]->has_maxmcs = 1;
config->ul[i]->maxmcs = slice_config[mod_id]->ul[i]->maxmcs;
config->ul[i]->n_sorting = slice_config[mod_id]->ul[i]->n_sorting;
config->ul[i]->sorting = calloc(config->ul[i]->n_sorting, sizeof(Protocol__FlexUlSorting));
if (!config->ul[i]->sorting) config->ul[i]->n_sorting = 0;
for (int j = 0; j < config->ul[i]->n_sorting; ++j)
config->ul[i]->sorting[j] = slice_config[mod_id]->ul[i]->sorting[j];
config->ul[i]->has_accounting = 1;
config->ul[i]->accounting = slice_config[mod_id]->ul[i]->accounting;
config->ul[i]->scheduler_name = strdup(slice_config[mod_id]->ul[i]->scheduler_name);
}
pthread_mutex_unlock(&sc_update_mtx);
return config;
}
@@ -115,7 +115,16 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id);
/* Inform controller about possibility to update slice configuration */
void flexran_agent_slice_update(mid_t mod_id);
/* return a pointer to the current config */
Protocol__FlexSliceConfig *flexran_agent_get_slice_config(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);
/* 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 */
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config);
/* free slice_config part of flexCellConfig, filled in
* flexran_agent_fill_mac_cell_config() */
void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf);
#endif
@@ -33,14 +33,6 @@
#include "flexran_agent_mac_internal.h"
#include "flexran_agent_mac_slice_verification.h"
/* from flexran_agent_mac.c */
extern Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES];
extern Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES];
extern int perform_slice_config_update_count;
extern Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES];
extern int n_ue_slice_assoc_updates;
extern pthread_mutex_t sc_update_mtx;
Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message,
Protocol__FlexranMessage *old_message) {
@@ -1033,724 +1025,166 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
}
Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul)
{
int i;
Protocol__FlexSliceConfig *fsc = malloc(sizeof(Protocol__FlexSliceConfig));
if (!fsc) return NULL;
protocol__flex_slice_config__init(fsc);
/* say there are n_dl slices but reserve memory for up to MAX_NUM_SLICES so
* we don't need to reserve again later */
fsc->n_dl = n_dl;
fsc->dl = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexDlSlice *));
if (!fsc->dl) fsc->n_dl = 0;
for (i = 0; i < MAX_NUM_SLICES; i++) {
fsc->dl[i] = malloc(sizeof(Protocol__FlexDlSlice));
if (!fsc->dl[i]) continue;
protocol__flex_dl_slice__init(fsc->dl[i]);
}
/* as above */
fsc->n_ul = m_ul;
fsc->ul = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexUlSlice *));
if (!fsc->ul) fsc->n_ul = 0;
for (i = 0; i < MAX_NUM_SLICES; i++) {
fsc->ul[i] = malloc(sizeof(Protocol__FlexUlSlice));
if (!fsc->ul[i]) continue;
protocol__flex_ul_slice__init(fsc->ul[i]);
}
return fsc;
}
void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s)
{
s->intraslice_share_active = flexran_get_intraslice_sharing_active(mod_id);
s->has_intraslice_share_active = 1;
s->interslice_share_active = flexran_get_interslice_sharing_active(mod_id);
s->has_interslice_share_active = 1;
}
void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice)
{
dl_slice->id = flexran_get_dl_slice_id(mod_id, slice_idx);
dl_slice->has_id = 1;
/* read label from corresponding sc_update entry or give default */
dl_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB;
dl_slice->has_label = 1;
for (int i = 0; i < sc_update[mod_id]->n_dl; i++) {
if (sc_update[mod_id]->dl[i]->id == dl_slice->id
&& sc_update[mod_id]->dl[i]->has_label) {
dl_slice->label = sc_update[mod_id]->dl[i]->label;
break;
}
}
dl_slice->percentage = flexran_get_dl_slice_percentage(mod_id, slice_idx);
dl_slice->has_percentage = 1;
dl_slice->isolation = flexran_get_dl_slice_isolation(mod_id, slice_idx);
dl_slice->has_isolation = 1;
dl_slice->priority = flexran_get_dl_slice_priority(mod_id, slice_idx);
dl_slice->has_priority = 1;
dl_slice->position_low = flexran_get_dl_slice_position_low(mod_id, slice_idx);
dl_slice->has_position_low = 1;
dl_slice->position_high = flexran_get_dl_slice_position_high(mod_id, slice_idx);
dl_slice->has_position_high = 1;
dl_slice->maxmcs = flexran_get_dl_slice_maxmcs(mod_id, slice_idx);
dl_slice->has_maxmcs = 1;
dl_slice->n_sorting = flexran_get_dl_slice_sorting(mod_id, slice_idx, &dl_slice->sorting);
if (dl_slice->n_sorting < 1) dl_slice->sorting = NULL;
dl_slice->accounting = flexran_get_dl_slice_accounting_policy(mod_id, slice_idx);
dl_slice->has_accounting = 1;
const char *s_name = flexran_get_dl_slice_scheduler(mod_id, slice_idx);
if (!dl_slice->scheduler_name
|| strcmp(dl_slice->scheduler_name, s_name) != 0) {
dl_slice->scheduler_name = realloc(dl_slice->scheduler_name, strlen(s_name) + 1);
strcpy(dl_slice->scheduler_name, s_name);
}
}
void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice)
{
ul_slice->id = flexran_get_ul_slice_id(mod_id, slice_idx);
ul_slice->has_id = 1;
/* read label from corresponding sc_update entry or give default */
ul_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB;
ul_slice->has_label = 1;
for (int i = 0; i < sc_update[mod_id]->n_ul; i++) {
if (sc_update[mod_id]->ul[i]->id == ul_slice->id
&& sc_update[mod_id]->ul[i]->has_label) {
ul_slice->label = sc_update[mod_id]->ul[i]->label;
break;
}
}
ul_slice->percentage = flexran_get_ul_slice_percentage(mod_id, slice_idx);
ul_slice->has_percentage = 1;
/*ul_slice->isolation = flexran_get_ul_slice_isolation(mod_id, slice_idx);*/
ul_slice->has_isolation = 0;
/*ul_slice->priority = flexran_get_ul_slice_priority(mod_id, slice_idx);*/
ul_slice->has_priority = 0;
ul_slice->first_rb = flexran_get_ul_slice_first_rb(mod_id, slice_idx);
ul_slice->has_first_rb = 1;
/*ul_slice-> = flexran_get_ul_slice_length_rb(mod_id, slice_idx);
ul_slice->has_length_rb = 0;*/
ul_slice->maxmcs = flexran_get_ul_slice_maxmcs(mod_id, slice_idx);
ul_slice->has_maxmcs = 1;
ul_slice->n_sorting = 0;
/*if (ul_slice->sorting) {
free(ul_slice->sorting);
ul_slice->sorting = NULL;
}
ul_slice->n_sorting = flexran_get_ul_slice_sorting(mod_id, slice_idx, &ul_slice->sorting);
if (ul_slice->n_sorting < 1) ul_slice->sorting = NULL;*/
/*ul_slice->accounting = flexran_get_ul_slice_accounting_policy(mod_id, slice_idx);*/
ul_slice->has_accounting = 0;
const char *s_name = flexran_get_ul_slice_scheduler(mod_id, slice_idx);
if (!ul_slice->scheduler_name
|| strcmp(ul_slice->scheduler_name, s_name) != 0) {
ul_slice->scheduler_name = realloc(ul_slice->scheduler_name, strlen(s_name) + 1);
strcpy(ul_slice->scheduler_name, s_name);
}
}
int check_dl_sorting_update(Protocol__FlexDlSlice *old, Protocol__FlexDlSlice *new)
{
/* sorting_update => true when old->n_sorting == 0 or different numbers of
* elements; otherwise will check * element-wise */
int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting);
for (int i = 0; i < old->n_sorting && !sorting_update; ++i) {
sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]);
}
return sorting_update;
}
int check_ul_sorting_update(Protocol__FlexUlSlice *old, Protocol__FlexUlSlice *new)
{
/* sorting_update => true when old->n_sorting == 0 or different numbers of
* elements; otherwise will check * element-wise */
int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting);
for (int i = 0; i < old->n_sorting && !sorting_update; ++i) {
sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]);
}
return sorting_update;
}
void overwrite_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *exist, Protocol__FlexSliceConfig *update)
{
if (update->has_intraslice_share_active
&& exist->intraslice_share_active != update->intraslice_share_active) {
LOG_I(FLEXRAN_AGENT, "[%d] update intraslice_share_active: %d -> %d\n",
mod_id, exist->intraslice_share_active, update->intraslice_share_active);
exist->intraslice_share_active = update->intraslice_share_active;
exist->has_intraslice_share_active = 1;
}
if (update->has_interslice_share_active
&& exist->interslice_share_active != update->interslice_share_active) {
LOG_I(FLEXRAN_AGENT, "[%d] update interslice_share_active: %d -> %d\n",
mod_id, exist->interslice_share_active, update->interslice_share_active);
exist->interslice_share_active = update->interslice_share_active;
exist->has_interslice_share_active = 1;
}
}
void overwrite_slice_config_dl(mid_t mod_id, Protocol__FlexDlSlice *exist, Protocol__FlexDlSlice *update)
{
if (update->label != exist->label) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update label: %d -> %d\n",
mod_id, update->id, exist->label, update->label);
exist->label = update->label;
exist->has_label = 1;
}
if (update->percentage != exist->percentage) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update percentage: %d -> %d\n",
mod_id, update->id, exist->percentage, update->percentage);
exist->percentage = update->percentage;
exist->has_percentage = 1;
}
if (update->isolation != exist->isolation) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update isolation: %d -> %d\n",
mod_id, update->id, exist->isolation, update->isolation);
exist->isolation = update->isolation;
exist->has_isolation = 1;
}
if (update->priority != exist->priority) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update priority: %d -> %d\n",
mod_id, update->id, exist->priority, update->priority);
exist->priority = update->priority;
exist->has_priority = 1;
}
if (update->position_low != exist->position_low) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_low: %d -> %d\n",
mod_id, update->id, exist->position_low, update->position_low);
exist->position_low = update->position_low;
exist->has_position_low = 1;
}
if (update->position_high != exist->position_high) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_high: %d -> %d\n",
mod_id, update->id, exist->position_high, update->position_high);
exist->position_high = update->position_high;
exist->has_position_high = 1;
}
if (update->maxmcs != exist->maxmcs) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update maxmcs: %d -> %d\n",
mod_id, update->id, exist->maxmcs, update->maxmcs);
exist->maxmcs = update->maxmcs;
exist->has_maxmcs = 1;
}
if (check_dl_sorting_update(exist, update)) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update sorting array\n", mod_id, update->id);
if (exist->n_sorting != update->n_sorting) {
exist->n_sorting = update->n_sorting;
exist->sorting = realloc(exist->sorting, exist->n_sorting * sizeof(Protocol__FlexDlSorting));
if (!exist->sorting) exist->n_sorting = 0;
}
for (int i = 0; i < exist->n_sorting; i++)
exist->sorting[i] = update->sorting[i];
}
if (update->accounting != exist->accounting) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update accounting: %d -> %d\n",
mod_id, update->id, exist->accounting, update->accounting);
exist->accounting = update->accounting;
exist->has_accounting = 1;
}
if (!exist->scheduler_name
|| strcmp(update->scheduler_name, exist->scheduler_name) != 0) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update scheduler: %s -> %s\n",
mod_id, update->id, exist->scheduler_name, update->scheduler_name);
if (exist->scheduler_name) free(exist->scheduler_name);
exist->scheduler_name = strdup(update->scheduler_name);
}
}
void overwrite_slice_config_ul(mid_t mod_id, Protocol__FlexUlSlice *exist, Protocol__FlexUlSlice *update)
{
if (update->label != exist->label) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update label: %d -> %d\n",
mod_id, update->id, exist->label, update->label);
exist->label = update->label;
exist->has_label = 1;
}
if (update->percentage != exist->percentage) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update percentage: %d -> %d\n",
mod_id, update->id, exist->percentage, update->percentage);
exist->percentage = update->percentage;
exist->has_percentage = 1;
}
if (update->isolation != exist->isolation) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update isolation: %d -> %d\n",
mod_id, update->id, exist->isolation, update->isolation);
exist->isolation = update->isolation;
exist->has_isolation = 1;
}
if (update->priority != exist->priority) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update priority: %d -> %d\n",
mod_id, update->id, exist->priority, update->priority);
exist->priority = update->priority;
exist->has_priority = 1;
}
if (update->first_rb != exist->first_rb) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update first_rb: %d -> %d\n",
mod_id, update->id, exist->first_rb, update->first_rb);
exist->first_rb = update ->first_rb;
exist->has_first_rb = 1;
}
/*if (update->lenght_rb != exist->lenght_rb) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update lenght_rb: %d -> %d\n",
mod_id, update->id, exist->lenght_rb, update->lenght_rb);
exist->lenght_rb = update->lenght_rb;
}*/
if (update->maxmcs != exist->maxmcs) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update maxmcs: %d -> %d\n",
mod_id, update->id, exist->maxmcs, update->maxmcs);
exist->maxmcs = update->maxmcs;
exist->has_maxmcs = 1;
}
/* TODO
int sorting_update = 0;
int n = min(exist->n_sorting, update->n_sorting);
int i = 0;
while (i < n && !sorting_update) {
sorting_update = sorting_update || (update->sorting[i] != exist->sorting[i]);
i++;
}
if (sorting_update) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update sorting array\n", update->id, mod_id);
if (exist->n_sorting != update->n_sorting)
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] only writing %d elements\n",
mod_id, update->id, n);
for (i = 0; i < n; i++)
exist->sorting[i] = update->sorting[i];
}
*/
if (update->accounting != exist->accounting) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update accounting: %d -> %d\n",
mod_id, update->id, exist->accounting, update->accounting);
exist->accounting = update->accounting;
exist->has_accounting = 1;
}
if (!exist->scheduler_name
|| strcmp(update->scheduler_name, exist->scheduler_name) != 0) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update scheduler: %s -> %s\n",
mod_id, update->id, exist->scheduler_name, update->scheduler_name);
if (exist->scheduler_name) free(exist->scheduler_name);
exist->scheduler_name = strdup(update->scheduler_name);
}
}
void fill_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *s, Protocol__FlexDlSlice *from)
{
/* function fills slice with information from another slice or with default
* values (currently slice 0) if from is NULL */
/* TODO fill the slice depending on the chosen label */
if (!s->has_label) {
s->has_label = 1;
s->label = from ? from->label : sc_update[mod_id]->dl[0]->label;
}
if (!s->has_percentage) {
s->has_percentage = 1;
s->percentage = from ? from->percentage : sc_update[mod_id]->dl[0]->percentage;
}
if (!s->has_isolation) {
s->has_isolation = 1;
s->isolation = from ? from->isolation : sc_update[mod_id]->dl[0]->isolation;
}
if (!s->has_priority) {
s->has_priority = 1;
s->priority = from ? from->priority : sc_update[mod_id]->dl[0]->priority;
}
if (!s->has_position_low) {
s->has_position_low = 1;
s->position_low = from ? from->position_low : sc_update[mod_id]->dl[0]->position_low;
}
if (!s->has_position_high) {
s->has_position_high = 1;
s->position_high = from ? from->position_high : sc_update[mod_id]->dl[0]->position_high;
}
if (!s->has_maxmcs) {
s->has_maxmcs = 1;
s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->dl[0]->maxmcs;
}
if (s->n_sorting == 0) {
s->n_sorting = from ? from->n_sorting : sc_update[mod_id]->dl[0]->n_sorting;
s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexDlSorting));
if (!s->sorting) s->n_sorting = 0;
for (int i = 0; i < s->n_sorting; ++i)
s->sorting[i] = from ? from->sorting[i] : sc_update[0]->dl[0]->sorting[i];
}
if (!s->has_accounting) {
s->accounting = from ? from->accounting : sc_update[mod_id]->dl[0]->accounting;
}
if (!s->scheduler_name) {
s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->dl[0]->scheduler_name);
}
}
Protocol__FlexDlSlice *get_existing_dl_slice(mid_t mod_id, int id)
{
for (int i = 0; i < sc_update[mod_id]->n_dl; ++i) {
if (id == sc_update[mod_id]->dl[i]->id) {
return sc_update[mod_id]->dl[i];
}
}
return NULL;
}
Protocol__FlexDlSlice *create_new_dl_slice(mid_t mod_id, int id)
{
LOG_I(FLEXRAN_AGENT,
"[%d] Creating DL slice with ID %d, taking default values from DL slice 0\n",
mod_id, id);
Protocol__FlexDlSlice *to = sc_update[mod_id]->dl[sc_update[mod_id]->n_dl];
sc_update[mod_id]->n_dl++;
AssertFatal(sc_update[mod_id]->n_dl <= MAX_NUM_SLICES,
"cannot create more than MAX_NUM_SLICES\n");
to->id = id;
return to;
}
void fill_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *s, Protocol__FlexUlSlice *from)
{
/* function fills slice with information from another slice or with default
* values (currently slice 0) if from is NULL */
/* TODO fill the slice depending on the chosen label */
if (!s->has_label) {
s->has_label = 1;
s->label = from ? from->label : sc_update[mod_id]->ul[0]->label;
}
if (!s->has_percentage) {
s->has_percentage = 1;
s->percentage = from ? from->percentage : sc_update[mod_id]->ul[0]->percentage;
}
if (!s->has_isolation) {
s->has_isolation = 1;
s->isolation = from ? from->isolation : sc_update[mod_id]->ul[0]->isolation;
}
if (!s->has_priority) {
s->has_priority = 1;
s->priority = from ? from->priority : sc_update[mod_id]->ul[0]->priority;
}
if (!s->has_first_rb) {
s->has_first_rb = 1;
s->first_rb = from ? from->first_rb : sc_update[mod_id]->ul[0]->first_rb;
}
if (!s->has_maxmcs) {
s->has_maxmcs = 1;
s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->ul[0]->maxmcs;
}
if (s->n_sorting == 0) {
s->n_sorting = from ? from->n_sorting : sc_update[0]->ul[0]->n_sorting;
s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexUlSorting));
if (!s->sorting) s->n_sorting = 0;
for (int i = 0; i < s->n_sorting; ++i)
s->sorting[i] = from ? from->sorting[i] : sc_update[0]->ul[0]->sorting[i];
}
if (!s->has_accounting) {
s->accounting = from ? from->accounting : sc_update[0]->ul[0]->accounting;
}
if (!s->scheduler_name) {
s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->ul[0]->scheduler_name);
}
}
Protocol__FlexUlSlice *get_existing_ul_slice(mid_t mod_id, int id)
{
for (int i = 0; i < sc_update[mod_id]->n_ul; ++i) {
if (id == sc_update[mod_id]->ul[i]->id) {
return sc_update[mod_id]->ul[i];
}
}
return NULL;
}
Protocol__FlexUlSlice *create_new_ul_slice(mid_t mod_id, int id)
{
LOG_I(FLEXRAN_AGENT,
"[%d] Creating UL slice with ID %d, taking default values from UL slice 0\n",
mod_id, id);
Protocol__FlexUlSlice *to = sc_update[mod_id]->ul[sc_update[mod_id]->n_ul];
sc_update[mod_id]->n_ul++;
AssertFatal(sc_update[mod_id]->n_ul <= MAX_NUM_SLICES,
"cannot create more than MAX_NUM_SLICES\n");
to->id = id;
return to;
}
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *sup)
{
int verified = 1;
if (!sc_update[mod_id]) {
LOG_E(FLEXRAN_AGENT, "Can not update slice policy (no existing slice profile)\n");
return;
}
pthread_mutex_lock(&sc_update_mtx);
/* no need for tests in the current state as there are only two protobuf
* bools for intra-/interslice sharing. The function applies new values if
* applicable */
overwrite_slice_config(mod_id, sc_update[mod_id], sup);
if (sup->n_dl == 0) {
LOG_I(FLEXRAN_AGENT, "[%d] no DL slice configuration in flex_slice_config message\n", mod_id);
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) {
LOG_I(FLEXRAN_AGENT, "remove DL slice ID %d\n", s->id);
const int rc = flexran_remove_dl_slice(mod_id, s);
if (!rc)
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
} else {
/* verify slice parameters */
for (int i = 0; i < sup->n_dl; i++) {
if (!sup->dl[i]->has_id) {
verified = 0;
break;
}
Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id);
/* fill up so that the slice is complete. This way, we don't need to
* worry about it later */
fill_dl_slice(mod_id, sup->dl[i], dls);
verified = verified && flexran_verify_dl_slice(mod_id, sup->dl[i]);
if (!verified) break;
}
/* verify group-based parameters (e.g. sum percentage should not exceed
* 100%). Can be used to perform admission control */
verified = verified && flexran_verify_group_dl_slices(mod_id,
sc_update[mod_id]->dl, sc_update[mod_id]->n_dl, sup->dl, sup->n_dl);
if (verified) {
for (int i = 0; i < sup->n_dl; i++) {
/* if all verifications were successful, get existing slice for ID or
* create new one and overwrite with the update */
Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id);
if (!dls) dls = create_new_dl_slice(mod_id, sup->dl[i]->id);
overwrite_slice_config_dl(mod_id, dls, sup->dl[i]);
}
} else {
LOG_E(FLEXRAN_AGENT, "[%d] DL slice verification failed, refusing application\n", mod_id);
}
LOG_I(FLEXRAN_AGENT, "updating DL slice ID %d\n", s->id);
const int rc = flexran_create_dl_slice(mod_id, s);
if (rc < 0)
LOG_W(FLEXRAN_AGENT,
"error while update slice ID %d: flexran_create_dl_slice() -> %d\n",
s->id, rc);
}
}
verified = 1;
if (sup->n_ul == 0) {
LOG_I(FLEXRAN_AGENT, "[%d] no UL slice configuration in flex_slice_config message\n", mod_id);
void update_or_remove_ul(mid_t mod_id, Protocol__FlexSlice *s) {
if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET
&& !s->label && !s->scheduler) {
LOG_I(FLEXRAN_AGENT, "remove UL slice ID %d\n", s->id);
const int rc = flexran_remove_ul_slice(mod_id, s);
if (!rc)
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
} else {
/* verify slice parameters */
for (int i = 0; i < sup->n_ul; i++) {
if (!sup->ul[i]->has_id) {
verified = 0;
break;
}
Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id);
/* fill up so that the slice is complete. This way, we don't need to
* worry about it later */
fill_ul_slice(mod_id, sup->ul[i], uls);
verified = verified && flexran_verify_ul_slice(mod_id, sup->ul[i]);
if (!verified) break;
}
/* verify group-based parameters (e.g. sum percentage should not exceed
* 100%). Can be used to perform admission control */
verified = verified && flexran_verify_group_ul_slices(mod_id,
sc_update[mod_id]->ul, sc_update[mod_id]->n_ul, sup->ul, sup->n_ul);
if (verified) {
for (int i = 0; i < sup->n_ul; i++) {
/* if all verifications were successful, get existing slice for ID or
* create new one and overwrite with the update */
Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id);
if (!uls) uls = create_new_ul_slice(mod_id, sup->ul[i]->id);
overwrite_slice_config_ul(mod_id, uls, sup->ul[i]);
}
} else {
LOG_E(FLEXRAN_AGENT, "[%d] UL slice verification failed, refusing application\n", mod_id);
}
LOG_I(FLEXRAN_AGENT, "updating UL slice ID %d\n", s->id);
const int rc = flexran_create_ul_slice(mod_id, s);
if (rc < 0)
LOG_W(FLEXRAN_AGENT,
"error while updating slice ID %d: flexran_create_ul_slice() -> %d)\n",
s->id, rc);
}
pthread_mutex_unlock(&sc_update_mtx);
perform_slice_config_update_count = 1;
}
int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news)
{
/* not setting the old configuration is intentional, as it will be picked up
* later when reading the configuration. There is thus a direct feedback
* whether it has been set. */
int changes = 0;
if (olds->intraslice_share_active != news->intraslice_share_active) {
flexran_set_intraslice_sharing_active(mod_id, news->intraslice_share_active);
changes++;
}
if (olds->interslice_share_active != news->interslice_share_active) {
flexran_set_interslice_sharing_active(mod_id, news->interslice_share_active);
changes++;
}
return changes;
}
int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc)
{
/* not setting the old configuration is intentional, as it will be picked up
* later when reading the configuration. There is thus a direct feedback
* whether it has been set. */
int changes = 0;
int slice_idx = flexran_find_dl_slice(mod_id, newc->id);
if (slice_idx < 0) {
LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id);
return 0;
}
if (oldc->percentage != newc->percentage) {
flexran_set_dl_slice_percentage(mod_id, slice_idx, newc->percentage);
changes++;
}
if (oldc->isolation != newc->isolation) {
flexran_set_dl_slice_isolation(mod_id, slice_idx, newc->isolation);
changes++;
}
if (oldc->priority != newc->priority) {
flexran_set_dl_slice_priority(mod_id, slice_idx, newc->priority);
changes++;
}
if (oldc->position_low != newc->position_low) {
flexran_set_dl_slice_position_low(mod_id, slice_idx, newc->position_low);
changes++;
}
if (oldc->position_high != newc->position_high) {
flexran_set_dl_slice_position_high(mod_id, slice_idx, newc->position_high);
changes++;
}
if (oldc->maxmcs != newc->maxmcs) {
flexran_set_dl_slice_maxmcs(mod_id, slice_idx, newc->maxmcs);
changes++;
}
if (check_dl_sorting_update(oldc, newc)) {
flexran_set_dl_slice_sorting(mod_id, slice_idx, newc->sorting, newc->n_sorting);
changes++;
}
if (oldc->accounting != newc->accounting) {
flexran_set_dl_slice_accounting_policy(mod_id, slice_idx, newc->accounting);
changes++;
}
if (!oldc->scheduler_name
|| strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) {
int ret = flexran_set_dl_slice_scheduler(mod_id, slice_idx, newc->scheduler_name);
AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n",
newc->id, slice_idx);
changes++;
}
return changes;
}
int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc)
{
/* not setting the old configuration is intentional, as it will be picked up
* later when reading the configuration. There is thus a direct feedback
* whether it has been set. */
int changes = 0;
int slice_idx = flexran_find_ul_slice(mod_id, newc->id);
if (slice_idx < 0) {
LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id);
return 0;
}
if (oldc->percentage != newc->percentage) {
flexran_set_ul_slice_percentage(mod_id, slice_idx, newc->percentage);
changes++;
}
if (oldc->isolation != newc->isolation) {
/*flexran_set_ul_slice_isolation(mod_id, slice_idx, newc->isolation);
*changes++;*/
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting isolation is not supported\n",
mod_id, newc->id);
}
if (oldc->priority != newc->priority) {
/*flexran_set_ul_slice_priority(mod_id, slice_idx, newc->priority);
*changes++;*/
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the priority is not supported\n",
mod_id, newc->id);
}
if (oldc->first_rb != newc->first_rb) {
flexran_set_ul_slice_first_rb(mod_id, slice_idx, newc->first_rb);
changes++;
}
/*if (oldc->length_rb != newc->length_rb) {
flexran_set_ul_slice_length_rb(mod_id, slice_idx, newc->length_rb);
changes++;
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting length_rb is not supported\n",
mod_id, newc->id);
}*/
if (oldc->maxmcs != newc->maxmcs) {
flexran_set_ul_slice_maxmcs(mod_id, slice_idx, newc->maxmcs);
changes++;
}
/*if (check_ul_sorting_update(oldc, newc)) {
flexran_set_ul_slice_sorting(mod_id, slice_idx, newc->sorting, n);
changes++;
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the sorting is not supported\n",
mod_id, newc->id);
}*/
if (oldc->accounting != newc->accounting) {
/*flexran_set_ul_slice_accounting_policy(mod_id, slice_idx, newc->accounting);
*changes++;*/
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the accounting is not supported\n",
mod_id, newc->id);
}
if (!oldc->scheduler_name
|| strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) {
int ret = flexran_set_ul_slice_scheduler(mod_id, slice_idx, newc->scheduler_name);
AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n",
newc->id, slice_idx);
changes++;
}
return changes;
}
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config)
{
if (n_ue_slice_assoc_updates == MAX_NUM_SLICES) {
LOG_E(FLEXRAN_AGENT,
"[%d] can not handle flex_ue_config message, buffer is full; try again later\n",
mod_id);
void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *dl) {
if (!dl)
return;
Protocol__FlexSliceAlgorithm dl_algo = flexran_get_dl_slice_algo(mod_id);
if (dl->has_algorithm && dl_algo != dl->algorithm) {
LOG_I(FLEXRAN_AGENT, "loading new DL slice algorithm %d\n", dl->algorithm);
dl_algo = dl->algorithm;
flexran_set_dl_slice_algo(mod_id, dl_algo);
}
/* first update existing slices, then create new. Thus, we go through the
* list twice. First round, if a slice exists, handle and mark as such. Then,
* apply all others in the second round */
if (dl->n_slices > 0) {
if (dl_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n");
return;
}
int handled_dl[dl->n_slices];
for (int i = 0; i < dl->n_slices; ++i) {
if (flexran_find_dl_slice(mod_id, dl->slices[i]->id) < 0) {
handled_dl[i] = 0;
continue;
}
update_or_remove_dl(mod_id, dl->slices[i]);
handled_dl[i] = 1;
}
for (int i = 0; i < dl->n_slices; ++i) {
if (handled_dl[i])
continue;
update_or_remove_dl(mod_id, dl->slices[i]);
}
}
if (dl->scheduler) {
if (dl_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
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);
if (rc < 0) {
LOG_E(FLEXRAN_AGENT,
"error while updating scheduling algorithm: "
"flexran_update_dl_sched_algo() -> %d)\n",
rc);
return;
}
}
}
void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *ul) {
if (!ul)
return;
Protocol__FlexSliceAlgorithm ul_algo = flexran_get_ul_slice_algo(mod_id);
if (ul->has_algorithm && ul_algo != ul->algorithm) {
LOG_I(FLEXRAN_AGENT, "loading new UL slice algorithm %d\n", ul->algorithm);
ul_algo = ul->algorithm;
flexran_set_ul_slice_algo(mod_id, ul_algo);
}
if (ul->n_slices > 0) {
if (ul_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n");
return;
}
int handled_ul[ul->n_slices];
for (int i = 0; i < ul->n_slices; ++i) {
if (flexran_find_ul_slice(mod_id, ul->slices[i]->id) < 0) {
handled_ul[i] = 0;
continue;
}
update_or_remove_ul(mod_id, ul->slices[i]);
handled_ul[i] = 1;
}
for (int i = 0; i < ul->n_slices; ++i) {
if (handled_ul[i])
continue;
update_or_remove_ul(mod_id, ul->slices[i]);
}
}
if (ul->scheduler) {
if (ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
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);
if (rc < 0) {
LOG_E(FLEXRAN_AGENT,
"error while updating scheduling algorithm: "
"flexran_update_dl_sched_algo() -> %d)\n",
rc);
return;
}
}
}
int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config)
{
if (!ue_config->has_rnti) {
LOG_E(FLEXRAN_AGENT,
"[%d] cannot update UE to slice association, no RNTI in flex_ue_config message\n",
mod_id);
return;
return 0;
}
if (ue_config->has_dl_slice_id)
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to DL slice ID %d\n",
mod_id, ue_config->rnti, ue_config->dl_slice_id);
if (ue_config->has_ul_slice_id)
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to UL slice ID %d\n",
mod_id, ue_config->rnti, ue_config->ul_slice_id);
ue_slice_assoc_update[n_ue_slice_assoc_updates++] = ue_config;
perform_slice_config_update_count = 2;
}
int apply_ue_slice_assoc_update(mid_t mod_id)
{
int i;
int changes = 0;
for (i = 0; i < n_ue_slice_assoc_updates; i++) {
int ue_id = find_UE_id(mod_id, ue_slice_assoc_update[i]->rnti);
if (ue_id < 0 || ue_id > MAX_MOBILES_PER_ENB){
LOG_E(FLEXRAN_AGENT,"UE_id %d is wrong!!\n",ue_id);
continue;
}
if (ue_slice_assoc_update[i]->has_dl_slice_id) {
int slice_idx = flexran_find_dl_slice(mod_id, ue_slice_assoc_update[i]->dl_slice_id);
if (flexran_dl_slice_exists(mod_id, slice_idx)) {
flexran_set_ue_dl_slice_idx(mod_id, ue_id, slice_idx);
changes++;
} else {
LOG_W(FLEXRAN_AGENT, "[%d] DL slice %d does not exist, refusing change\n",
mod_id, ue_slice_assoc_update[i]->dl_slice_id);
}
}
if (ue_slice_assoc_update[i]->has_ul_slice_id) {
int slice_idx = flexran_find_ul_slice(mod_id, ue_slice_assoc_update[i]->ul_slice_id);
if (flexran_ul_slice_exists(mod_id, slice_idx)) {
flexran_set_ue_ul_slice_idx(mod_id, ue_id, slice_idx);
changes++;
} else {
LOG_W(FLEXRAN_AGENT, "[%d] UL slice %d does not exist, refusing change\n",
mod_id, ue_slice_assoc_update[i]->ul_slice_id);
}
int UE_id = flexran_get_mac_ue_id_rnti(mod_id, ue_config->rnti);
if (ue_config->has_dl_slice_id) {
if (flexran_get_dl_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
LOG_E(FLEXRAN_AGENT, "no DL slice algorithm loaded\n");
} else {
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to DL slice ID %d\n",
mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->dl_slice_id);
flexran_set_ue_dl_slice_id(mod_id, UE_id, ue_config->dl_slice_id);
}
}
n_ue_slice_assoc_updates = 0;
return changes;
if (ue_config->has_ul_slice_id) {
if (flexran_get_ul_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
LOG_E(FLEXRAN_AGENT, "no UL slice algorithm loaded\n");
} else {
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to UL slice ID %d\n",
mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->ul_slice_id);
flexran_set_ue_ul_slice_id(mod_id, UE_id, ue_config->ul_slice_id);
}
}
return 0;
}
@@ -103,43 +103,11 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name);
/*** Functions for handling a slice config ***/
/* allocate memory for a Protocol__FlexSliceConfig structure with n_dl DL slice
* configs and m_ul UL slice configs */
Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul);
/* read the general slice parameters via RAN into the given
* Protocol__FlexSliceConfig struct */
void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s);
/* read the DL slice config via the RAN into a given Protocol__FlexDlSlice
* struct */
void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice);
/* read the UL slice config via the RAN into a given Protocol__FlexUlSlice
* struct */
void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice);
/* reads content of slice over the sc_update structure, so that it can be
* applied later by performing a diff between slice_config and sc_update */
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *slice);
/* apply generic slice parameters (e.g. intra-/interslice sharing activated or
* not) if there are changes. Returns the number of changed parameters. */
int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news);
/* apply new configuration of slice in DL if there are changes between the
* parameters. Returns the number of changed parameters. */
int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc);
/* apply new configuration of slice in UL if there are changes between the
* parameters. Returns the number of changed parameters. */
int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc);
/* inserts a new ue_config into the structure keeping ue to slice association
* updates and marks so it can be applied */
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config);
/* Prepare the application of a slicing config */
void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *slice);
void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *slice);
/* apply a new association between a UE and a slice (both DL and UL) */
int apply_ue_slice_assoc_update(mid_t mod_id);
int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config);
#endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/
@@ -28,346 +28,3 @@
#include "flexran_agent_mac_slice_verification.h"
/* overlap check for UL slices, helper type */
struct sregion_s {
int start;
int length;
};
/* forward declaration of locally-used verification functions */
int flexran_dl_slice_verify_pct(int pct);
int flexran_dl_slice_verify_priority(int prio);
int flexran_dl_slice_verify_position(int pos_low, int pos_high);
int flexran_dl_slice_verify_maxmcs(int maxmcs);
int flexran_ul_slice_verify_pct(int pct);
int flexran_ul_slice_verify_priority(int prio);
int flexran_ul_slice_verify_first_rb(int first_rb);
int flexran_ul_slice_verify_maxmcs(int maxmcs);
int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n);
int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls)
{
/* check mandatory parameters */
if (!dls->has_id) {
LOG_E(FLEXRAN_AGENT, "[%d] Incoming DL slice configuration has no ID\n", mod_id);
return 0;
}
/* verify parameters individualy */
/* label is enum */
if (!flexran_dl_slice_verify_pct(dls->percentage)) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice percentage (%d)\n",
mod_id, dls->id, dls->percentage);
return 0;
}
/* isolation is a protobuf bool */
if (!flexran_dl_slice_verify_priority(dls->priority)) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice priority (%d)\n",
mod_id, dls->id, dls->priority);
return 0;
}
if (!flexran_dl_slice_verify_position(dls->position_low, dls->position_high)) {
LOG_E(FLEXRAN_AGENT,
"[%d][DL slice %d] illegal DL slice position low (%d) and/or high (%d)\n",
mod_id, dls->id, dls->position_low, dls->position_high);
return 0;
}
if (!flexran_dl_slice_verify_maxmcs(dls->maxmcs)) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice max mcs %d\n",
mod_id, dls->id, dls->maxmcs);
return 0;
}
if (dls->n_sorting == 0) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting in DL slice\n",
mod_id, dls->id);
return 0;
}
if (!dls->sorting) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting found in DL slice\n",
mod_id, dls->id);
return 0;
}
/* sorting is an enum */
/* accounting is an enum */
if (!dls->scheduler_name) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no scheduler name found\n",
mod_id, dls->id);
return 0;
}
if (strcmp(dls->scheduler_name, "schedule_ue_spec") != 0) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] setting the scheduler to something "
"different than schedule_ue_spec is currently not allowed\n",
mod_id, dls->id);
return 0;
}
return 1;
}
int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing,
int n_ex, Protocol__FlexDlSlice **update, int n_up)
{
int i, j, n;
int pct, pct_orig;
/* for every update, array points to existing slice, or NULL if update
* creates new slice */
Protocol__FlexDlSlice *s[n_up];
for (i = 0; i < n_up; i++) {
s[i] = NULL;
for (j = 0; j < n_ex; j++) {
if (existing[j]->id == update[i]->id)
s[i] = existing[j];
}
}
/* check that number of created and number of added slices in total matches
* [1,10] */
n = n_ex;
for (i = 0; i < n_up; i++) {
/* new slice */
if (!s[i]) n += 1;
/* slice will be deleted */
else if (s[i]->percentage == 0) n -= 1;
/* else "only" an update */
}
if (n < 1 || n > MAX_NUM_SLICES) {
LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting DL slices (%d -> %d)\n",
mod_id, n_ex, n);
return 0;
}
/* check that the sum of all slices percentages (including removed/added
* slices) matches [1,100] */
pct = 0;
for (i = 0; i < n_ex; i++) {
pct += existing[i]->percentage;
}
pct_orig = pct;
for (i = 0; i < n_up; i++) {
/* if there is an existing slice, subtract its percentage and add the
* update's percentage */
if (s[i])
pct -= s[i]->percentage;
pct += update[i]->percentage;
}
if (pct < 1 || pct > 100) {
LOG_E(FLEXRAN_AGENT,
"[%d] invalid total RB share for DL slices (%d%% -> %d%%)\n",
mod_id, pct_orig, pct);
return 0;
}
return 1;
}
int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls)
{
/* check mandatory parameters */
if (!uls->has_id) {
LOG_E(FLEXRAN_AGENT, "[%d] Incoming UL slice configuration has no ID\n", mod_id);
return 0;
}
/* verify parameters individually */
/* label is enum */
if (!flexran_ul_slice_verify_pct(uls->percentage)) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n",
mod_id, uls->id, uls->percentage);
return 0;
}
/* isolation is a protobuf bool */
if (!flexran_ul_slice_verify_priority(uls->priority)) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n",
mod_id, uls->id, uls->priority);
return 0;
}
if (!flexran_ul_slice_verify_first_rb(uls->first_rb)) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice first RB (%d)\n",
mod_id, uls->id, uls->first_rb);
return 0;
}
if (!flexran_ul_slice_verify_maxmcs(uls->maxmcs)) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice max mcs (%d)\n",
mod_id, uls->id, uls->maxmcs);
return 0;
}
/* TODO
if (uls->n_sorting == 0) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting in UL slice\n",
mod_id, uls->id);
return 0;
}
if (!uls->sorting) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting found in UL slice\n",
mod_id, uls->id);
return 0;
}
*/
/* sorting is an enum */
/* accounting is an enum */
if (!uls->scheduler_name) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no scheduler name found\n",
mod_id, uls->id);
return 0;
}
if (strcmp(uls->scheduler_name, "schedule_ulsch_rnti") != 0) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] setting the scheduler to something "
"different than schedule_ulsch_rnti is currently not allowed\n",
mod_id, uls->id);
return 0;
}
return 1;
}
int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing,
int n_ex, Protocol__FlexUlSlice **update, int n_up)
{
int i, j, n;
int pct, pct_orig;
/* for every update, array "s" points to existing slice, or NULL if update
* creates new slice; array "offs" gives the offset of this slice */
Protocol__FlexUlSlice *s[n_up];
int offs[n_up];
for (i = 0; i < n_up; i++) {
s[i] = NULL;
offs[i] = 0;
for (j = 0; j < n_ex; j++) {
if (existing[j]->id == update[i]->id) {
s[i] = existing[j];
offs[i] = j;
}
}
}
/* check that number of created and number of added slices in total matches
* [1,10] */
n = n_ex;
for (i = 0; i < n_up; i++) {
/* new slice */
if (!s[i]) n += 1;
/* slice will be deleted */
else if (s[i]->percentage == 0) n -= 1;
/* else "only" an update */
}
if (n < 1 || n > MAX_NUM_SLICES) {
LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting UL slices (%d -> %d)\n",
mod_id, n_ex, n);
return 0;
}
/* check that the sum of all slices percentages (including removed/added
* slices) matches [1,100] */
pct = 0;
for (i = 0; i < n_ex; i++) {
pct += existing[i]->percentage;
}
pct_orig = pct;
for (i = 0; i < n_up; i++) {
/* if there is an existing slice, subtract its percentage and add the
* update's percentage */
if (s[i])
pct -= s[i]->percentage;
pct += update[i]->percentage;
}
if (pct < 1 || pct > 100) {
LOG_E(FLEXRAN_AGENT, "[%d] invalid total RB share (%d%% -> %d%%)\n",
mod_id, pct_orig, pct);
return 0;
}
/* check that there is no overlap in slices resulting as the combination of
* first_rb and percentage */
struct sregion_s sregion[n];
const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */
int k = n_ex;
for (i = 0; i < n_ex; i++) {
sregion[i].start = existing[i]->first_rb;
sregion[i].length = existing[i]->percentage * N_RB / 100;
}
for (i = 0; i < n_up; i++) {
ptrdiff_t d = s[i] ? offs[i] : k++;
AssertFatal(d >= 0 && d < k, "illegal pointer offset (%ld, k=%d)\n", d, k);
sregion[d].start = update[i]->first_rb;
sregion[d].length = update[i]->percentage * N_RB / 100;
}
AssertFatal(k == n, "illegal number of slices while calculating overlap\n");
if (!check_ul_slice_overlap(mod_id, sregion, k)) {
LOG_E(FLEXRAN_AGENT, "[%d] UL slices are overlapping\n", mod_id);
return 0;
}
return 1;
}
int flexran_dl_slice_verify_pct(int pct)
{
return pct >= 0 && pct <= 100;
}
int flexran_dl_slice_verify_priority(int prio)
{
return prio >= 0;
}
int flexran_dl_slice_verify_position(int pos_low, int pos_high)
{
return pos_low < pos_high && pos_low >= 0 && pos_high <= N_RBG_MAX;
}
int flexran_dl_slice_verify_maxmcs(int maxmcs)
{
return maxmcs >= 0 && maxmcs <= 28;
}
int flexran_ul_slice_verify_pct(int pct)
{
return pct >= 0 && pct <= 100;
}
int flexran_ul_slice_verify_priority(int prio)
{
return prio >= 0;
}
int flexran_ul_slice_verify_first_rb(int first_rb)
{
return first_rb >= 0 && first_rb < 100;
}
int flexran_ul_slice_verify_maxmcs(int maxmcs)
{
return maxmcs >= 0 && maxmcs <= 20;
}
int sregion_compare(const void *_a, const void *_b)
{
const struct sregion_s *a = (const struct sregion_s *)_a;
const struct sregion_s *b = (const struct sregion_s *)_b;
const int res = a->start - b->start;
if (res < 0) return -1;
else if (res == 0) return 0;
else return 1;
}
int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n)
{
int i;
int overlap, op, u;
const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */
qsort(sr, n, sizeof(sr[0]), sregion_compare);
for (i = 0; i < n; i++) {
u = i == n-1 ? N_RB : sr[i+1].start;
AssertFatal(sr[i].start <= u, "unsorted slice list\n");
overlap = sr[i].start + sr[i].length - u;
if (overlap <= 0) continue;
op = overlap * 100 / sr[i].length;
LOG_W(FLEXRAN_AGENT, "[%d] slice overlap of %d%% detected\n", mod_id, op);
if (op >= 10) /* more than 10% overlap -> refuse */
return 0;
}
return 1;
}
@@ -29,9 +29,3 @@
#include "flexran_agent_common_internal.h"
#include "flexran_agent_mac_internal.h"
int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls);
int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing,
int n_ex, Protocol__FlexDlSlice **update, int n_up);
int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls);
int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing,
int n_ex, Protocol__FlexUlSlice **update, int n_up);
@@ -125,6 +125,63 @@ void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply) {
}
}
void flexran_agent_handle_mme_update(mid_t mod_id,
size_t n_mme,
Protocol__FlexS1apMme **mme) {
if (n_mme == 0 || n_mme > 1) {
LOG_E(FLEXRAN_AGENT, "cannot handle %lu MMEs yet\n", n_mme);
return;
}
if (!mme[0]->s1_ip) {
LOG_E(FLEXRAN_AGENT, "no S1 IP present, cannot handle request\n");
return;
}
if (mme[0]->has_state
&& mme[0]->state == PROTOCOL__FLEX_MME_STATE__FLMMES_DISCONNECTED) {
int rc = flexran_remove_s1ap_mme(mod_id, 1, &mme[0]->s1_ip);
if (rc == 0)
LOG_I(FLEXRAN_AGENT, "remove MME at IP %s\n", mme[0]->s1_ip);
else
LOG_W(FLEXRAN_AGENT,
"could not remove MME: flexran_remove_s1ap_mme() returned %d\n",
rc);
} else {
int rc = flexran_add_s1ap_mme(mod_id, 1, &mme[0]->s1_ip);
if (rc == 0)
LOG_I(FLEXRAN_AGENT, "add MME at IP %s\n", mme[0]->s1_ip);
else
LOG_W(FLEXRAN_AGENT,
"could not add MME: flexran_add_s1ap_mme() returned %d\n",
rc);
}
}
void flexran_agent_handle_plmn_update(mid_t mod_id,
int CC_id,
size_t n_plmn,
Protocol__FlexPlmn **plmn_id) {
if (n_plmn < 1 || n_plmn > 6) {
LOG_E(FLEXRAN_AGENT, "cannot handle %lu PLMNs\n", n_plmn);
return;
}
/* We assume the controller has checked all the parameters within each
* plmn_id */
int rc = flexran_set_new_plmn_id(mod_id, CC_id, n_plmn, plmn_id);
if (rc == 0) {
LOG_I(FLEXRAN_AGENT, "set %lu new PLMNs:\n", n_plmn);
for (int i = 0; i < (int)n_plmn; ++i)
LOG_I(FLEXRAN_AGENT, " MCC %d MNC %d MNC length %d\n",
plmn_id[i]->mcc, plmn_id[i]->mnc, plmn_id[0]->mnc_length);
} else {
LOG_W(FLEXRAN_AGENT,
"could not set new PLMN configuration: flexran_set_new_plmn_id() returned %d\n",
rc);
}
}
int flexran_agent_register_s1ap_xface(mid_t mod_id) {
if (agent_s1ap_xface[mod_id]) {
LOG_E(FLEXRAN_AGENT, "S1AP agent CM for eNB %d is already registered\n", mod_id);
@@ -60,6 +60,17 @@ int flexran_agent_s1ap_stats_reply(mid_t mod_id,
/* Free allocated S1AP stats message */
void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply);
/* Add or remove MME updates */
void flexran_agent_handle_mme_update(mid_t mod_id,
size_t n_mme,
Protocol__FlexS1apMme **mme);
/* Set a new PLMN configuration */
void flexran_agent_handle_plmn_update(mid_t mod_id,
int CC_id,
size_t n_plmn,
Protocol__FlexPlmn **plmn_id);
/* Register technology specific interface callbacks */
int flexran_agent_register_s1ap_xface(mid_t mod_id);
+3
View File
@@ -58,6 +58,7 @@
#define CONFIG_STRING_MACRLC_SCHED_MODE "scheduler_mode"
#define CONFIG_MACRLC_PUSCH10xSNR "puSch10xSnr"
#define CONFIG_MACRLC_PUCCH10xSNR "puCch10xSnr"
#define CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO "default_sched_dl_algo"
/*-------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* MacRLC configuration parameters */
@@ -84,6 +85,7 @@
{CONFIG_STRING_MACRLC_SCHED_MODE, NULL, 0, strptr:NULL, defstrval:"default", TYPE_STRING, 0}, \
{CONFIG_MACRLC_PUSCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \
{CONFIG_MACRLC_PUCCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \
{CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO, NULL, 0, strptr:NULL, defstrval:"round_robin_dl", TYPE_STRING, 0}, \
}
#define MACRLC_CC_IDX 0
#define MACRLC_TRANSPORT_N_PREFERENCE_IDX 1
@@ -105,6 +107,7 @@
#define MACRLC_SCHED_MODE_IDX 17
#define MACRLC_PUSCH10xSNR_IDX 18
#define MACRLC_PUCCH10xSNR_IDX 19
#define MACRLC_DEFAULT_SCHED_DL_ALGO_IDX 20
/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/
#endif
@@ -61,82 +61,30 @@ enum flex_qam {
//
// Slice config related structures and enums
//
enum flex_dl_sorting {
CR_ROUND = 0; // Highest HARQ first
CR_SRB12 = 1; // Highest SRB1+2 first
CR_HOL = 2; // Highest HOL first
CR_LC = 3; // Greatest RLC buffer first
CR_CQI = 4; // Highest CQI first
CR_LCP = 5; // Highest LC priority first
enum flex_slice_algorithm {
None = 0;
Static = 1;
NVS = 2;
}
enum flex_ul_sorting {
CRU_ROUND = 0; // Highest HARQ first
CRU_BUF = 1; // Highest BSR first
CRU_BTS = 2; // More bytes to schedule first
CRU_MCS = 3; // Highest MCS first
CRU_LCP = 4; // Highest LC priority first
CRU_HOL = 5; // Highest HOL first
message flex_slice_static {
optional uint32 posLow = 1;
optional uint32 posHigh = 2;
}
enum flex_dl_accounting_policy {
POL_FAIR = 0;
POL_GREEDY = 1;
POL_NUM = 2;
message flex_slice {
optional uint32 id = 1;
optional string label = 2;
optional string scheduler = 3;
oneof params {
flex_slice_static static = 10;
}
}
enum flex_ul_accounting_policy {
POLU_FAIR = 0;
POLU_GREEDY = 1;
POLU_NUM = 2;
}
enum flex_slice_label {
xMBB = 0;
URLLC = 1;
mMTC = 2;
xMTC = 3;
Other = 4;
}
message flex_dl_slice {
optional uint32 id = 1;
optional flex_slice_label label = 2;
// should be between 0 and 100
optional uint32 percentage = 3;
// whether this slice should be exempted form interslice sharing
optional bool isolation = 4;
// increasing value means increasing prio
optional uint32 priority = 5;
// min and max RB to use (in frequency) in the range [0, N_RBG_MAX]
optional uint32 position_low = 6;
optional uint32 position_high = 7;
// maximum MCS to be allowed in this slice
optional uint32 maxmcs = 8;
repeated flex_dl_sorting sorting = 9;
optional flex_dl_accounting_policy accounting = 10;
optional string scheduler_name = 11;
}
message flex_ul_slice {
optional uint32 id = 1;
optional flex_slice_label label = 2;
// should be between 0 and 100
optional uint32 percentage = 3;
// whether this slice should be exempted form interslice sharing
optional bool isolation = 4;
// increasing value means increasing prio
optional uint32 priority = 5;
// RB start to use (in frequency) in the range [0, N_RB_MAX]
optional uint32 first_rb = 6;
// TODO RB number
//optional uint32 length_rb = 7;
// maximum MCS to be allowed in this slice
optional uint32 maxmcs = 8;
repeated flex_ul_sorting sorting = 9;
optional flex_ul_accounting_policy accounting = 10;
optional string scheduler_name = 11;
message flex_slice_dl_ul_config {
optional flex_slice_algorithm algorithm = 1;
repeated flex_slice slices = 2;
optional string scheduler = 3; // if no slicing
}
//
@@ -49,14 +49,8 @@ message flex_cell_config {
}
message flex_slice_config {
// whether remaining RBs after first intra-slice allocation will
// be allocated to UEs of the same slice
optional bool intraslice_share_active = 3;
// whether remaining RBs after slice allocation will be allocated
// to UEs of another slice. Isolated slices will be ignored.
optional bool interslice_share_active = 4;
repeated flex_dl_slice dl = 1;
repeated flex_ul_slice ul = 2;
optional flex_slice_dl_ul_config dl = 6;
optional flex_slice_dl_ul_config ul = 7;
}
message flex_ue_config {
-1
View File
@@ -268,7 +268,6 @@ void *eNB_app_task(void *args_p) {
if (EPC_MODE_ENABLED) {
LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
S1AP_REGISTER_ENB_CNF(msg_p).nb_mme);
DevAssert(register_enb_pending > 0);
register_enb_pending--;
/* Check if at least eNB is registered with one MME */
+11
View File
@@ -29,6 +29,7 @@
#include <string.h>
#include <inttypes.h>
#include <dlfcn.h>
#include "common/utils/LOG/log.h"
#include "assertions.h"
@@ -260,6 +261,16 @@ void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) {
global_scheduler_mode=SCHED_MODE_DEFAULT;
printf("sched mode = default %d [%s]\n",global_scheduler_mode,*(MacRLC_ParamList.paramarray[j][MACRLC_SCHED_MODE_IDX].strptr));
}
char *s = *MacRLC_ParamList.paramarray[j][MACRLC_DEFAULT_SCHED_DL_ALGO_IDX].strptr;
void *d = dlsym(NULL, s);
AssertFatal(d, "%s(): no default scheduler DL algo '%s' found\n", __func__, s);
// release default, add new
pp_impl_param_t *dl_pp = &RC.mac[j]->pre_processor_dl;
dl_pp->dl_algo.unset(&dl_pp->dl_algo.data);
dl_pp->dl_algo = *(default_sched_dl_algo_t *) d;
dl_pp->dl_algo.data = dl_pp->dl_algo.setup();
LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", dl_pp->dl_algo.name);
}// j=0..num_inst
} /*else {// MacRLC_ParamList.numelt > 0 // ignore it
+38 -43
View File
@@ -306,6 +306,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
if (reply->cell_config[i]->mbsfn_subframe_config_sfalloc)
free(reply->cell_config[i]->mbsfn_subframe_config_sfalloc);
/* si_config is shared between MAC and RRC, free here */
if (reply->cell_config[i]->si_config) {
for(int j = 0; j < reply->cell_config[i]->si_config->n_si_message; j++) {
free(reply->cell_config[i]->si_config->si_message[j]);
@@ -316,26 +317,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
}
if (reply->cell_config[i]->slice_config) {
for (int j = 0; j < reply->cell_config[i]->slice_config->n_dl; ++j) {
if (reply->cell_config[i]->slice_config->dl[j]->n_sorting > 0)
free(reply->cell_config[i]->slice_config->dl[j]->sorting);
free(reply->cell_config[i]->slice_config->dl[j]->scheduler_name);
free(reply->cell_config[i]->slice_config->dl[j]);
}
free(reply->cell_config[i]->slice_config->dl);
for (int j = 0; j < reply->cell_config[i]->slice_config->n_ul; ++j) {
if (reply->cell_config[i]->slice_config->ul[j]->n_sorting > 0)
free(reply->cell_config[i]->slice_config->ul[j]->sorting);
free(reply->cell_config[i]->slice_config->ul[j]->scheduler_name);
free(reply->cell_config[i]->slice_config->ul[j]);
}
free(reply->cell_config[i]->slice_config->ul);
free(reply->cell_config[i]->slice_config);
flexran_agent_destroy_mac_slice_config(reply->cell_config[i]);
}
free(reply->cell_config[i]);
@@ -893,31 +875,40 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
Protocol__FlexEnbConfigReply *enb_config = input->enb_config_reply_msg;
if (enb_config->n_cell_config == 0) {
LOG_W(FLEXRAN_AGENT,
"received enb_config_reply message does not contain a cell_config\n");
*msg = NULL;
return 0;
}
if (enb_config->n_cell_config > 1)
LOG_W(FLEXRAN_AGENT, "ignoring slice configs for other cell except cell 0\n");
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);
} else if (enb_config->cell_config[0]->has_eutra_band
&& enb_config->cell_config[0]->has_dl_freq
&& enb_config->cell_config[0]->has_ul_freq
&& enb_config->cell_config[0]->has_dl_bandwidth) {
initiate_soft_restart(mod_id, enb_config->cell_config[0]);
} else if (flexran_agent_get_rrc_xface(mod_id)
&& enb_config->cell_config[0]->has_x2_ho_net_control) {
LOG_I(FLEXRAN_AGENT,
"setting X2 HO NetControl to %d\n",
enb_config->cell_config[0]->x2_ho_net_control);
const int rc = flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control);
if (rc < 0)
LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network");
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);
}
if (enb_config->cell_config[0]->has_eutra_band
&& enb_config->cell_config[0]->has_dl_freq
&& enb_config->cell_config[0]->has_ul_freq
&& enb_config->cell_config[0]->has_dl_bandwidth) {
initiate_soft_restart(mod_id, enb_config->cell_config[0]);
}
if (flexran_agent_get_rrc_xface(mod_id)
&& enb_config->cell_config[0]->has_x2_ho_net_control) {
LOG_I(FLEXRAN_AGENT,
"setting X2 HO NetControl to %d\n",
enb_config->cell_config[0]->x2_ho_net_control);
const int rc = flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control);
if (rc < 0)
LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network");
}
if (flexran_agent_get_rrc_xface(mod_id) && enb_config->cell_config[0]->n_plmn_id > 0) {
flexran_agent_handle_plmn_update(mod_id,
0,
enb_config->cell_config[0]->n_plmn_id,
enb_config->cell_config[0]->plmn_id);
}
}
if (flexran_agent_get_s1ap_xface(mod_id) && enb_config->s1ap) {
flexran_agent_handle_mme_update(mod_id,
enb_config->s1ap->n_mme,
enb_config->s1ap->mme);
}
*msg = NULL;
@@ -930,7 +921,11 @@ int flexran_agent_handle_ue_config_reply(mid_t mod_id, const void *params, Proto
Protocol__FlexUeConfigReply *ue_config_reply = input->ue_config_reply_msg;
for (i = 0; flexran_agent_get_mac_xface(mod_id) && i < ue_config_reply->n_ue_config; i++)
prepare_ue_slice_assoc_update(mod_id, ue_config_reply->ue_config[i]);
prepare_ue_slice_assoc_update(mod_id, &ue_config_reply->ue_config[i]);
/* prepare_ue_slice_assoc_update takes ownership of the individual
* FlexUeConfig messages. Therefore, mark zero messages to not accidentally
* free them twice */
ue_config_reply->n_ue_config = 0;
*msg = NULL;
return 0;
+407 -422
View File
@@ -30,6 +30,7 @@
#include "flexran_agent_ran_api.h"
#include "s1ap_eNB_ue_context.h"
#include "s1ap_eNB_management_procedures.h"
#include "openair2/LAYER2/MAC/slicing/slicing.h"
static inline int phy_is_present(mid_t mod_id, uint8_t cc_id) {
return RC.eNB && RC.eNB[mod_id] && RC.eNB[mod_id][cc_id];
@@ -3013,471 +3014,293 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti)
}
/**************************** SLICING ****************************/
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
if (!mac_is_present(mod_id)) return -1;
Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id) {
if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id];
if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl)
return RC.mac[mod_id]->slice_info.dl[slice_idx].id;
return 0;
switch (RC.mac[mod_id]->pre_processor_dl.algorithm) {
case STATIC_SLICING:
return PROTOCOL__FLEX_SLICE_ALGORITHM__Static;
default:
return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
}
}
void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) {
int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) {
if (!mac_is_present(mod_id)) return 0;
eNB_MAC_INST *mac = RC.mac[mod_id];
const int cc_id = 0;
pp_impl_param_t dl = mac->pre_processor_dl;
switch (algo) {
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
mac->pre_processor_dl = static_dl_init(mod_id, cc_id);
break;
default:
mac->pre_processor_dl.algorithm = 0;
mac->pre_processor_dl.dl = dlsch_scheduler_pre_processor;
mac->pre_processor_dl.dl_algo.data = mac->pre_processor_dl.dl_algo.setup();
mac->pre_processor_dl.slices = NULL;
break;
}
if (dl.slices)
dl.destroy(&dl.slices);
if (dl.dl_algo.data)
dl.dl_algo.unset(&dl.dl_algo.data);
return 1;
}
Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id) {
if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
switch (RC.mac[mod_id]->pre_processor_ul.algorithm) {
case STATIC_SLICING:
return PROTOCOL__FLEX_SLICE_ALGORITHM__Static;
default:
return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
}
}
int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) {
if (!mac_is_present(mod_id)) return 0;
eNB_MAC_INST *mac = RC.mac[mod_id];
const int cc_id = 0;
pp_impl_param_t ul = mac->pre_processor_ul;
switch (algo) {
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
mac->pre_processor_ul = static_ul_init(mod_id, cc_id);
break;
default:
mac->pre_processor_ul.algorithm = 0;
mac->pre_processor_ul.ul = ulsch_scheduler_pre_processor;
mac->pre_processor_ul.ul_algo.data = mac->pre_processor_ul.ul_algo.setup();
mac->pre_processor_ul.slices = NULL;
break;
}
if (ul.slices)
ul.destroy(&ul.slices);
if (ul.ul_algo.data)
ul.ul_algo.unset(&ul.ul_algo.data);
return 1;
}
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
if (!mac_is_present(mod_id)) return -1;
slice_info_t *slices = RC.mac[mod_id]->pre_processor_dl.slices;
if (!slices) return -1;
const int idx = slices->UE_assoc_slice[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;
if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return;
if (!flexran_dl_slice_exists(mod_id, slice_idx)) return;
//RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id] = slice_idx;
int idx = flexran_find_dl_slice(mod_id, slice_id);
if (idx < 0) return;
pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
dl->move_UE(dl->slices, ue_id, idx);
}
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) {
if (!mac_is_present(mod_id)) return -1;
int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id];
if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul)
return RC.mac[mod_id]->slice_info.ul[slice_idx].id;
return 0;
slice_info_t *slices = RC.mac[mod_id]->pre_processor_ul.slices;
if (!slices) return -1;
const int idx = slices->UE_assoc_slice[ue_id];
return slices->s[idx]->id;
}
void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) {
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;
if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return;
if (!flexran_ul_slice_exists(mod_id, slice_idx)) return;
//RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id] = slice_idx;
int idx = flexran_find_ul_slice(mod_id, slice_id);
if (idx < 0) return;
pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
ul->move_UE(ul->slices, ue_id, idx);
}
int flexran_dl_slice_exists(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl;
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
if (!mac_is_present(mod_id)) return 0;
void *params = NULL;
switch (s->params_case) {
case PROTOCOL__FLEX_SLICE__PARAMS_STATIC:
params = malloc(sizeof(static_slice_param_t));
if (!params) return 0;
((static_slice_param_t *)params)->posLow = s->static_->poslow;
((static_slice_param_t *)params)->posHigh = s->static_->poshigh;
break;
default:
break;
}
pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
char *l = s->label ? strdup(s->label) : NULL;
void *algo = &dl->dl_algo; // default scheduler
if (s->scheduler) {
algo = dlsym(NULL, s->scheduler);
if (!algo) {
free(params);
LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
return -15;
}
}
return dl->addmod_slice(dl->slices, s->id, l, algo, params);
}
int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id) {
if (!mac_is_present(mod_id)) return -1;
int newidx = RC.mac[mod_id]->slice_info.n_dl;
if (newidx >= MAX_NUM_SLICES) return -1;
++RC.mac[mod_id]->slice_info.n_dl;
flexran_set_dl_slice_id(mod_id, newidx, slice_id);
return newidx;
int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
if (!mac_is_present(mod_id)) return 0;
const int idx = flexran_find_dl_slice(mod_id, s->id);
if (idx < 0) return 0;
pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
return dl->remove_slice(dl->slices, idx);
}
int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) {
if (!mac_is_present(mod_id)) return -1;
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
int n = sli->n_dl;
for (int i = 0; i < n; i++) {
if (sli->dl[i].id == slice_id) return i;
}
slice_info_t *si = RC.mac[mod_id]->pre_processor_dl.slices;
for (int i = 0; i < si->num; ++i)
if (si->s[i]->id == slice_id)
return i;
return -1;
}
int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
if (sli->n_dl <= 1) return -1;
if (sli->dl[slice_idx].sched_name) free(sli->dl[slice_idx].sched_name);
--sli->n_dl;
/* move last element to the position of the removed one */
if (slice_idx != sli->n_dl)
memcpy(&sli->dl[slice_idx], &sli->dl[sli->n_dl], sizeof(sli->dl[sli->n_dl]));
memset(&sli->dl[sli->n_dl], 0, sizeof(sli->dl[sli->n_dl]));
/* all UEs that have been in the old slice are put into slice index 0 */
//int *assoc_list = RC.mac[mod_id]->UE_info.assoc_dl_slice_idx;
//for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) {
// if (assoc_list[i] == slice_idx)
// assoc_list[i] = 0;
//}
return 1;
void flexran_get_dl_slice(mid_t mod_id,
int slice_idx,
Protocol__FlexSlice *slice,
Protocol__FlexSliceAlgorithm algo) {
if (!mac_is_present(mod_id)) return;
slice_t *s_ = RC.mac[mod_id]->pre_processor_dl.slices->s[slice_idx];
slice->has_id = 1;
slice->id = s_->id;
slice->label = s_->label;
slice->scheduler = s_->dl_algo.name;
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET;
switch (algo) {
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic));
if (!slice->static_) return;
protocol__flex_slice_static__init(slice->static_);
slice->static_->has_poslow = 1;
slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow;
slice->static_->has_poshigh = 1;
slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh;
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC;
break;
default:
break;
}
}
int flexran_get_num_dl_slices(mid_t mod_id) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.n_dl;
}
int flexran_get_intraslice_sharing_active(mid_t mod_id) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.intraslice_share_active;
}
void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.intraslice_share_active = intraslice_active;
}
int flexran_get_interslice_sharing_active(mid_t mod_id) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.interslice_share_active;
}
void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.interslice_share_active = interslice_active;
}
slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].id;
}
void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].id = slice_id;
}
int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].pct * 100.0f;
}
void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].pct = percentage / 100.0f;
}
int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].isol;
}
void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].isol = is_isolated;
}
int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].prio;
}
void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].prio = priority;
}
int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low;
}
void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low = poslow;
}
int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high;
}
void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high = poshigh;
}
int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs;
}
void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs = maxmcs;
}
int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list) {
if (!mac_is_present(mod_id)) return -1;
if (!(*sorting_list)) {
*sorting_list = calloc(CR_NUM, sizeof(Protocol__FlexDlSorting));
if (!(*sorting_list)) return -1;
}
uint32_t policy = RC.mac[mod_id]->slice_info.dl[slice_idx].sorting;
for (int i = 0; i < CR_NUM; i++) {
switch (policy >> 4 * (CR_NUM - 1 - i) & 0xF) {
case CR_ROUND:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND;
break;
case CR_SRB12:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_SRB12;
break;
case CR_HOL:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_HOL;
break;
case CR_LC:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LC;
break;
case CR_CQI:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_CQI;
break;
case CR_LCP:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LCP;
break;
default:
/* this should not happen, but a "default" */
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND;
break;
}
}
return CR_NUM;
}
void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n) {
if (!mac_is_present(mod_id)) return;
uint32_t policy = 0;
for (int i = 0; i < n && i < CR_NUM; i++) {
switch (sorting_list[i]) {
case PROTOCOL__FLEX_DL_SORTING__CR_ROUND:
policy = policy << 4 | CR_ROUND;
break;
case PROTOCOL__FLEX_DL_SORTING__CR_SRB12:
policy = policy << 4 | CR_SRB12;
break;
case PROTOCOL__FLEX_DL_SORTING__CR_HOL:
policy = policy << 4 | CR_HOL;
break;
case PROTOCOL__FLEX_DL_SORTING__CR_LC:
policy = policy << 4 | CR_LC;
break;
case PROTOCOL__FLEX_DL_SORTING__CR_CQI:
policy = policy << 4 | CR_CQI;
break;
case PROTOCOL__FLEX_DL_SORTING__CR_LCP:
policy = policy << 4 | CR_LCP;
break;
default: /* suppresses warnings */
policy = policy << 4 | CR_ROUND;
break;
}
}
/* fill up with 0 == CR_ROUND */
if (CR_NUM > n) policy = policy << 4 * (CR_NUM - n);
RC.mac[mod_id]->slice_info.dl[slice_idx].sorting = policy;
}
Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
switch (RC.mac[mod_id]->slice_info.dl[slice_idx].accounting) {
case POL_FAIR:
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
case POL_GREEDY:
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY;
default:
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
}
}
void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting) {
if (!mac_is_present(mod_id)) return;
switch (accounting) {
case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR:
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR;
return;
case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY:
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_GREEDY;
return;
default:
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR;
return;
}
}
char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return NULL;
return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name;
}
int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name) {
if (!mac_is_present(mod_id)) return 0;
if (RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name)
free(RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name);
RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name = strdup(name);
RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb = dlsym(NULL, name);
return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb != NULL;
if (!RC.mac[mod_id]->pre_processor_dl.slices) return 0;
return RC.mac[mod_id]->pre_processor_dl.slices->num;
}
int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) {
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
if (!mac_is_present(mod_id)) return -1;
void *params = NULL;
switch (s->params_case) {
case PROTOCOL__FLEX_SLICE__PARAMS_STATIC:
params = malloc(sizeof(static_slice_param_t));
if (!params) return 0;
((static_slice_param_t *)params)->posLow = s->static_->poslow;
((static_slice_param_t *)params)->posHigh = s->static_->poshigh;
break;
default:
break;
}
pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
char *l = s->label ? strdup(s->label) : NULL;
void *algo = &ul->ul_algo; // default scheduler
if (s->scheduler) {
algo = dlsym(NULL, s->scheduler);
if (!algo) {
free(params);
LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
return -15;
}
}
return ul->addmod_slice(ul->slices, s->id, l, algo, params);
}
int newidx = RC.mac[mod_id]->slice_info.n_ul;
if (newidx >= MAX_NUM_SLICES) return -1;
++RC.mac[mod_id]->slice_info.n_ul;
flexran_set_ul_slice_id(mod_id, newidx, slice_id);
return newidx;
int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
if (!mac_is_present(mod_id)) return 0;
const int idx = flexran_find_ul_slice(mod_id, s->id);
if (idx < 0) return 0;
pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
return ul->remove_slice(ul->slices, idx);
}
int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id) {
if (!mac_is_present(mod_id)) return -1;
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
int n = sli->n_ul;
for (int i = 0; i < n; i++) {
if (sli->ul[i].id == slice_id) return i;
}
slice_info_t *si = RC.mac[mod_id]->pre_processor_ul.slices;
for (int i = 0; i < si->num; ++i)
if (si->s[i]->id == slice_id)
return i;
return -1;
}
int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
void flexran_get_ul_slice(mid_t mod_id,
int slice_idx,
Protocol__FlexSlice *slice,
Protocol__FlexSliceAlgorithm algo) {
if (!mac_is_present(mod_id)) return;
slice_t *s_ = RC.mac[mod_id]->pre_processor_ul.slices->s[slice_idx];
slice->has_id = 1;
slice->id = s_->id;
slice->label = s_->label;
slice->scheduler = s_->ul_algo.name;
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET;
switch (algo) {
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic));
if (!slice->static_) return;
protocol__flex_slice_static__init(slice->static_);
slice->static_->has_poslow = 1;
slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow;
slice->static_->has_poshigh = 1;
slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh;
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC;
break;
default:
break;
}
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
if (sli->n_ul <= 1) return -1;
if (sli->ul[slice_idx].sched_name) free(sli->ul[slice_idx].sched_name);
--sli->n_ul;
/* move last element to the position of the removed one */
if (slice_idx != sli->n_ul)
memcpy(&sli->ul[slice_idx], &sli->ul[sli->n_ul], sizeof(sli->ul[sli->n_ul]));
memset(&sli->ul[sli->n_ul], 0, sizeof(sli->ul[sli->n_ul]));
/* all UEs that have been in the old slice are put into slice index 0 */
//int *assoc_list = RC.mac[mod_id]->UE_info.assoc_ul_slice_idx;
//for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) {
// if (assoc_list[i] == slice_idx)
// assoc_list[i] = 0;
//}
return sli->n_ul;
}
int flexran_get_num_ul_slices(mid_t mod_id) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.n_ul;
}
int flexran_ul_slice_exists(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul;
}
slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.ul[slice_idx].id;
}
void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.ul[slice_idx].id = slice_id;
}
int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.ul[slice_idx].pct * 100.0f;
}
void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.ul[slice_idx].pct = percentage / 100.0f;
}
int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb;
}
void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb = first_rb;
}
int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs;
}
void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) {
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs = maxmcs;
}
char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx) {
if (!mac_is_present(mod_id)) return NULL;
return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name;
}
int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name) {
if (!mac_is_present(mod_id)) return 0;
if (!RC.mac[mod_id]->pre_processor_ul.slices) return 0;
return RC.mac[mod_id]->pre_processor_ul.slices->num;
}
if (RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name)
free(RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name);
char *flexran_get_dl_scheduler_name(mid_t mod_id) {
if (!mac_is_present(mod_id)) return NULL;
return RC.mac[mod_id]->pre_processor_dl.dl_algo.name;
}
RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name = strdup(name);
RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb = dlsym(NULL, name);
return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb != NULL;
int flexran_set_dl_scheduler(mid_t mod_id, char *sched) {
if (!mac_is_present(mod_id)) return -1;
void *d = dlsym(NULL, 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);
dl_pp->dl_algo = *(default_sched_dl_algo_t *) d;
dl_pp->dl_algo.data = dl_pp->dl_algo.setup();
return 0;
}
char *flexran_get_ul_scheduler_name(mid_t mod_id) {
if (!mac_is_present(mod_id)) return NULL;
return RC.mac[mod_id]->pre_processor_ul.ul_algo.name;
}
int flexran_set_ul_scheduler(mid_t mod_id, char *sched) {
if (!mac_is_present(mod_id)) return -1;
void *d = dlsym(NULL, 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);
ul_pp->ul_algo = *(default_sched_ul_algo_t *) d;
ul_pp->ul_algo.data = ul_pp->ul_algo.setup();
return 0;
}
/************************** S1AP **************************/
@@ -3634,6 +3457,168 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM
return 0;
}
int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) {
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap) return -1;
if (!rrc_is_present(mod_id)) return -2;
/* Reconstruct S1AP_REGISTER_ENB_REQ */
MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, S1AP_REGISTER_ENB_REQ);
RCconfig_S1(m, mod_id);
const int CC_id = 0;
eNB_RRC_INST *rrc = RC.rrc[CC_id];
RrcConfigurationReq *conf = &rrc->configuration;
S1AP_REGISTER_ENB_REQ(m).num_plmn = conf->num_plmn;
for (int i = 0; i < conf->num_plmn; ++i) {
S1AP_REGISTER_ENB_REQ(m).mcc[i] = conf->mcc[i];
S1AP_REGISTER_ENB_REQ(m).mnc[i] = conf->mnc[i];
S1AP_REGISTER_ENB_REQ(m).mnc_digit_length[i] = conf->mnc_digit_length[i];
}
/* reconstruct MME list, it might have been updated since initial
* configuration */
S1AP_REGISTER_ENB_REQ(m).nb_mme = 0;
struct s1ap_eNB_mme_data_s *mme = NULL;
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme;
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = mme->mme_s1_ip.ipv4;
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme->mme_s1_ip.ipv4_address);
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = mme->mme_s1_ip.ipv6;
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6_address, mme->mme_s1_ip.ipv6_address);
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = mme->broadcast_plmn_num;
for (int i = 0; i < mme->broadcast_plmn_num; ++i)
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = mme->broadcast_plmn_index[i];
S1AP_REGISTER_ENB_REQ(m).nb_mme += 1;
}
if (S1AP_REGISTER_ENB_REQ(m).nb_mme + n_mme > S1AP_MAX_NB_MME_IP_ADDRESS)
return -1;
for (int i = 0; i < n_mme; ++i) {
const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme;
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme_ipv4[0]);
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = 1;
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = 0;
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = S1AP_REGISTER_ENB_REQ(m).num_plmn;
for (int i = 0; i < S1AP_REGISTER_ENB_REQ(m).num_plmn; ++i)
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = i;
S1AP_REGISTER_ENB_REQ(m).nb_mme += 1;
}
itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m);
return 0;
}
int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) {
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap) return -1;
struct s1ap_eNB_mme_data_s *mme = NULL;
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
if (mme->mme_s1_ip.ipv4
&& strncmp(mme->mme_s1_ip.ipv4_address, mme_ipv4[0], 16) == 0)
break;
}
if (!mme)
return -2;
MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, SCTP_CLOSE_ASSOCIATION);
SCTP_CLOSE_ASSOCIATION(m).assoc_id = mme->assoc_id;
itti_send_msg_to_task (TASK_SCTP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m);
switch (mme->state) {
case S1AP_ENB_STATE_WAITING:
s1ap->s1ap_mme_nb -= 1;
if (s1ap->s1ap_mme_pending_nb > 0)
s1ap->s1ap_mme_pending_nb -= 1;
break;
case S1AP_ENB_STATE_CONNECTED:
case S1AP_ENB_OVERLOAD: /* I am not sure the decrements are right here */
s1ap->s1ap_mme_nb -= 1;
s1ap->s1ap_mme_associated_nb -= 1;
break;
case S1AP_ENB_STATE_DISCONNECTED:
default:
break;
}
RB_REMOVE(s1ap_mme_map, &s1ap->s1ap_mme_head, mme);
return 0;
}
int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id) {
if (!rrc_is_present(mod_id))
return -1;
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
if (!s1ap)
return -2;
eNB_RRC_INST *rrc = RC.rrc[CC_id];
RrcConfigurationReq *conf = &rrc->configuration;
uint8_t num_plmn_old = conf->num_plmn;
uint16_t mcc[PLMN_LIST_MAX_SIZE];
uint16_t mnc[PLMN_LIST_MAX_SIZE];
uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE];
for (int i = 0; i < num_plmn_old; ++i) {
mcc[i] = conf->mcc[i];
mnc[i] = conf->mnc[i];
mnc_digit_length[i] = conf->mnc_digit_length[i];
}
conf->num_plmn = (uint8_t) n_plmn;
for (int i = 0; i < conf->num_plmn; ++i) {
conf->mcc[i] = plmn_id[i]->mcc;
conf->mnc[i] = plmn_id[i]->mnc;
conf->mnc_digit_length[i] = plmn_id[i]->mnc_length;
}
rrc_eNB_carrier_data_t *carrier = &rrc->carrier[CC_id];
extern uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
int Mod_id,
int CC_id,
BOOLEAN_t brOption,
RrcConfigurationReq *configuration);
carrier->sizeof_SIB1 = do_SIB1(carrier, mod_id, CC_id, FALSE, conf);
if (carrier->sizeof_SIB1 < 0)
return -1337; /* SIB1 encoding failed, hell will probably break loose */
s1ap->num_plmn = (uint8_t) n_plmn;
for (int i = 0; i < conf->num_plmn; ++i) {
s1ap->mcc[i] = plmn_id[i]->mcc;
s1ap->mnc[i] = plmn_id[i]->mnc;
s1ap->mnc_digit_length[i] = plmn_id[i]->mnc_length;
}
int bpn_failed = 0;
struct s1ap_eNB_mme_data_s *mme = NULL;
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
for (int i = 0; i < mme->broadcast_plmn_num; ++i) {
/* search the new index and update. If we don't find, we count this using
* bpn_failed to now how many broadcast_plmns could not be updated */
int idx = mme->broadcast_plmn_index[i];
int omcc = mcc[idx];
int omnc = mnc[idx];
int omncl = mnc_digit_length[idx];
int j = 0;
for (j = 0; j < s1ap->num_plmn; ++j) {
if (s1ap->mcc[j] == omcc
&& s1ap->mnc[j] == omnc
&& s1ap->mnc_digit_length[j] == omncl) {
mme->broadcast_plmn_index[i] = j;
break;
}
}
if (j == s1ap->num_plmn) /* could not find the old PLMN in the new ones */
bpn_failed++;
}
}
if (bpn_failed > 0)
return -10000 - bpn_failed;
return 0;
}
int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf){
if (!rrc_is_present(mod_id)) return -1;
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
@@ -3644,7 +3629,7 @@ int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_con
RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head){
if (ue->eNB_ue_s1ap_id == enb_ue_s1ap_id) break;
}
if (ue == NULL) return -1;
if (!ue) return 0; // UE does not exist: it might be connected but CN did not answer
if (ue->mme_ref->mme_s1_ip.ipv4)
ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv4_address[0];
+52 -133
View File
@@ -656,156 +656,66 @@ int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index);
uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti);
/************************** Slice configuration **************************/
/* Get the currently active DL slicing algorithm */
Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id);
/* Set the active DL slicing algorithm */
int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo);
/* Get the currently active UL slicing algorithm */
Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id);
/* Set the active UL slicing algorithm */
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 index(!) for a UE */
void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx);
/* 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);
/* 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);
/* Set the UL slice index(!) for a UE */
void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx);
/* Whether intraslice sharing is active, return boolean */
int flexran_get_intraslice_sharing_active(mid_t mod_id);
/* Set whether intraslice sharing is active */
void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active);
/* Whether intraslice sharing is active, return boolean */
int flexran_get_interslice_sharing_active(mid_t mod_id);
/* Set whether intraslice sharing is active */
void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active);
/* Create slice in DL, returns the new slice index */
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s);
/* 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);
/* Finds slice in DL with given slice_id and returns slice index */
int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id);
/* Return the parameters of slice at index slice_idx */
void flexran_get_dl_slice(mid_t mod_id,
int slice_idx,
Protocol__FlexSlice *slice,
Protocol__FlexSliceAlgorithm algo);
/* Get the number of slices in DL */
int flexran_get_num_dl_slices(mid_t mod_id);
/* Query slice existence in DL. Return is boolean value */
int flexran_dl_slice_exists(mid_t mod_id, int slice_idx);
/* Create slice in UL, returns the new slice index */
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s);
/* Remove slice in UL */
int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s);
/* Create slice in DL, returns the new slice index */
int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id);
/* Finds slice in DL with given slice_id and returns slice index */
int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id);
/* Remove slice in DL, returns new number of slices or -1 on error */
int flexran_remove_dl_slice(mid_t mod_id, int slice_idx);
/* Get the ID of a slice in DL */
slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx);
/* Set the ID of a slice in DL */
void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id);
/* Get the RB share a slice in DL, value 0-100 */
int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx);
/* Set the RB share a slice in DL, value 0-100 */
void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage);
/* Whether a slice in DL is isolated */
int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx);
/* Set whether a slice in DL is isolated */
void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated);
/* Get the priority of a slice in DL */
int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx);
/* Get the priority of a slice in DL */
void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority);
/* Get the lower end of the frequency range for the slice positioning in DL */
int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx);
/* Set the lower end of the frequency range for the slice positioning in DL */
void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow);
/* Get the higher end of the frequency range for the slice positioning in DL */
int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx);
/* Set the higher end of the frequency range for the slice positioning in DL */
void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh);
/* Get the maximum MCS for slice in DL */
int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx);
/* Set the maximum MCS for slice in DL */
void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs);
/* Get the sorting order of a slice in DL, return value is number of elements
* in sorting_list */
int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list);
/* Set the sorting order of a slice in DL */
void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n);
/* Get the accounting policy for a slice in DL */
Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx);
/* Set the accounting policy for a slice in DL */
void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting);
/* Get the scheduler name for a slice in DL */
char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx);
/* Set the scheduler name for a slice in DL */
int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name);
int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id);
/* Return the parameters of slice at index slice_idx */
void flexran_get_ul_slice(mid_t mod_id,
int slice_idx,
Protocol__FlexSlice *slice,
Protocol__FlexSliceAlgorithm algo);
/* Get the number of slices in UL */
int flexran_get_num_ul_slices(mid_t mod_id);
/* Query slice existence in UL. Return is boolean value */
int flexran_ul_slice_exists(mid_t mod_id, int slice_idx);
/* 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. */
char *flexran_get_dl_scheduler_name(mid_t mod_id);
int flexran_set_dl_scheduler(mid_t mod_id, char *sched);
/* Create slice in UL, returns the new slice index */
int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id);
/* Finds slice in UL with given slice_id and returns slice index */
int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id);
/* Remove slice in UL */
int flexran_remove_ul_slice(mid_t mod_id, int slice_idx);
/* Get the ID of a slice in UL */
slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx);
/* Set the ID of a slice in UL */
void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id);
/* Get the RB share a slice in UL, value 0-100 */
int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx);
/* Set the RB share a slice in UL, value 0-100 */
void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage);
/* TODO Whether a slice in UL is isolated */
/*int flexran_get_ul_slice_isolation(mid_t mod_id, int slice_idx);*/
/* TODO Set whether a slice in UL is isolated */
/*void flexran_set_ul_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated);*/
/* TODO Get the priority of a slice in UL */
/*int flexran_get_ul_slice_priority(mid_t mod_id, int slice_idx);*/
/* TODO Set the priority of a slice in UL */
/*void flexran_set_ul_slice_priority(mid_t mod_id, int slice_idx, int priority);*/
/* Get the first RB for allocation in a slice in UL */
int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx);
/* Set the first RB for allocation in a slice in UL */
void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb);
/* TODO Get the number of RB for the allocation in a slice in UL */
/*int flexran_get_ul_slice_length_rb(mid_t mod_id, int slice_idx);*/
/* TODO Set the of number of RB for the allocation in a slice in UL */
/*void flexran_set_ul_slice_length_rb(mid_t mod_id, int slice_idx, int poshigh);*/
/* Get the maximum MCS for slice in UL */
int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx);
/* Set the maximum MCS for slice in UL */
void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs);
/* TODO Get the sorting order of a slice in UL, return value is number of elements
* in sorting_list */
/*int flexran_get_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting **sorting_list);*/
/* TODO Set the sorting order of a slice in UL */
/*void flexran_set_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting *sorting_list, int n);*/
/* TODO Get the accounting policy for a slice in UL */
/*Protocol__UlAccountingPolicy flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx);*/
/* TODO Set the accounting policy for a slice in UL */
/*void flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__UlAccountingPolicy accountin);*/
/* Get the scheduler name for a slice in UL */
char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx);
/* Set the scheduler name for a slice in UL */
int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name);
/* Get the name of/Set the UL scheduler algorithm. Same applies as for the DL
* case */
char *flexran_get_ul_scheduler_name(mid_t mod_id);
int flexran_set_ul_scheduler(mid_t mod_id, char *sched);
/************************** S1AP **************************/
/* Get the number of MMEs to be connected */
@@ -832,6 +742,15 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM
/* Get the S1AP UE conf */
int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf);
/* Add MMEs and re-issue S1AP Registration Request */
int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4);
/* Remove MMEs and and cut SCTP to MME */
int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4);
/* Set a new PLMN configuration */
int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id);
/********************* general information *****************/
/* get an ID for this BS (or part of a BS) */
uint64_t flexran_get_bs_id(mid_t mod_id);