diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 549c7eaa2227e944a98747b6bcdd2f8a2ac73207..0c33026a38b39c1742210efdf6be8afe8b688217 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -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_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, const report_config_t *report_config, @@ -1372,8 +1382,141 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) { 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]; +} diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h index 03e7def95e04610e57503917c38dbafe9e6fb3d4..0d686a53eed6fa5c13fc39129e0aff4508b86056 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h @@ -87,4 +87,14 @@ int flexran_agent_register_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface); /*Unregister technology specific callbacks*/ 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 diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index 2acee0686f62165881d256e96eb09500274d0a30..435e8da064d2180c99ea8119c9cfc3681f5e3353 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -32,6 +32,13 @@ #include "flexran_agent_common_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 *old_message) { @@ -899,3 +906,519 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { 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; +} diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h index f69e2cde4098ad5d035a522c9815632bffb37312..2f8f3f8258fb9c48d072be47f999d8a520daf8ab 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h @@ -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); +/*** 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_*/ diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index a2988f26d8c27b34265fe94635d625e2858935c0..4dbf3cf36f57d2c700463d071b02d805bb61a704 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -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); } + if (mac_agent_registered[module_idP] && subframeP == 9) { + flexran_agent_slice_update(module_idP); + } + stop_meas(&RC.mac[module_idP]->eNB_scheduler); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME