FlexRAN: move slice param verification to agent
- until now, on every iteration, the scheduler checked for changed parameter (and verified some) - this functionality moves to the FlexRAN Agent, which verifies all parameters * individually, e.g. Max MCS <= 28 for DL * group-based, e.g. the sum of slice percentages is <= 100 - slice configuration changes are only applied if all verifications pass - it is assumed in the scheduler, that configuration passed from outside is correct and can be used "as-is" fix accounting setting
This commit is contained in:
@@ -870,6 +870,7 @@ add_library(FLEXRAN_AGENT
|
||||
${OPENAIR2_DIR}/ENB_APP/flexran_agent_net_comm.c
|
||||
${OPENAIR2_DIR}/ENB_APP/flexran_agent_async.c
|
||||
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
|
||||
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c
|
||||
)
|
||||
set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT)
|
||||
#include_directories(${OPENAIR2_DIR}/ENB_APP)
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "flexran_agent_common_internal.h"
|
||||
#include "flexran_agent_mac_internal.h"
|
||||
#include "flexran_agent_mac_slice_verification.h"
|
||||
|
||||
/* from flexran_agent_mac.c */
|
||||
extern Protocol__FlexSliceConfig *slice_config[NUM_MAX_ENB];
|
||||
@@ -1141,107 +1142,203 @@ void overwrite_slice_config_ul(Protocol__FlexUlSlice *exist, Protocol__FlexUlSli
|
||||
}
|
||||
}
|
||||
|
||||
void prepare_update_slice_config_dl(mid_t mod_id, Protocol__FlexDlSlice *dls)
|
||||
void fill_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *s)
|
||||
{
|
||||
if (!dls->has_id) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] Incoming DL slice configuration has no ID\n", mod_id);
|
||||
return;
|
||||
/* TODO fill the slice depending on the chosen label */
|
||||
/* for now, we fill it up with the information from slice 0 */
|
||||
/* assume there is an ID (will be checked later) */
|
||||
if (!s->has_label) {
|
||||
s->has_label = 1;
|
||||
s->label = sc_update[mod_id]->dl[0]->label;
|
||||
}
|
||||
/* 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 (!s->has_percentage) {
|
||||
s->has_percentage = 1;
|
||||
s->percentage = sc_update[mod_id]->dl[0]->percentage;
|
||||
}
|
||||
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;
|
||||
if (!s->has_isolation) {
|
||||
s->has_isolation = 1;
|
||||
s->isolation = sc_update[mod_id]->dl[0]->isolation;
|
||||
}
|
||||
if (!s->has_priority) {
|
||||
s->has_priority = 1;
|
||||
s->priority = sc_update[mod_id]->dl[0]->priority;
|
||||
}
|
||||
if (!s->has_position_low) {
|
||||
s->has_position_low = 1;
|
||||
s->position_low = sc_update[mod_id]->dl[0]->position_low;
|
||||
}
|
||||
if (!s->has_position_high) {
|
||||
s->has_position_high = 1;
|
||||
s->position_high = sc_update[mod_id]->dl[0]->position_high;
|
||||
}
|
||||
if (!s->has_maxmcs) {
|
||||
s->has_maxmcs = 1;
|
||||
s->maxmcs = sc_update[mod_id]->dl[0]->maxmcs;
|
||||
}
|
||||
if (s->n_sorting == 0) {
|
||||
s->n_sorting = sc_update[0]->dl[0]->n_sorting;
|
||||
/* TODO Dangerous? */
|
||||
s->sorting = sc_update[0]->dl[0]->sorting;
|
||||
}
|
||||
if (!s->has_accounting) {
|
||||
/* TODO Dangerous? */
|
||||
s->accounting = sc_update[0]->dl[0]->accounting;
|
||||
}
|
||||
/* scheduler name not set, cannot be changed for the moment */
|
||||
}
|
||||
|
||||
Protocol__FlexDlSlice *to = NULL;
|
||||
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 (dls->id == sc_update[mod_id]->dl[i]->id) {
|
||||
to = sc_update[mod_id]->dl[i];
|
||||
break;
|
||||
if (id == sc_update[mod_id]->dl[i]->id) {
|
||||
return sc_update[mod_id]->dl[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void prepare_update_slice_config_ul(mid_t mod_id, Protocol__FlexUlSlice *uls)
|
||||
Protocol__FlexDlSlice *create_new_dl_slice(mid_t mod_id, int id)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
Protocol__FlexUlSlice *to = NULL;
|
||||
void fill_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *s)
|
||||
{
|
||||
/* TODO fill the slice depending on the chosen label */
|
||||
/* for now, we fill it up with the information from slice 0 */
|
||||
/* assume there is an ID (will be checked later) */
|
||||
if (!s->has_label) {
|
||||
s->has_label = 1;
|
||||
s->label = sc_update[mod_id]->ul[0]->label;
|
||||
}
|
||||
if (!s->has_percentage) {
|
||||
s->has_percentage = 1;
|
||||
s->percentage = sc_update[mod_id]->ul[0]->percentage;
|
||||
}
|
||||
if (!s->has_isolation) {
|
||||
s->has_isolation = 1;
|
||||
s->isolation = sc_update[mod_id]->ul[0]->isolation;
|
||||
}
|
||||
if (!s->has_priority) {
|
||||
s->has_priority = 1;
|
||||
s->priority = sc_update[mod_id]->ul[0]->priority;
|
||||
}
|
||||
if (!s->has_first_rb) {
|
||||
s->has_first_rb = 1;
|
||||
s->first_rb = sc_update[mod_id]->ul[0]->first_rb;
|
||||
}
|
||||
if (!s->has_maxmcs) {
|
||||
s->has_maxmcs = 1;
|
||||
s->maxmcs = sc_update[mod_id]->ul[0]->maxmcs;
|
||||
}
|
||||
if (s->n_sorting == 0) {
|
||||
s->n_sorting = sc_update[0]->ul[0]->n_sorting;
|
||||
/* TODO Dangerous? */
|
||||
s->sorting = sc_update[0]->ul[0]->sorting;
|
||||
}
|
||||
if (!s->has_accounting) {
|
||||
/* TODO Dangerous? */
|
||||
s->accounting = sc_update[0]->ul[0]->accounting;
|
||||
}
|
||||
/* scheduler name not set, cannot be changed for the moment */
|
||||
}
|
||||
|
||||
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 (uls->id == sc_update[mod_id]->ul[i]->id) {
|
||||
to = sc_update[mod_id]->ul[i];
|
||||
break;
|
||||
if (id == sc_update[mod_id]->ul[i]->id) {
|
||||
return sc_update[mod_id]->ul[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *slice)
|
||||
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);
|
||||
|
||||
if (slice->n_dl == 0)
|
||||
if (sup->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]);
|
||||
} else {
|
||||
/* verify slice parameters */
|
||||
for (int i = 0; i < sup->n_dl; i++) {
|
||||
fill_dl_slice(mod_id, sup->dl[i]);
|
||||
verified = verified && flexran_verify_dl_slice(mod_id, sup->dl[i]);
|
||||
if (!verified) break;
|
||||
}
|
||||
|
||||
if (slice->n_ul == 0)
|
||||
/* 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(dls, sup->dl[i]);
|
||||
}
|
||||
} else {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] DL slice verification failed, refusing application\n", mod_id);
|
||||
}
|
||||
}
|
||||
|
||||
verified = 1;
|
||||
if (sup->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]);
|
||||
} else {
|
||||
/* verify slice parameters */
|
||||
for (int i = 0; i < sup->n_ul; i++) {
|
||||
fill_ul_slice(mod_id, sup->ul[i]);
|
||||
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(uls, sup->ul[i]);
|
||||
}
|
||||
} else {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] UL slice verification failed, refusing application\n", mod_id);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&sc_update_mtx);
|
||||
|
||||
/* perform the slice configuration reads a couple of times. If there are
|
||||
@@ -1299,11 +1396,6 @@ int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protoco
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1365,11 +1457,6 @@ int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protoco
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file flexran_agent_mac_slice_verification.c
|
||||
* \brief MAC Agent slice verification helper functions
|
||||
* \author Robert Schmidt
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
*/
|
||||
|
||||
|
||||
#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] illegal DL slice percentage (%d)\n", mod_id, dls->percentage);
|
||||
return 0;
|
||||
}
|
||||
/* isolation is a protobuf bool */
|
||||
if (!flexran_dl_slice_verify_priority(dls->priority)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] illegal DL slice priority (%d)\n", mod_id, dls->priority);
|
||||
return 0;
|
||||
}
|
||||
if (!flexran_dl_slice_verify_position(dls->position_low, dls->position_high)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] illegal DL slice position low (%d) and/or high (%d)\n",
|
||||
mod_id, dls->position_low, dls->position_high);
|
||||
return 0;
|
||||
}
|
||||
if (!flexran_dl_slice_verify_maxmcs(dls->maxmcs)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] illegal DL slice max mcs %d\n", mod_id, dls->maxmcs);
|
||||
return 0;
|
||||
}
|
||||
if (dls->n_sorting == 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] no sorting in DL slice", mod_id);
|
||||
return 0;
|
||||
}
|
||||
if (!dls->sorting) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] no sorting found in DL slice\n", mod_id);
|
||||
return 0;
|
||||
}
|
||||
/* sorting is an enum */
|
||||
/* accounting is an enum */
|
||||
if (dls->scheduler_name) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] setting the scheduler is not allowed\n", mod_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 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;
|
||||
}
|
||||
|
||||
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] illegal UL slice percentage (%d)\n", mod_id, uls->percentage);
|
||||
return 0;
|
||||
}
|
||||
/* isolation is a protobuf bool */
|
||||
if (!flexran_ul_slice_verify_priority(uls->priority)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] illegal UL slice percentage (%d)\n", mod_id, uls->priority);
|
||||
return 0;
|
||||
}
|
||||
if (!flexran_ul_slice_verify_first_rb(uls->first_rb)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] illegal UL slice first RB (%d)\n", mod_id, uls->first_rb);
|
||||
return 0;
|
||||
}
|
||||
if (!flexran_ul_slice_verify_maxmcs(uls->maxmcs)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] illegal UL slice max mcs (%d)\n", mod_id, uls->maxmcs);
|
||||
return 0;
|
||||
}
|
||||
if (uls->n_sorting == 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] no sorting in UL slice\n", mod_id);
|
||||
return 0;
|
||||
}
|
||||
if (!uls->sorting) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] no sorting found in UL slice\n", mod_id);
|
||||
return 0;
|
||||
}
|
||||
/* sorting is an enum */
|
||||
/* accounting is an enum */
|
||||
if (uls->scheduler_name) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] setting the scheduler is not allowed\n", mod_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 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;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file flexran_agent_mac_slice_verification.h
|
||||
* \brief MAC Agent slice verification helper functions
|
||||
* \author Robert Schmidt
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
*/
|
||||
|
||||
#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);
|
||||
@@ -414,193 +414,7 @@ schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, in
|
||||
slice_info_t *sli = &RC.mac[module_idP]->slice_info;
|
||||
memset(sli->rballoc_sub, 0, sizeof(sli->rballoc_sub));
|
||||
|
||||
sli->tot_pct_dl = 0;
|
||||
sli->avg_pct_dl = 1.0 / sli->n_dl;
|
||||
//sli->slice_counter = sli->n_dl;
|
||||
|
||||
for (i = 0; i < sli->n_dl; i++) {
|
||||
if (sli->dl[i].pct < 0) {
|
||||
LOG_W(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: invalid percentage %f. resetting to zero",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP, sli->dl[i].pct);
|
||||
sli->dl[i].pct = 0;
|
||||
}
|
||||
sli->tot_pct_dl += sli->dl[i].pct;
|
||||
}
|
||||
|
||||
// Check for *intra*slice share activation
|
||||
if (sli->intraslice_share_active_current != sli->intraslice_share_active) {
|
||||
if (sli->intraslice_share_active != 1 && sli->intraslice_share_active != 0) {
|
||||
LOG_W(MAC,
|
||||
"[eNB %d][DL] frame %d subframe %d: invalid intraslice sharing status (%d), revert to its previous value (%d)\n",
|
||||
module_idP, frameP, subframeP, sli->intraslice_share_active, sli->intraslice_share_active_current);
|
||||
sli->intraslice_share_active = sli->intraslice_share_active_current;
|
||||
} else {
|
||||
LOG_N(MAC, "[eNB %d][DL] frame %d subframe %d: intraslice sharing status has changed (%x-->%x)\n",
|
||||
module_idP, frameP, subframeP, sli->intraslice_share_active_current, sli->intraslice_share_active);
|
||||
sli->intraslice_share_active_current = sli->intraslice_share_active;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for *inter*slice share activation
|
||||
if (sli->interslice_share_active_current != sli->interslice_share_active) {
|
||||
if (sli->interslice_share_active != 1 && sli->interslice_share_active != 0) {
|
||||
LOG_W(MAC,
|
||||
"[eNB %d][DL] frame %d subframe %d: invalid interslice sharing status (%d), revert to its previous value (%d)\n",
|
||||
module_idP, frameP, subframeP, sli->interslice_share_active, sli->interslice_share_active_current);
|
||||
sli->interslice_share_active = sli->interslice_share_active_current;
|
||||
} else {
|
||||
LOG_N(MAC, "[eNB %d][DL] frame %d subframe %d: interslice sharing status has changed (%x-->%x)\n",
|
||||
module_idP, frameP, subframeP, sli->interslice_share_active_current, sli->interslice_share_active);
|
||||
sli->interslice_share_active_current = sli->interslice_share_active;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sli->n_dl; i++) {
|
||||
|
||||
// Load any updated functions
|
||||
if (sli->dl[i].update_sched > 0) {
|
||||
sli->dl[i].sched_cb = dlsym(NULL, sli->dl[i].sched_name);
|
||||
sli->dl[i].update_sched = 0;
|
||||
sli->dl[i].update_sched_current = 0;
|
||||
LOG_I(MAC, "update dl scheduler (%s) slice index %d ID %d\n",
|
||||
sli->dl[i].sched_name, i, sli->dl[i].id);
|
||||
}
|
||||
|
||||
if (sli->tot_pct_dl <= 1.0) { // the new total RB share is within the range
|
||||
|
||||
// check if the number of slices has changed, and log
|
||||
if (sli->n_dl_current != sli->n_dl) {
|
||||
if ((sli->n_dl > 0) && (sli->n_dl <= MAX_NUM_SLICES)) {
|
||||
LOG_I(MAC, "[eNB %d]frame %d subframe %d: number of active DL slices has changed: %d-->%d\n",
|
||||
module_idP, frameP, subframeP, sli->n_dl_current, sli->n_dl);
|
||||
sli->n_dl_current = sli->n_dl;
|
||||
} else {
|
||||
LOG_W(MAC, "invalid number of DL slices %d, revert to the previous value %d\n",
|
||||
sli->n_dl, sli->n_dl_current);
|
||||
sli->n_dl = sli->n_dl_current;
|
||||
}
|
||||
}
|
||||
|
||||
// check if the slice rb share has changed, and log the console
|
||||
if (sli->dl[i].pct_current != sli->dl[i].pct) { // new slice percentage
|
||||
LOG_I(MAC,
|
||||
"[eNB %d][SLICE %d][DL] frame %d subframe %d: total percentage %f-->%f, slice RB percentage has changed: %f-->%f\n",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP,
|
||||
sli->tot_pct_dl_current, sli->tot_pct_dl,
|
||||
sli->dl[i].pct_current, sli->dl[i].pct);
|
||||
sli->tot_pct_dl_current = sli->tot_pct_dl;
|
||||
sli->dl[i].pct_current = sli->dl[i].pct;
|
||||
}
|
||||
|
||||
// check if the slice max MCS, and log the console
|
||||
if (sli->dl[i].maxmcs_current != sli->dl[i].maxmcs) {
|
||||
if ((sli->dl[i].maxmcs >= 0) && (sli->dl[i].maxmcs < 29)) {
|
||||
LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: slice MAX MCS has changed: %d-->%d\n",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP,
|
||||
sli->dl[i].maxmcs_current, sli->dl[i].maxmcs);
|
||||
sli->dl[i].maxmcs_current = sli->dl[i].maxmcs;
|
||||
} else {
|
||||
LOG_W(MAC, "[eNB %d][SLICE %d][DL] invalid slice max mcs %d, revert the previous value %d\n",
|
||||
module_idP, sli->dl[i].id, sli->dl[i].maxmcs, sli->dl[i].maxmcs_current);
|
||||
sli->dl[i].maxmcs = sli->dl[i].maxmcs_current;
|
||||
}
|
||||
}
|
||||
|
||||
// check if a new scheduler, and log the console
|
||||
if (sli->dl[i].update_sched_current != sli->dl[i].update_sched) {
|
||||
LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: DL scheduler for this slice is updated: %s \n",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP, sli->dl[i].sched_name);
|
||||
sli->dl[i].update_sched_current = sli->dl[i].update_sched;
|
||||
}
|
||||
|
||||
} else {
|
||||
// here we can correct the values, e.g. reduce proportionally
|
||||
|
||||
if (sli->n_dl == sli->n_dl_current) {
|
||||
LOG_W(MAC,
|
||||
"[eNB %d][SLICE %d][DL] invalid total RB share (%f->%f), reduce proportionally the RB share by 0.1\n",
|
||||
module_idP, sli->dl[i].id, sli->tot_pct_dl_current, sli->tot_pct_dl);
|
||||
if (sli->dl[i].pct >= sli->avg_pct_dl) {
|
||||
sli->dl[i].pct -= 0.1;
|
||||
sli->tot_pct_dl -= 0.1;
|
||||
}
|
||||
} else {
|
||||
LOG_W(MAC,
|
||||
"[eNB %d][SLICE %d][DL] invalid total RB share (%f->%f), revert the number of slice to its previous value (%d->%d)\n",
|
||||
module_idP, sli->dl[i].id, sli->tot_pct_dl_current, sli->tot_pct_dl,
|
||||
sli->n_dl, sli->n_dl_current);
|
||||
sli->n_dl = sli->n_dl_current;
|
||||
sli->dl[i].pct = sli->dl[i].pct_current;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for new slice positions
|
||||
if (sli->dl[i].pos_low > sli->dl[i].pos_high ||
|
||||
sli->dl[i].pos_low < 0 ||
|
||||
sli->dl[i].pos_high > N_RBG_MAX) {
|
||||
LOG_W(MAC, "[eNB %d][SLICE %d][DL] invalid slicing position (%d-%d), using previous values (%d-%d)\n",
|
||||
module_idP, sli->dl[i].id,
|
||||
sli->dl[i].pos_low, sli->dl[i].pos_high,
|
||||
sli->dl[i].pos_low_current, sli->dl[i].pos_high_current);
|
||||
sli->dl[i].pos_low = sli->dl[i].pos_low_current;
|
||||
sli->dl[i].pos_high = sli->dl[i].pos_high_current;
|
||||
} else {
|
||||
if (sli->dl[i].pos_low_current != sli->dl[i].pos_low) {
|
||||
LOG_N(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: start frequency has changed (%d-->%d)\n",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP, sli->dl[i].pos_low_current, sli->dl[i].pos_low);
|
||||
sli->dl[i].pos_low_current = sli->dl[i].pos_low;
|
||||
}
|
||||
if (sli->dl[i].pos_high_current != sli->dl[i].pos_high) {
|
||||
LOG_N(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: end frequency has changed (%d-->%d)\n",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP, sli->dl[i].pos_high_current, sli->dl[i].pos_high);
|
||||
sli->dl[i].pos_high_current = sli->dl[i].pos_high;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for new sorting policy
|
||||
if (sli->dl[i].sorting_current != sli->dl[i].sorting) {
|
||||
LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: UE sorting policy has changed (%x-->%x)\n",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP, sli->dl[i].sorting_current, sli->dl[i].sorting);
|
||||
sli->dl[i].sorting_current = sli->dl[i].sorting;
|
||||
}
|
||||
|
||||
// Check for new slice isolation
|
||||
if (sli->dl[i].isol_current != sli->dl[i].isol) {
|
||||
if (sli->dl[i].isol != 1 && sli->dl[i].isol != 0) {
|
||||
LOG_W(MAC,
|
||||
"[eNB %d][SLICE %d][DL] frame %d subframe %d: invalid slice isolation setting (%d), revert to its previous value (%d)\n",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP, sli->dl[i].isol, sli->dl[i].isol_current);
|
||||
sli->dl[i].isol = sli->dl[i].isol_current;
|
||||
} else {
|
||||
LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: slice isolation setting has changed (%x-->%x)\n",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP, sli->dl[i].isol_current, sli->dl[i].isol);
|
||||
sli->dl[i].isol_current = sli->dl[i].isol;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for new slice priority
|
||||
if (sli->dl[i].prio_current != sli->dl[i].prio) {
|
||||
LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: slice priority setting has changed (%d-->%d)\n",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP, sli->dl[i].prio_current, sli->dl[i].prio);
|
||||
sli->dl[i].prio_current = sli->dl[i].prio;
|
||||
}
|
||||
|
||||
// Check for new accounting policy
|
||||
if (sli->dl[i].accounting_current != sli->dl[i].accounting) {
|
||||
if (sli->dl[i].accounting > 1 || sli->dl[i].accounting < 0) {
|
||||
LOG_W(MAC,
|
||||
"[eNB %d][SLICE %d][DL] frame %d subframe %d: invalid accounting policy (%d), revert to its previous value (%d)\n",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP,
|
||||
sli->dl[i].accounting, sli->dl[i].accounting_current);
|
||||
sli->dl[i].accounting = sli->dl[i].accounting_current;
|
||||
} else {
|
||||
LOG_N(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: UE sorting policy has changed (%x-->%x)\n",
|
||||
module_idP, sli->dl[i].id, frameP, subframeP,
|
||||
sli->dl[i].accounting_current, sli->dl[i].accounting);
|
||||
sli->dl[i].accounting_current = sli->dl[i].accounting;
|
||||
}
|
||||
}
|
||||
|
||||
// Run each enabled slice-specific schedulers one by one
|
||||
sli->dl[i].sched_cb(module_idP, i, frameP, subframeP, mbsfn_flag/*, dl_info*/);
|
||||
}
|
||||
|
||||
@@ -1038,112 +1038,7 @@ schedule_ulsch(module_id_t module_idP, frame_t frameP,
|
||||
}
|
||||
}
|
||||
|
||||
// perform slice-specifc operations
|
||||
|
||||
sli->tot_pct_ul = 0;
|
||||
sli->avg_pct_ul = 1.0 / sli->n_ul;
|
||||
|
||||
for (i = 0; i < sli->n_ul; i++) {
|
||||
if (sli->ul[i].pct < 0 ){
|
||||
LOG_W(MAC,
|
||||
"[eNB %d][SLICE %d][UL] frame %d subframe %d: invalid percentage %f. resetting to zero",
|
||||
module_idP, sli->ul[i].id, frameP, subframeP, sli->ul[i].pct);
|
||||
sli->ul[i].pct = 0;
|
||||
}
|
||||
sli->tot_pct_ul += sli->ul[i].pct;
|
||||
}
|
||||
|
||||
for (i = 0; i < sli->n_ul; i++) {
|
||||
|
||||
// Load any updated functions
|
||||
if (sli->ul[i].update_sched > 0 ) {
|
||||
sli->ul[i].sched_cb = dlsym(NULL, sli->ul[i].sched_name);
|
||||
sli->ul[i].update_sched = 0;
|
||||
sli->ul[i].update_sched_current = 0;
|
||||
//sli->ul[i].pct_current = sli->ul[i].pct;
|
||||
//sli->tot_pct_ul_current += sli->ul[i].pct;
|
||||
//if (sli->tot_pct_ul_current > 1)
|
||||
//sli->tot_pct_ul_current = 1;
|
||||
LOG_I(MAC,"update ul scheduler (%s) slice index %d ID %d\n",
|
||||
sli->ul[i].sched_name, i, sli->ul[i].id);
|
||||
}
|
||||
// the new total RB share is within the range
|
||||
if (sli->tot_pct_ul <= 1.0){
|
||||
|
||||
// check if the number of slices has changed, and log
|
||||
if (sli->n_ul_current != sli->n_ul ){
|
||||
if ((sli->n_ul > 0) && (sli->n_ul <= MAX_NUM_SLICES)) {
|
||||
LOG_I(MAC,"[eNB %d]frame %d subframe %d: number of active UL slices has changed: %d-->%d\n",
|
||||
module_idP, frameP, subframeP, sli->n_ul_current, sli->n_ul);
|
||||
sli->n_ul_current = sli->n_ul;
|
||||
} else {
|
||||
LOG_W(MAC,"invalid number of UL slices %d, revert to the previous value %d\n",
|
||||
sli->n_ul, sli->n_ul_current);
|
||||
sli->n_ul = sli->n_ul_current;
|
||||
}
|
||||
}
|
||||
|
||||
// check if the slice rb share has changed, and log the console
|
||||
if (sli->ul[i].pct_current != sli->ul[i].pct){
|
||||
LOG_I(MAC,"[eNB %d][SLICE %d][UL] frame %d subframe %d: total percentage %f-->%f, slice RB percentage has changed: %f-->%f\n",
|
||||
module_idP, sli->ul[i].id, frameP, subframeP, sli->tot_pct_ul_current,
|
||||
sli->tot_pct_ul, sli->ul[i].pct_current, sli->ul[i].pct);
|
||||
sli->tot_pct_ul_current = sli->tot_pct_ul;
|
||||
sli->ul[i].pct_current = sli->ul[i].pct;
|
||||
}
|
||||
|
||||
// check if the slice max MCS, and log the console
|
||||
if (sli->ul[i].maxmcs_current != sli->ul[i].maxmcs){
|
||||
if ((sli->ul[i].maxmcs >= 0) && (sli->ul[i].maxmcs <= 20)){
|
||||
LOG_I(MAC,"[eNB %d][SLICE %d][UL] frame %d subframe %d: slice MAX MCS has changed: %d-->%d\n",
|
||||
module_idP, sli->ul[i].id, frameP, subframeP,
|
||||
sli->ul[i].maxmcs_current, sli->ul[i].maxmcs);
|
||||
sli->ul[i].maxmcs_current = sli->ul[i].maxmcs;
|
||||
} else {
|
||||
LOG_W(MAC,"[eNB %d][SLICE %d][UL] invalid slice max mcs %d, revert the previous value %d\n",
|
||||
module_idP, sli->ul[i].id, sli->ul[i].maxmcs, sli->ul[i].maxmcs_current);
|
||||
sli->ul[i].maxmcs = sli->ul[i].maxmcs_current;
|
||||
}
|
||||
}
|
||||
|
||||
if (sli->ul[i].first_rb_current != sli->ul[i].first_rb){
|
||||
if (sli->ul[i].first_rb >= 0){ // FIXME: Max limit is checked in the scheduler
|
||||
LOG_N(MAC,"[eNB %d][SLICE %d][UL] frame %d subframe %d: slice first rb has changed: %d-->%d\n",
|
||||
module_idP, sli->ul[i].id, frameP, subframeP,
|
||||
sli->ul[i].first_rb_current, sli->ul[i].first_rb);
|
||||
sli->ul[i].first_rb_current = sli->ul[i].first_rb;
|
||||
} else {
|
||||
LOG_W(MAC,"[eNB %d][SLICE %d][UL] invalid slice first rb %d, revert the previous value %d\n",
|
||||
module_idP, sli->ul[i].id, sli->ul[i].first_rb,
|
||||
sli->ul[i].first_rb_current);
|
||||
sli->ul[i].first_rb = sli->ul[i].first_rb_current;
|
||||
}
|
||||
}
|
||||
|
||||
// check if a new scheduler, and log the console
|
||||
if (sli->ul[i].update_sched_current != sli->ul[i].update_sched) {
|
||||
LOG_I(MAC,"[eNB %d][SLICE %d][UL] frame %d subframe %d: UL scheduler for this slice is updated: %s \n",
|
||||
module_idP, sli->ul[i].id, frameP, subframeP, sli->ul[i].sched_name);
|
||||
sli->ul[i].update_sched_current = sli->ul[i].update_sched;
|
||||
}
|
||||
} else {
|
||||
if (sli->n_ul == sli->n_ul_current) {
|
||||
LOG_W(MAC,"[eNB %d][SLICE %d][UL] invalid total RB share (%f->%f), reduce proportionally the RB share by 0.1\n",
|
||||
module_idP, sli->ul[i].id, sli->tot_pct_ul_current, sli->tot_pct_ul);
|
||||
if (sli->ul[i].pct > sli->avg_pct_ul) {
|
||||
sli->ul[i].pct -= 0.1;
|
||||
sli->tot_pct_ul -= 0.1;
|
||||
}
|
||||
} else {
|
||||
// here we can correct the values, e.g. reduce proportionally
|
||||
LOG_W(MAC,"[eNB %d][SLICE %d][UL] invalid total RB share (%f->%f), revert the number of slice to its previous value (%d->%d)\n",
|
||||
module_idP, sli->ul[i].id, sli->tot_pct_ul_current,
|
||||
sli->tot_pct_ul, sli->n_ul, sli->n_ul_current);
|
||||
sli->n_ul = sli->n_ul_current;
|
||||
sli->ul[i].pct = sli->ul[i].pct_current;
|
||||
}
|
||||
}
|
||||
|
||||
// Run each enabled slice-specific schedulers one by one
|
||||
sli->ul[i].sched_cb(module_idP, i, frameP, subframeP, sched_subframe, first_rb);
|
||||
}
|
||||
|
||||
@@ -1151,38 +1151,29 @@ typedef void (*slice_scheduler_dl)(module_id_t mod_id,
|
||||
typedef struct {
|
||||
slice_id_t id;
|
||||
|
||||
/// RB share for each slice for past and current time
|
||||
/// RB share for each slice
|
||||
float pct;
|
||||
float pct_current;
|
||||
|
||||
/// whether this slice is isolated from the others for past and current time
|
||||
/// whether this slice is isolated from the others
|
||||
int isol;
|
||||
int isol_current;
|
||||
|
||||
int prio;
|
||||
int prio_current;
|
||||
|
||||
/// Frequency ranges for slice positioning
|
||||
int pos_low;
|
||||
int pos_high;
|
||||
int pos_low_current;
|
||||
int pos_high_current;
|
||||
|
||||
// max mcs for each slice for past and current time
|
||||
// max mcs for each slice
|
||||
int maxmcs;
|
||||
int maxmcs_current;
|
||||
|
||||
/// criteria for sorting policies of the slices
|
||||
uint32_t sorting;
|
||||
uint32_t sorting_current;
|
||||
|
||||
/// Accounting policy (just greedy(1) or fair(0) setting for now)
|
||||
int accounting;
|
||||
int accounting_current;
|
||||
|
||||
/// Whether the scheduler callback should be updated
|
||||
int update_sched;
|
||||
int update_sched_current;
|
||||
|
||||
/// name of available scheduler
|
||||
char *sched_name;
|
||||
@@ -1202,25 +1193,20 @@ typedef void (*slice_scheduler_ul)(module_id_t mod_id,
|
||||
typedef struct {
|
||||
slice_id_t id;
|
||||
|
||||
/// RB share for each slice for past and current time
|
||||
/// RB share for each slice
|
||||
float pct;
|
||||
float pct_current;
|
||||
|
||||
// MAX MCS for each slice for past and current time
|
||||
// MAX MCS for each slice
|
||||
int maxmcs;
|
||||
int maxmcs_current;
|
||||
|
||||
/// criteria for sorting policies of the slices
|
||||
uint32_t sorting;
|
||||
uint32_t sorting_current;
|
||||
|
||||
/// starting RB (RB offset) of UL scheduling
|
||||
int first_rb;
|
||||
int first_rb_current;
|
||||
|
||||
/// Slice scheduler callback update needed
|
||||
int update_sched;
|
||||
int update_sched_current;
|
||||
|
||||
/// name of available scheduler
|
||||
char *sched_name;
|
||||
@@ -1238,28 +1224,16 @@ typedef struct {
|
||||
/// indicates whether remaining RBs after first intra-slice allocation will
|
||||
/// be allocated to UEs of the same slice
|
||||
int intraslice_share_active;
|
||||
int intraslice_share_active_current;
|
||||
/// indicates whether remaining RBs after slice allocation will be
|
||||
/// allocated to UEs of another slice. Isolated slices will be ignored
|
||||
int interslice_share_active;
|
||||
int interslice_share_active_current;
|
||||
|
||||
/// number of active slices for past and current time in DL
|
||||
/// number of active DL slices
|
||||
int n_dl;
|
||||
int n_dl_current;
|
||||
/// RB share stats for DL
|
||||
float tot_pct_dl;
|
||||
float tot_pct_dl_current;
|
||||
float avg_pct_dl;
|
||||
slice_sched_conf_dl_t dl[MAX_NUM_SLICES];
|
||||
|
||||
/// number of active slices for past and current time in UL
|
||||
/// number of active UL slices
|
||||
int n_ul;
|
||||
int n_ul_current;
|
||||
/// RB share stats for UL
|
||||
float tot_pct_ul;
|
||||
float tot_pct_ul_current;
|
||||
float avg_pct_ul;
|
||||
slice_sched_conf_ul_t ul[MAX_NUM_SLICES];
|
||||
|
||||
pre_processor_results_t pre_processor_results[MAX_NUM_SLICES];
|
||||
|
||||
@@ -138,44 +138,24 @@ void mac_top_init_eNB(void)
|
||||
sli = &mac->slice_info;
|
||||
|
||||
sli->intraslice_share_active = 1;
|
||||
sli->intraslice_share_active_current = 1;
|
||||
sli->interslice_share_active = 1;
|
||||
sli->interslice_share_active_current = 1;
|
||||
|
||||
sli->n_dl = 1;
|
||||
sli->n_dl_current = 1;
|
||||
sli->tot_pct_dl = 1;
|
||||
sli->tot_pct_dl_current = 1;
|
||||
sli->avg_pct_dl = 0.25;
|
||||
memset(sli->dl, 0, sizeof(slice_sched_conf_dl_t) * MAX_NUM_SLICES);
|
||||
sli->dl[0].pct = 1.0;
|
||||
sli->dl[0].pct_current = 1.0;
|
||||
sli->dl[0].prio = 10;
|
||||
sli->dl[0].prio_current = 10;
|
||||
sli->dl[0].pos_high = N_RBG_MAX;
|
||||
sli->dl[0].pos_high_current = N_RBG_MAX;
|
||||
sli->dl[0].maxmcs = 28;
|
||||
sli->dl[0].maxmcs_current = 28;
|
||||
sli->dl[0].sorting = 0x012345;
|
||||
sli->dl[0].sorting_current = 0x012345;
|
||||
sli->dl[0].update_sched = 1;
|
||||
sli->dl[0].update_sched_current = 1;
|
||||
sli->dl[0].sched_name = "schedule_ue_spec";
|
||||
|
||||
sli->n_ul = 1;
|
||||
sli->n_ul_current = 1;
|
||||
sli->tot_pct_ul = 1;
|
||||
sli->tot_pct_ul_current = 1;
|
||||
sli->avg_pct_ul = 0.25;
|
||||
memset(sli->ul, 0, sizeof(slice_sched_conf_ul_t) * MAX_NUM_SLICES);
|
||||
sli->ul[0].pct = 1.0;
|
||||
sli->ul[0].pct_current = 1.0;
|
||||
sli->ul[0].maxmcs = 20;
|
||||
sli->ul[0].maxmcs_current = 20;
|
||||
sli->ul[0].sorting = 0x0123;
|
||||
sli->ul[0].sorting_current = 0x0123;
|
||||
sli->ul[0].update_sched = 1;
|
||||
sli->ul[0].update_sched_current = 1;
|
||||
sli->ul[0].sched_name = "schedule_ulsch_rnti";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user