Commit fcaf2371 authored by Robert Schmidt's avatar Robert Schmidt

FlexRAN: Handle slice configuration

Incoming slice configuration changes are buffered in an intermediate structure.
The MAC scheduler periodically polls the agent about changes. If there has been
a slice configuration change, apply it.
parent 9d75b5c3
...@@ -52,6 +52,16 @@ struct lfds700_misc_prng_state ps[NUM_MAX_ENB]; ...@@ -52,6 +52,16 @@ struct lfds700_misc_prng_state ps[NUM_MAX_ENB];
struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB];
struct lfds700_ringbuffer_state ringbuffer_state[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[NUM_MAX_ENB];
/* a structure that keeps updates which will be reflected in slice_config later */
Protocol__FlexSliceConfig *sc_update[NUM_MAX_ENB];
/* 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[NUM_MAX_UE];
int n_ue_slice_assoc_updates = 0;
int flexran_agent_mac_stats_reply(mid_t mod_id, int flexran_agent_mac_stats_reply(mid_t mod_id,
const report_config_t *report_config, const report_config_t *report_config,
...@@ -1372,8 +1382,141 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) { ...@@ -1372,8 +1382,141 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) {
return 0; 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;
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]);
}
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]);
}
}
void flexran_check_and_remove_slices(mid_t mod_id)
{
int i;
Protocol__FlexDlSlice **dl = sc_update[mod_id]->dl;
size_t n_dl = sc_update[mod_id]->n_dl;
for (i = 0; i < n_dl; i++) {
/* remove slices whose percentage is zero */
if (dl[i]->percentage > 0) 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);
continue;
}
LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n",
mod_id, i, dl[i]->id);
/* don't update slice_config, it will be read in below */
/* we need to memcpy the higher slice to the position we just deleted */
memcpy(dl[i], dl[n_dl-1], sizeof(*dl[n_dl-1]));
--sc_update[mod_id]->n_dl;
}
Protocol__FlexUlSlice **ul = sc_update[mod_id]->ul;
size_t n_ul = sc_update[mod_id]->n_ul;
for (i = 0; i < n_ul; i++) {
if (ul[i]->percentage > 0) 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);
continue;
}
LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n",
mod_id, i, ul[i]->id);
/* see DL remarks */
memcpy(ul[i], ul[n_ul-1], sizeof(*ul[n_ul-1]));
--sc_update[mod_id]->n_ul;
}
}
void flexran_agent_slice_update(mid_t mod_id)
{
int i;
int changes = 0;
if (perform_slice_config_update_count <= 0) return;
perform_slice_config_update_count--;
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);
return;
}
/********* 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]);
}
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]);
}
/* in case we tried to add a slice and it failed (e.g. due to high sum
* percentage being too high), revert to the correct number of slices.
* Also, do not write if we try the last time */
if (perform_slice_config_update_count == 1) {
if (slice_config[mod_id]->n_dl != sc_update[mod_id]->n_dl) {
sc_update[mod_id]->n_dl = slice_config[mod_id]->n_dl;
LOG_W(FLEXRAN_AGENT, "[%d] reverting to original number of %ld DL slices\n",
mod_id, sc_update[mod_id]->n_dl);
}
if (slice_config[mod_id]->n_ul != sc_update[mod_id]->n_ul) {
sc_update[mod_id]->n_ul = slice_config[mod_id]->n_ul;
LOG_W(FLEXRAN_AGENT, "[%d] reverting to original number of %ld UL slices\n",
mod_id, sc_update[mod_id]->n_ul);
}
return;
}
/********* 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, 0);
slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id);
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
}
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, 0);
slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id);
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
}
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]);
}
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]);
}
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);
}
Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id)
{
return slice_config[mod_id];
}
...@@ -87,4 +87,14 @@ int flexran_agent_register_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface); ...@@ -87,4 +87,14 @@ int flexran_agent_register_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface);
/*Unregister technology specific callbacks*/ /*Unregister technology specific callbacks*/
int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface*xface); int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface*xface);
/***************************************
* FlexRAN agent - slice configuration *
***************************************/
/* 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);
#endif #endif
...@@ -32,6 +32,13 @@ ...@@ -32,6 +32,13 @@
#include "flexran_agent_common_internal.h" #include "flexran_agent_common_internal.h"
#include "flexran_agent_mac_internal.h" #include "flexran_agent_mac_internal.h"
/* from flexran_agent_mac.c */
extern Protocol__FlexSliceConfig *slice_config[NUM_MAX_ENB];
extern Protocol__FlexSliceConfig *sc_update[NUM_MAX_ENB];
extern int perform_slice_config_update_count;
extern Protocol__FlexUeConfig *ue_slice_assoc_update[NUM_MAX_UE];
extern int n_ue_slice_assoc_updates;
Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message, Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message,
Protocol__FlexranMessage *old_message) { Protocol__FlexranMessage *old_message) {
...@@ -899,3 +906,519 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { ...@@ -899,3 +906,519 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
return -1; return -1;
} }
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_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;
dl_slice->scheduler_name = flexran_get_dl_slice_scheduler_name(mod_id, slice_idx);
}
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;
ul_slice->scheduler_name = flexran_get_ul_slice_scheduler_name(mod_id, slice_idx);
}
void overwrite_slice_config_dl(Protocol__FlexDlSlice *exist, Protocol__FlexDlSlice *update)
{
if (update->has_label && update->label != exist->label) {
LOG_I(FLEXRAN_AGENT, "[DL slice %d] update label: %d -> %d\n",
update->id, exist->label, update->label);
exist->label = update->label;
}
if (update->has_percentage && update->percentage != exist->percentage) {
LOG_I(FLEXRAN_AGENT, "[DL slice %d] update percentage: %d -> %d\n",
update->id, exist->percentage, update->percentage);
exist->percentage = update->percentage;
}
if (update->has_isolation && update->isolation != exist->isolation) {
LOG_I(FLEXRAN_AGENT, "[DL slice %d] update isolation: %d -> %d\n",
update->id, exist->isolation, update->isolation);
exist->isolation = update->isolation;
}
if (update->has_priority && update->priority != exist->priority) {
LOG_I(FLEXRAN_AGENT, "[DL slice %d] update priority: %d -> %d\n",
update->id, exist->priority, update->priority);
exist->priority = update->priority;
}
if (update->has_position_low && update->position_low != exist->position_low) {
LOG_I(FLEXRAN_AGENT, "[DL slice %d] update position_low: %d -> %d\n",
update->id, exist->position_low, update->position_low);
exist->position_low = update->position_low;
}
if (update->has_position_high && update->position_high != exist->position_high) {
LOG_I(FLEXRAN_AGENT, "[DL slice %d] update position_high: %d -> %d\n",
update->id, exist->position_high, update->position_high);
exist->position_high = update->position_high;
}
if (update->has_maxmcs && update->maxmcs != exist->maxmcs) {
LOG_I(FLEXRAN_AGENT, "[DL slice %d] update maxmcs: %d -> %d\n",
update->id, exist->maxmcs, update->maxmcs);
exist->maxmcs = update->maxmcs;
}
int sorting_update = 0;
int n = min(exist->n_sorting, update->n_sorting);
/* check whether something has changed. If update->n_sorting is 0,
* sorting_update will remain false, so no update will be done */
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, "[DL slice %d] update sorting array\n", update->id);
if (exist->n_sorting != update->n_sorting)
LOG_W(FLEXRAN_AGENT, "[slice %d] only writing %d elements\n",
update->id, n);
for (int i = 0; i < n; i++)
exist->sorting[i] = update->sorting[i];
}
if (update->has_accounting && update->accounting != exist->accounting) {
LOG_I(FLEXRAN_AGENT, "[DL slice %d] update accounting: %d -> %d\n",
update->id, exist->accounting, update->accounting);
exist->accounting = update->accounting;
}
if (update->scheduler_name
&& strcmp(update->scheduler_name, exist->scheduler_name) != 0) {
LOG_W(FLEXRAN_AGENT, "[DL slice %d] ignoring new scheduler name \"%s\"!\n",
update->id, update->scheduler_name);
}
}
void overwrite_slice_config_ul(Protocol__FlexUlSlice *exist, Protocol__FlexUlSlice *update)
{
if (update->has_label && update->label != exist->label) {
LOG_I(FLEXRAN_AGENT, "[UL slice %d] update label: %d -> %d\n",
update->id, exist->label, update->label);
exist->label = update->label;
}
if (update->has_percentage && update->percentage != exist->percentage) {
LOG_I(FLEXRAN_AGENT, "[UL slice %d] update percentage: %d -> %d\n",
update->id, exist->percentage, update->percentage);
exist->percentage = update->percentage;
}
if (update->has_isolation && update->isolation != exist->isolation) {
LOG_I(FLEXRAN_AGENT, "[UL slice %d] update isolation: %d -> %d\n",
update->id, exist->isolation, update->isolation);
exist->isolation = update->isolation;
}
if (update->has_priority && update->priority != exist->priority) {
LOG_I(FLEXRAN_AGENT, "[UL slice %d] update priority: %d -> %d\n",
update->id, exist->priority, update->priority);
exist->priority = update->priority;
}
if (update->has_first_rb && update->first_rb != exist->first_rb) {
LOG_I(FLEXRAN_AGENT, "[UL slice %d] update first_rb: %d -> %d\n",
update->id, exist->first_rb, update->first_rb);
exist->first_rb = update ->first_rb;
}
/*if (update->has_length_rb && update->lenght_rb != exist->lenght_rb) {
LOG_I(FLEXRAN_AGENT, "[UL slice %d] update lenght_rb: %d -> %d\n",
update->id, exist->lenght_rb, update->lenght_rb);
exist->lenght_rb = update->lenght_rb;
}*/
if (update->has_maxmcs && update->maxmcs != exist->maxmcs) {
LOG_I(FLEXRAN_AGENT, "[UL slice %d] update maxmcs: %d -> %d\n",
update->id, exist->maxmcs, update->maxmcs);
exist->maxmcs = update->maxmcs;
}
int sorting_update = 0;
int n = min(exist->n_sorting, update->n_sorting);
/* check whether something has changed. If update-> n_sorting is 0,
* sorting_update will remain false, so no update will be done */
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, "[UL slice %d] update sorting array\n", update->id);
if (exist->n_sorting != update->n_sorting)
LOG_W(FLEXRAN_AGENT, "[UL slice %d] only writing %d elements\n",
update->id, n);
for (i = 0; i < n; i++)
exist->sorting[i] = update->sorting[i];
}
if (update->has_accounting && update->accounting != exist->accounting) {
LOG_I(FLEXRAN_AGENT, "[UL slice %d] update accounting: %d -> %d\n",
update->id, exist->accounting, update->accounting);
exist->accounting = update->accounting;
}
if (update->scheduler_name
&& strcmp(update->scheduler_name, exist->scheduler_name) != 0) {
LOG_W(FLEXRAN_AGENT, "[UL slice %d] ignoring new scheduler name \"%s\"!\n",
update->id, update->scheduler_name);
}
}
void prepare_update_slice_config_dl(mid_t mod_id, Protocol__FlexDlSlice *dls)
{
if (!dls->has_id) {
LOG_E(FLEXRAN_AGENT, "[%d] Incoming DL slice configuration has no ID\n", mod_id);
return;
}
/* a percentage of zero will be interpreted as removal command */
if (sc_update[mod_id]->n_dl >= MAX_NUM_SLICES
&& (!dls->has_percentage || dls->percentage > 0)) {
LOG_E(FLEXRAN_AGENT, "[%d] Cannot create more than %ld slices in DL\n",
mod_id, sc_update[mod_id]->n_dl);
return;
}
if (sc_update[mod_id]->n_dl == 1 && dls->has_percentage && dls->percentage == 0) {
LOG_E(FLEXRAN_AGENT, "[%d] Cannot delete last slice ID %d in DL\n",
mod_id, sc_update[mod_id]->dl[0]->id);
return;
}
Protocol__FlexDlSlice *to = NULL;
for (int i = 0; i < sc_update[mod_id]->n_dl; ++i) {
if (dls->id == sc_update[mod_id]->dl[i]->id) {
to = sc_update[mod_id]->dl[i];
break;
}
}
/* create new slice -> read contents from existing slice config index 0 */
if (!to) {
LOG_I(FLEXRAN_AGENT,
"[%d] Creating DL slice with ID %d, taking default values from DL slice 0\n",
mod_id, dls->id);
to = sc_update[mod_id]->dl[sc_update[mod_id]->n_dl];
sc_update[mod_id]->n_dl++;
memcpy(to, slice_config[mod_id]->dl[0], sizeof(*to));
to->id = dls->id;
}
overwrite_slice_config_dl(to, dls);
}
void prepare_update_slice_config_ul(mid_t mod_id, Protocol__FlexUlSlice *uls)
{
if (!uls->has_id) {
LOG_E(FLEXRAN_AGENT, "[%d] Incoming UL slice configuration has no ID\n", mod_id);
return;
}
/* a percentage of zero will be interpreted as removal command */
if (sc_update[mod_id]->n_ul >= MAX_NUM_SLICES
&& (!uls->has_percentage || uls->percentage > 0)) {
LOG_E(FLEXRAN_AGENT, "[%d] Cannot create more than %ld slices in UL\n",
mod_id, sc_update[mod_id]->n_ul);
return;
}
if (sc_update[mod_id]->n_ul == 1 && uls->has_percentage && uls->percentage == 0) {
LOG_E(FLEXRAN_AGENT, "[%d] Cannot delete last slice ID %d in UL\n",
mod_id, sc_update[mod_id]->ul[0]->id);
return;
}
Protocol__FlexUlSlice *to = NULL;
for (int i = 0; i < sc_update[mod_id]->n_ul; ++i) {
if (uls->id == sc_update[mod_id]->ul[i]->id) {
to = sc_update[mod_id]->ul[i];
break;
}
}
/* create new slice -> read contents from existing slice config index 0 */
if (!to) {
LOG_I(FLEXRAN_AGENT,
"[%d] Creating UL slice with ID %d, taking default values from UL slice 0\n",
mod_id, uls->id);
to = sc_update[mod_id]->ul[sc_update[mod_id]->n_ul];
sc_update[mod_id]->n_ul++;
memcpy(to, slice_config[mod_id]->ul[0], sizeof(*to));
to->id = uls->id;
}
overwrite_slice_config_ul(to, uls);
}
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *slice)
{
if (!sc_update[mod_id]) {
LOG_E(FLEXRAN_AGENT, "Can not update slice policy (no existing slice profile)\n");
return;
}
if (slice->n_dl == 0)
LOG_I(FLEXRAN_AGENT, "[%d] no DL slice configuration in flex_slice_config message\n", mod_id);
for (int i = 0; i < slice->n_dl; i++)
prepare_update_slice_config_dl(mod_id, slice->dl[i]);
if (slice->n_ul == 0)
LOG_I(FLEXRAN_AGENT, "[%d] no UL slice configuration in flex_slice_config message\n", mod_id);
for (int i = 0; i < slice->n_ul; i++)
prepare_update_slice_config_ul(mod_id, slice->ul[i]);
/* perform the slice configuration reads a couple of times. If there are
* inconsistencies (i.e. the MAC refuses a configuration), we will have a
* couple of warnings because the current configuration and the one in
* sc_update will be diverged */
perform_slice_config_update_count = 3;
}
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 n;
int slice_idx = flexran_find_dl_slice(mod_id, newc->id);
if (slice_idx < 0) {
LOG_W(FLEXRAN_AGENT, "cannot find index for slice ID %d\n", 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++;
}
n = min(oldc->n_sorting, newc->n_sorting);
for (int i = 0; i < n; i++) {
if (oldc->sorting[i] != newc->sorting[i]) {
flexran_set_dl_slice_sorting(mod_id, slice_idx, newc->sorting, n);
changes++;
break;
}
}
if (oldc->accounting != newc->accounting) {
flexran_set_dl_slice_accounting_policy(mod_id, slice_idx, newc->accounting);
changes++;
}
if (strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] setting the DL scheduler is not supported, reverting\n",
mod_id, newc->id);
newc->scheduler_name = oldc->scheduler_name;
}
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 n;
int slice_idx = flexran_find_ul_slice(mod_id, newc->id);
if (slice_idx < 0) {
LOG_W(FLEXRAN_AGENT, "cannot find index for slice ID %d\n", 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, slice_idx);
}
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, slice_idx);
}
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, slice_idx);
}*/
if (oldc->maxmcs != newc->maxmcs) {
flexran_set_ul_slice_maxmcs(mod_id, slice_idx, newc->maxmcs);
changes++;
}
n = min(oldc->n_sorting, newc->n_sorting);
for (int i = 0; i < n; i++) {
if (oldc->sorting[i] != newc->sorting[i]) {
/*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, slice_idx);
break;
}
}
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, slice_idx);
}
if (strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] setting the UL scheduler is not supported, reverting\n",
mod_id, slice_idx);
newc->scheduler_name = oldc->scheduler_name;
}
return changes;
}
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config)
{
if (n_ue_slice_assoc_updates == NUM_MAX_UE) {
LOG_E(FLEXRAN_AGENT,
"[%d] can not handle flex_ue_config message, buffer is full; try again later\n",
mod_id);
return;
}
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;
}
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;
/* TODO should lock structure */
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_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);
}
}
}
n_ue_slice_assoc_updates = 0;
return changes;
}
...@@ -107,4 +107,37 @@ int parse_ul_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser); ...@@ -107,4 +107,37 @@ int parse_ul_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser);
int load_dl_scheduler_function(mid_t mod_id, const char *function_name); 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 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 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);
/* apply a new association between a UE and a slice (both DL and UL) */
int apply_ue_slice_assoc_update(mid_t mod_id);
#endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/ #endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/
...@@ -703,6 +703,10 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, ...@@ -703,6 +703,10 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP,
allocate_CCEs(module_idP, CC_id, frameP, subframeP, 2); allocate_CCEs(module_idP, CC_id, frameP, subframeP, 2);
} }
if (mac_agent_registered[module_idP] && subframeP == 9) {
flexran_agent_slice_update(module_idP);
}
stop_meas(&RC.mac[module_idP]->eNB_scheduler); stop_meas(&RC.mac[module_idP]->eNB_scheduler);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment