Merge remote-tracking branch 'origin/develop' into NR_UL_scheduling
This commit is contained in:
@@ -49,18 +49,13 @@ struct lfds700_misc_prng_state ps[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB];
|
||||
|
||||
/* the slice config as kept in the underlying system */
|
||||
Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES];
|
||||
/* a structure that keeps updates which will be reflected in slice_config later */
|
||||
Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES];
|
||||
/* indicates whether sc_update contains new data */
|
||||
int perform_slice_config_update_count = 1;
|
||||
/* queue of incoming new UE<>slice association commands */
|
||||
Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES];
|
||||
int n_ue_slice_assoc_updates = 0;
|
||||
/* mutex for sc_update: do not receive new config and write it at the same time */
|
||||
pthread_mutex_t sc_update_mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
/* Ringbuffer-related to slice configuration */
|
||||
struct lfds700_ringbuffer_element *slice_config_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state slice_config_ringbuffer_state[NUM_MAX_ENB];
|
||||
|
||||
/* Ringbuffer-related to slice configuration */
|
||||
struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB];
|
||||
|
||||
int flexran_agent_mac_stats_reply_ue(mid_t mod_id,
|
||||
Protocol__FlexUeStatsReport **ue_report,
|
||||
@@ -1354,6 +1349,33 @@ void flexran_agent_init_mac_agent(mid_t mod_id) {
|
||||
AssertFatal(i == 0, "posix_memalign(): could not allocate aligned memory for lfds library\n");
|
||||
lfds700_ringbuffer_init_valid_on_current_logical_core(&ringbuffer_state[mod_id],
|
||||
dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL);
|
||||
|
||||
struct lfds700_misc_prng_state scrng;
|
||||
i = posix_memalign((void **) &slice_config_array[mod_id],
|
||||
LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES,
|
||||
sizeof(struct lfds700_ringbuffer_element) * num_elements);
|
||||
AssertFatal(i == 0,
|
||||
"posix_memalign(): could not allocate aligned memory\n");
|
||||
lfds700_ringbuffer_init_valid_on_current_logical_core(
|
||||
&slice_config_ringbuffer_state[mod_id],
|
||||
slice_config_array[mod_id],
|
||||
num_elements,
|
||||
&scrng,
|
||||
NULL);
|
||||
|
||||
struct lfds700_misc_prng_state uarng;
|
||||
i = posix_memalign((void **) &ue_assoc_array[mod_id],
|
||||
LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES,
|
||||
sizeof(struct lfds700_ringbuffer_element) * num_elements);
|
||||
AssertFatal(i == 0,
|
||||
"posix_memalign(): could not allocate aligned memory\n");
|
||||
lfds700_ringbuffer_init_valid_on_current_logical_core(
|
||||
&ue_assoc_ringbuffer_state[mod_id],
|
||||
ue_assoc_array[mod_id],
|
||||
num_elements,
|
||||
&uarng,
|
||||
NULL);
|
||||
|
||||
for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (RC.mac && RC.mac[mod_id])
|
||||
@@ -1465,9 +1487,74 @@ void flexran_agent_fill_mac_cell_config(mid_t mod_id, uint8_t cc_id,
|
||||
conf->si_config->has_sfn = 1;
|
||||
}
|
||||
|
||||
/* get a pointer to the config which is maintained in the agent throughout
|
||||
* its lifetime */
|
||||
conf->slice_config = flexran_agent_get_slice_config(mod_id);
|
||||
conf->slice_config = malloc(sizeof(Protocol__FlexSliceConfig));
|
||||
if (conf->slice_config) {
|
||||
protocol__flex_slice_config__init(conf->slice_config);
|
||||
Protocol__FlexSliceConfig *sc = conf->slice_config;
|
||||
|
||||
sc->dl = malloc(sizeof(Protocol__FlexSliceDlUlConfig));
|
||||
DevAssert(sc->dl);
|
||||
protocol__flex_slice_dl_ul_config__init(sc->dl);
|
||||
sc->dl->algorithm = flexran_get_dl_slice_algo(mod_id);
|
||||
sc->dl->has_algorithm = 1;
|
||||
sc->dl->n_slices = flexran_get_num_dl_slices(mod_id);
|
||||
if (sc->dl->n_slices > 0) {
|
||||
sc->dl->slices = calloc(sc->dl->n_slices, sizeof(Protocol__FlexSlice *));
|
||||
DevAssert(sc->dl->slices);
|
||||
for (int i = 0; i < sc->dl->n_slices; ++i) {
|
||||
sc->dl->slices[i] = malloc(sizeof(Protocol__FlexSlice));
|
||||
DevAssert(sc->dl->slices[i]);
|
||||
protocol__flex_slice__init(sc->dl->slices[i]);
|
||||
flexran_get_dl_slice(mod_id, i, sc->dl->slices[i], sc->dl->algorithm);
|
||||
}
|
||||
} else {
|
||||
sc->dl->scheduler = flexran_get_dl_scheduler_name(mod_id);
|
||||
}
|
||||
|
||||
sc->ul = malloc(sizeof(Protocol__FlexSliceDlUlConfig));
|
||||
DevAssert(sc->ul);
|
||||
protocol__flex_slice_dl_ul_config__init(sc->ul);
|
||||
sc->ul->algorithm = flexran_get_ul_slice_algo(mod_id);
|
||||
sc->ul->has_algorithm = 1;
|
||||
sc->ul->n_slices = flexran_get_num_ul_slices(mod_id);
|
||||
if (sc->ul->n_slices > 0) {
|
||||
sc->ul->slices = calloc(sc->ul->n_slices, sizeof(Protocol__FlexSlice *));
|
||||
DevAssert(sc->ul->slices);
|
||||
for (int i = 0; i < sc->ul->n_slices; ++i) {
|
||||
sc->ul->slices[i] = malloc(sizeof(Protocol__FlexSlice));
|
||||
DevAssert(sc->ul->slices[i]);
|
||||
protocol__flex_slice__init(sc->ul->slices[i]);
|
||||
flexran_get_ul_slice(mod_id, i, sc->ul->slices[i], sc->ul->algorithm);
|
||||
}
|
||||
} else {
|
||||
sc->ul->scheduler = flexran_get_ul_scheduler_name(mod_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf) {
|
||||
Protocol__FlexSliceConfig *sc = conf->slice_config;
|
||||
for (int i = 0; i < sc->dl->n_slices; ++i) {
|
||||
free(sc->dl->slices[i]);
|
||||
sc->dl->slices[i] = NULL;
|
||||
/* scheduler names are not freed: we assume we read them directly from the
|
||||
* underlying memory and do not dispose it */
|
||||
}
|
||||
free(sc->dl->slices);
|
||||
/* scheduler name is not freed */
|
||||
free(sc->dl);
|
||||
sc->dl = NULL;
|
||||
for (int i = 0; i < sc->ul->n_slices; ++i) {
|
||||
free(sc->ul->slices[i]);
|
||||
sc->ul->slices[i] = NULL;
|
||||
/* scheduler names are not freed */
|
||||
}
|
||||
free(sc->ul->slices);
|
||||
/* scheduler name is not freed */
|
||||
free(sc->ul);
|
||||
sc->ul = NULL;
|
||||
free(conf->slice_config);
|
||||
conf->slice_config = NULL;
|
||||
}
|
||||
|
||||
void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id,
|
||||
@@ -1481,10 +1568,12 @@ void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id,
|
||||
ue_conf->rnti = flexran_get_mac_ue_crnti(mod_id, ue_id);
|
||||
ue_conf->has_rnti = 1;
|
||||
|
||||
ue_conf->dl_slice_id = flexran_get_ue_dl_slice_id(mod_id, ue_id);
|
||||
ue_conf->has_dl_slice_id = 1;
|
||||
ue_conf->ul_slice_id = flexran_get_ue_ul_slice_id(mod_id, ue_id);
|
||||
ue_conf->has_ul_slice_id = 1;
|
||||
int dl_id = flexran_get_ue_dl_slice_id(mod_id, ue_id);
|
||||
ue_conf->dl_slice_id = dl_id;
|
||||
ue_conf->has_dl_slice_id = dl_id >= 0;
|
||||
int ul_id = flexran_get_ue_ul_slice_id(mod_id, ue_id);
|
||||
ue_conf->ul_slice_id = ul_id;
|
||||
ue_conf->has_ul_slice_id = ul_id >= 0;
|
||||
|
||||
ue_conf->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id, ue_id);
|
||||
ue_conf->has_ue_aggregated_max_bitrate_ul = 1;
|
||||
@@ -1565,6 +1654,15 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id)
|
||||
LOG_E(FLEXRAN_AGENT, "MAC agent CM for eNB %d is not registered\n", mod_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lfds700_ringbuffer_cleanup(&ringbuffer_state[mod_id], NULL );
|
||||
free(dl_mac_config_array[mod_id]);
|
||||
lfds700_ringbuffer_cleanup(&slice_config_ringbuffer_state[mod_id], NULL );
|
||||
free(slice_config_array[mod_id]);
|
||||
lfds700_ringbuffer_cleanup(&ue_assoc_ringbuffer_state[mod_id], NULL );
|
||||
free(ue_assoc_array[mod_id]);
|
||||
lfds700_misc_library_cleanup();
|
||||
|
||||
AGENT_MAC_xface *xface = agent_mac_xface[mod_id];
|
||||
xface->flexran_agent_send_sr_info = NULL;
|
||||
xface->flexran_agent_send_sf_trigger = NULL;
|
||||
@@ -1579,230 +1677,91 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void flexran_create_config_structures(mid_t mod_id)
|
||||
{
|
||||
int i;
|
||||
int n_dl = flexran_get_num_dl_slices(mod_id);
|
||||
int m_ul = flexran_get_num_ul_slices(mod_id);
|
||||
slice_config[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul);
|
||||
sc_update[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul);
|
||||
if (!slice_config[mod_id] || !sc_update[mod_id]) return;
|
||||
|
||||
flexran_agent_read_slice_config(mod_id, slice_config[mod_id]);
|
||||
flexran_agent_read_slice_config(mod_id, sc_update[mod_id]);
|
||||
for (i = 0; i < n_dl; i++) {
|
||||
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
|
||||
flexran_agent_read_slice_dl_config(mod_id, i, sc_update[mod_id]->dl[i]);
|
||||
void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) {
|
||||
if (slice_config->dl) {
|
||||
if (slice_config->dl->scheduler)
|
||||
free(slice_config->dl->scheduler);
|
||||
for (int i = 0; i < slice_config->dl->n_slices; i++)
|
||||
if (slice_config->dl->slices[i]->scheduler)
|
||||
free(slice_config->dl->slices[i]->scheduler);
|
||||
}
|
||||
for (i = 0; i < m_ul; i++) {
|
||||
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
|
||||
flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]);
|
||||
if (slice_config->ul) {
|
||||
if (slice_config->ul->scheduler)
|
||||
free(slice_config->ul->scheduler);
|
||||
for (int i = 0; i < slice_config->ul->n_slices; i++)
|
||||
if (slice_config->ul->slices[i]->scheduler)
|
||||
free(slice_config->ul->slices[i]->scheduler);
|
||||
}
|
||||
|
||||
Protocol__FlexCellConfig helper;
|
||||
helper.slice_config = slice_config;
|
||||
flexran_agent_destroy_mac_slice_config(&helper);
|
||||
}
|
||||
|
||||
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) {
|
||||
if (!*slice_config) return;
|
||||
/* just use the memory and set to NULL in original */
|
||||
Protocol__FlexSliceConfig *sc = *slice_config;
|
||||
*slice_config = NULL;
|
||||
|
||||
struct lfds700_misc_prng_state ls;
|
||||
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
||||
lfds700_misc_prng_init(&ls);
|
||||
enum lfds700_misc_flag overwrite_occurred_flag;
|
||||
|
||||
Protocol__FlexSliceConfig *overwritten_sc;
|
||||
lfds700_ringbuffer_write(&slice_config_ringbuffer_state[mod_id],
|
||||
NULL,
|
||||
(void *)sc,
|
||||
&overwrite_occurred_flag,
|
||||
NULL,
|
||||
(void **)&overwritten_sc,
|
||||
&ls);
|
||||
|
||||
if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) {
|
||||
helper_destroy_mac_slice_config(overwritten_sc);
|
||||
LOG_E(FLEXRAN_AGENT, "lost slice config: too many reconfigurations at once\n");
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_check_and_remove_slices(mid_t mod_id)
|
||||
{
|
||||
Protocol__FlexDlSlice **dl = sc_update[mod_id]->dl;
|
||||
Protocol__FlexDlSlice **dlreal = slice_config[mod_id]->dl;
|
||||
int i = 0;
|
||||
while (i < sc_update[mod_id]->n_dl) {
|
||||
/* remove slices whose percentage is zero */
|
||||
if (dl[i]->percentage > 0) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (flexran_remove_dl_slice(mod_id, i) < 1) {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n",
|
||||
mod_id, i, dl[i]->id);
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n",
|
||||
mod_id, i, dl[i]->id);
|
||||
if (dl[i]->n_sorting > 0) free(dl[i]->sorting);
|
||||
free(dl[i]->scheduler_name);
|
||||
if (dlreal[i]->n_sorting > 0) {
|
||||
dlreal[i]->n_sorting = 0;
|
||||
free(dlreal[i]->sorting);
|
||||
}
|
||||
free(dlreal[i]->scheduler_name);
|
||||
--sc_update[mod_id]->n_dl;
|
||||
--slice_config[mod_id]->n_dl;
|
||||
const size_t last = sc_update[mod_id]->n_dl;
|
||||
/* we need to memcpy the higher slice to the position we just deleted */
|
||||
memcpy(dl[i], dl[last], sizeof(*dl[last]));
|
||||
memset(dl[last], 0, sizeof(*dl[last]));
|
||||
memcpy(dlreal[i], dlreal[last], sizeof(*dlreal[last]));
|
||||
memset(dlreal[last], 0, sizeof(*dlreal[last]));
|
||||
/* dont increase i but recheck the slice which has been copied to here */
|
||||
}
|
||||
Protocol__FlexUlSlice **ul = sc_update[mod_id]->ul;
|
||||
Protocol__FlexUlSlice **ulreal = slice_config[mod_id]->ul;
|
||||
i = 0;
|
||||
while (i < sc_update[mod_id]->n_ul) {
|
||||
if (ul[i]->percentage > 0) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (flexran_remove_ul_slice(mod_id, i) < 1) {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n",
|
||||
mod_id, i, ul[i]->id);
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n",
|
||||
mod_id, i, ul[i]->id);
|
||||
free(ul[i]->scheduler_name);
|
||||
free(ulreal[i]->scheduler_name);
|
||||
--sc_update[mod_id]->n_ul;
|
||||
--slice_config[mod_id]->n_ul;
|
||||
const size_t last = sc_update[mod_id]->n_ul;
|
||||
/* see DL remarks */
|
||||
memcpy(ul[i], ul[last], sizeof(*ul[last]));
|
||||
memset(ul[last], 0, sizeof(*ul[last]));
|
||||
memcpy(ulreal[i], ulreal[last], sizeof(*ulreal[last]));
|
||||
memset(ulreal[last], 0, sizeof(*ulreal[last]));
|
||||
/* dont increase i but recheck the slice which has been copied to here */
|
||||
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config) {
|
||||
struct lfds700_misc_prng_state ls;
|
||||
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
||||
lfds700_misc_prng_init(&ls);
|
||||
enum lfds700_misc_flag overwrite_occurred_flag;
|
||||
|
||||
Protocol__FlexUeConfig *overwritten_ue_config;
|
||||
lfds700_ringbuffer_write(&ue_assoc_ringbuffer_state[mod_id],
|
||||
NULL,
|
||||
(void *) *ue_config,
|
||||
&overwrite_occurred_flag,
|
||||
NULL,
|
||||
(void **)&overwritten_ue_config,
|
||||
&ls);
|
||||
|
||||
if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) {
|
||||
free(overwritten_ue_config);
|
||||
LOG_E(FLEXRAN_AGENT, "lost UE-slice association: too many UE-slice associations at once\n");
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_agent_slice_update(mid_t mod_id)
|
||||
{
|
||||
int i;
|
||||
int changes = 0;
|
||||
void flexran_agent_slice_update(mid_t mod_id) {
|
||||
struct lfds700_misc_prng_state ls;
|
||||
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
||||
lfds700_misc_prng_init(&ls);
|
||||
|
||||
if (perform_slice_config_update_count <= 0) return;
|
||||
perform_slice_config_update_count--;
|
||||
|
||||
pthread_mutex_lock(&sc_update_mtx);
|
||||
|
||||
if (!slice_config[mod_id]) {
|
||||
/* if the configuration does not exist for agent, create from eNB structure
|
||||
* and exit */
|
||||
flexran_create_config_structures(mod_id);
|
||||
pthread_mutex_unlock(&sc_update_mtx);
|
||||
return;
|
||||
Protocol__FlexSliceConfig *sc = NULL;
|
||||
struct lfds700_ringbuffer_state *state = &slice_config_ringbuffer_state[mod_id];
|
||||
if (lfds700_ringbuffer_read(state, NULL, (void **) &sc, &ls) != 0) {
|
||||
apply_update_dl_slice_config(mod_id, sc->dl);
|
||||
apply_update_ul_slice_config(mod_id, sc->ul);
|
||||
helper_destroy_mac_slice_config(sc);
|
||||
}
|
||||
|
||||
/********* read existing config *********/
|
||||
/* simply update slice_config all the time and write new config
|
||||
* (apply_new_slice_dl_config() only updates if changes are necessary) */
|
||||
slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id);
|
||||
slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id);
|
||||
for (i = 0; i < slice_config[mod_id]->n_dl; i++) {
|
||||
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
|
||||
Protocol__FlexUeConfig *ue_config = NULL;
|
||||
state = &ue_assoc_ringbuffer_state[mod_id];
|
||||
if (lfds700_ringbuffer_read(state, NULL, (void **) &ue_config, &ls) != 0) {
|
||||
apply_ue_slice_assoc_update(mod_id, ue_config);
|
||||
free(ue_config);
|
||||
}
|
||||
for (i = 0; i < slice_config[mod_id]->n_ul; i++) {
|
||||
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
|
||||
}
|
||||
|
||||
/********* write new config *********/
|
||||
/* check for removal (sc_update[X]->dl[Y].percentage == 0)
|
||||
* and update sc_update & slice_config accordingly */
|
||||
flexran_check_and_remove_slices(mod_id);
|
||||
|
||||
/* create new DL and UL slices if necessary */
|
||||
for (i = slice_config[mod_id]->n_dl; i < sc_update[mod_id]->n_dl; i++) {
|
||||
flexran_create_dl_slice(mod_id, sc_update[mod_id]->dl[i]->id);
|
||||
}
|
||||
for (i = slice_config[mod_id]->n_ul; i < sc_update[mod_id]->n_ul; i++) {
|
||||
flexran_create_ul_slice(mod_id, sc_update[mod_id]->ul[i]->id);
|
||||
}
|
||||
slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id);
|
||||
slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id);
|
||||
changes += apply_new_slice_config(mod_id, slice_config[mod_id], sc_update[mod_id]);
|
||||
for (i = 0; i < slice_config[mod_id]->n_dl; i++) {
|
||||
changes += apply_new_slice_dl_config(mod_id,
|
||||
slice_config[mod_id]->dl[i],
|
||||
sc_update[mod_id]->dl[i]);
|
||||
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
|
||||
}
|
||||
for (i = 0; i < slice_config[mod_id]->n_ul; i++) {
|
||||
changes += apply_new_slice_ul_config(mod_id,
|
||||
slice_config[mod_id]->ul[i],
|
||||
sc_update[mod_id]->ul[i]);
|
||||
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
|
||||
}
|
||||
flexran_agent_read_slice_config(mod_id, slice_config[mod_id]);
|
||||
if (n_ue_slice_assoc_updates > 0) {
|
||||
changes += apply_ue_slice_assoc_update(mod_id);
|
||||
}
|
||||
if (changes > 0)
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] slice configuration: applied %d changes\n", mod_id, changes);
|
||||
|
||||
pthread_mutex_unlock(&sc_update_mtx);
|
||||
}
|
||||
|
||||
Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id)
|
||||
{
|
||||
if (!slice_config[mod_id]) return NULL;
|
||||
Protocol__FlexSliceConfig *config = NULL;
|
||||
|
||||
pthread_mutex_lock(&sc_update_mtx);
|
||||
config = flexran_agent_create_slice_config(slice_config[mod_id]->n_dl,
|
||||
slice_config[mod_id]->n_ul);
|
||||
if (!config) {
|
||||
pthread_mutex_unlock(&sc_update_mtx);
|
||||
return NULL;
|
||||
}
|
||||
config->has_intraslice_share_active = 1;
|
||||
config->intraslice_share_active = slice_config[mod_id]->intraslice_share_active;
|
||||
config->has_interslice_share_active = 1;
|
||||
config->interslice_share_active = slice_config[mod_id]->interslice_share_active;
|
||||
for (int i = 0; i < slice_config[mod_id]->n_dl; ++i) {
|
||||
if (!config->dl[i]) continue;
|
||||
config->dl[i]->has_id = 1;
|
||||
config->dl[i]->id = slice_config[mod_id]->dl[i]->id;
|
||||
config->dl[i]->has_label = 1;
|
||||
config->dl[i]->label = slice_config[mod_id]->dl[i]->label;
|
||||
config->dl[i]->has_percentage = 1;
|
||||
config->dl[i]->percentage = slice_config[mod_id]->dl[i]->percentage;
|
||||
config->dl[i]->has_isolation = 1;
|
||||
config->dl[i]->isolation = slice_config[mod_id]->dl[i]->isolation;
|
||||
config->dl[i]->has_priority = 1;
|
||||
config->dl[i]->priority = slice_config[mod_id]->dl[i]->priority;
|
||||
config->dl[i]->has_position_low = 1;
|
||||
config->dl[i]->position_low = slice_config[mod_id]->dl[i]->position_low;
|
||||
config->dl[i]->has_position_high = 1;
|
||||
config->dl[i]->position_high = slice_config[mod_id]->dl[i]->position_high;
|
||||
config->dl[i]->has_maxmcs = 1;
|
||||
config->dl[i]->maxmcs = slice_config[mod_id]->dl[i]->maxmcs;
|
||||
config->dl[i]->n_sorting = slice_config[mod_id]->dl[i]->n_sorting;
|
||||
config->dl[i]->sorting = calloc(config->dl[i]->n_sorting, sizeof(Protocol__FlexDlSorting));
|
||||
if (!config->dl[i]->sorting) config->dl[i]->n_sorting = 0;
|
||||
for (int j = 0; j < config->dl[i]->n_sorting; ++j)
|
||||
config->dl[i]->sorting[j] = slice_config[mod_id]->dl[i]->sorting[j];
|
||||
config->dl[i]->has_accounting = 1;
|
||||
config->dl[i]->accounting = slice_config[mod_id]->dl[i]->accounting;
|
||||
config->dl[i]->scheduler_name = strdup(slice_config[mod_id]->dl[i]->scheduler_name);
|
||||
}
|
||||
for (int i = 0; i < slice_config[mod_id]->n_ul; ++i) {
|
||||
if (!config->ul[i]) continue;
|
||||
config->ul[i]->has_id = 1;
|
||||
config->ul[i]->id = slice_config[mod_id]->ul[i]->id;
|
||||
config->ul[i]->has_label = 1;
|
||||
config->ul[i]->label = slice_config[mod_id]->ul[i]->label;
|
||||
config->ul[i]->has_percentage = 1;
|
||||
config->ul[i]->percentage = slice_config[mod_id]->ul[i]->percentage;
|
||||
config->ul[i]->has_isolation = 1;
|
||||
config->ul[i]->isolation = slice_config[mod_id]->ul[i]->isolation;
|
||||
config->ul[i]->has_priority = 1;
|
||||
config->ul[i]->priority = slice_config[mod_id]->ul[i]->priority;
|
||||
config->ul[i]->has_first_rb = 1;
|
||||
config->ul[i]->first_rb = slice_config[mod_id]->ul[i]->first_rb;
|
||||
config->ul[i]->has_maxmcs = 1;
|
||||
config->ul[i]->maxmcs = slice_config[mod_id]->ul[i]->maxmcs;
|
||||
config->ul[i]->n_sorting = slice_config[mod_id]->ul[i]->n_sorting;
|
||||
config->ul[i]->sorting = calloc(config->ul[i]->n_sorting, sizeof(Protocol__FlexUlSorting));
|
||||
if (!config->ul[i]->sorting) config->ul[i]->n_sorting = 0;
|
||||
for (int j = 0; j < config->ul[i]->n_sorting; ++j)
|
||||
config->ul[i]->sorting[j] = slice_config[mod_id]->ul[i]->sorting[j];
|
||||
config->ul[i]->has_accounting = 1;
|
||||
config->ul[i]->accounting = slice_config[mod_id]->ul[i]->accounting;
|
||||
config->ul[i]->scheduler_name = strdup(slice_config[mod_id]->ul[i]->scheduler_name);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&sc_update_mtx);
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,16 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id);
|
||||
/* Inform controller about possibility to update slice configuration */
|
||||
void flexran_agent_slice_update(mid_t mod_id);
|
||||
|
||||
/* return a pointer to the current config */
|
||||
Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id);
|
||||
/* marks slice_config so that it can be applied later. Takes ownership of the
|
||||
* FlexSliceConfig message */
|
||||
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice);
|
||||
|
||||
/* inserts a new ue_config into the structure keeping ue to slice association
|
||||
* updates and marks so it can be applied. Takes ownership of the FlexUeConfig message */
|
||||
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config);
|
||||
|
||||
/* free slice_config part of flexCellConfig, filled in
|
||||
* flexran_agent_fill_mac_cell_config() */
|
||||
void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,14 +33,6 @@
|
||||
#include "flexran_agent_mac_internal.h"
|
||||
#include "flexran_agent_mac_slice_verification.h"
|
||||
|
||||
/* from flexran_agent_mac.c */
|
||||
extern Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES];
|
||||
extern Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES];
|
||||
extern int perform_slice_config_update_count;
|
||||
extern Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES];
|
||||
extern int n_ue_slice_assoc_updates;
|
||||
extern pthread_mutex_t sc_update_mtx;
|
||||
|
||||
Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message,
|
||||
Protocol__FlexranMessage *old_message) {
|
||||
|
||||
@@ -1033,724 +1025,166 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
|
||||
|
||||
}
|
||||
|
||||
Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul)
|
||||
{
|
||||
int i;
|
||||
Protocol__FlexSliceConfig *fsc = malloc(sizeof(Protocol__FlexSliceConfig));
|
||||
if (!fsc) return NULL;
|
||||
protocol__flex_slice_config__init(fsc);
|
||||
|
||||
/* say there are n_dl slices but reserve memory for up to MAX_NUM_SLICES so
|
||||
* we don't need to reserve again later */
|
||||
fsc->n_dl = n_dl;
|
||||
fsc->dl = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexDlSlice *));
|
||||
if (!fsc->dl) fsc->n_dl = 0;
|
||||
for (i = 0; i < MAX_NUM_SLICES; i++) {
|
||||
fsc->dl[i] = malloc(sizeof(Protocol__FlexDlSlice));
|
||||
if (!fsc->dl[i]) continue;
|
||||
protocol__flex_dl_slice__init(fsc->dl[i]);
|
||||
}
|
||||
|
||||
/* as above */
|
||||
fsc->n_ul = m_ul;
|
||||
fsc->ul = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexUlSlice *));
|
||||
if (!fsc->ul) fsc->n_ul = 0;
|
||||
for (i = 0; i < MAX_NUM_SLICES; i++) {
|
||||
fsc->ul[i] = malloc(sizeof(Protocol__FlexUlSlice));
|
||||
if (!fsc->ul[i]) continue;
|
||||
protocol__flex_ul_slice__init(fsc->ul[i]);
|
||||
}
|
||||
return fsc;
|
||||
}
|
||||
|
||||
void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s)
|
||||
{
|
||||
s->intraslice_share_active = flexran_get_intraslice_sharing_active(mod_id);
|
||||
s->has_intraslice_share_active = 1;
|
||||
s->interslice_share_active = flexran_get_interslice_sharing_active(mod_id);
|
||||
s->has_interslice_share_active = 1;
|
||||
}
|
||||
|
||||
void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice)
|
||||
{
|
||||
dl_slice->id = flexran_get_dl_slice_id(mod_id, slice_idx);
|
||||
dl_slice->has_id = 1;
|
||||
/* read label from corresponding sc_update entry or give default */
|
||||
dl_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB;
|
||||
dl_slice->has_label = 1;
|
||||
for (int i = 0; i < sc_update[mod_id]->n_dl; i++) {
|
||||
if (sc_update[mod_id]->dl[i]->id == dl_slice->id
|
||||
&& sc_update[mod_id]->dl[i]->has_label) {
|
||||
dl_slice->label = sc_update[mod_id]->dl[i]->label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dl_slice->percentage = flexran_get_dl_slice_percentage(mod_id, slice_idx);
|
||||
dl_slice->has_percentage = 1;
|
||||
dl_slice->isolation = flexran_get_dl_slice_isolation(mod_id, slice_idx);
|
||||
dl_slice->has_isolation = 1;
|
||||
dl_slice->priority = flexran_get_dl_slice_priority(mod_id, slice_idx);
|
||||
dl_slice->has_priority = 1;
|
||||
dl_slice->position_low = flexran_get_dl_slice_position_low(mod_id, slice_idx);
|
||||
dl_slice->has_position_low = 1;
|
||||
dl_slice->position_high = flexran_get_dl_slice_position_high(mod_id, slice_idx);
|
||||
dl_slice->has_position_high = 1;
|
||||
dl_slice->maxmcs = flexran_get_dl_slice_maxmcs(mod_id, slice_idx);
|
||||
dl_slice->has_maxmcs = 1;
|
||||
dl_slice->n_sorting = flexran_get_dl_slice_sorting(mod_id, slice_idx, &dl_slice->sorting);
|
||||
if (dl_slice->n_sorting < 1) dl_slice->sorting = NULL;
|
||||
dl_slice->accounting = flexran_get_dl_slice_accounting_policy(mod_id, slice_idx);
|
||||
dl_slice->has_accounting = 1;
|
||||
const char *s_name = flexran_get_dl_slice_scheduler(mod_id, slice_idx);
|
||||
if (!dl_slice->scheduler_name
|
||||
|| strcmp(dl_slice->scheduler_name, s_name) != 0) {
|
||||
dl_slice->scheduler_name = realloc(dl_slice->scheduler_name, strlen(s_name) + 1);
|
||||
strcpy(dl_slice->scheduler_name, s_name);
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice)
|
||||
{
|
||||
ul_slice->id = flexran_get_ul_slice_id(mod_id, slice_idx);
|
||||
ul_slice->has_id = 1;
|
||||
/* read label from corresponding sc_update entry or give default */
|
||||
ul_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB;
|
||||
ul_slice->has_label = 1;
|
||||
for (int i = 0; i < sc_update[mod_id]->n_ul; i++) {
|
||||
if (sc_update[mod_id]->ul[i]->id == ul_slice->id
|
||||
&& sc_update[mod_id]->ul[i]->has_label) {
|
||||
ul_slice->label = sc_update[mod_id]->ul[i]->label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ul_slice->percentage = flexran_get_ul_slice_percentage(mod_id, slice_idx);
|
||||
ul_slice->has_percentage = 1;
|
||||
/*ul_slice->isolation = flexran_get_ul_slice_isolation(mod_id, slice_idx);*/
|
||||
ul_slice->has_isolation = 0;
|
||||
/*ul_slice->priority = flexran_get_ul_slice_priority(mod_id, slice_idx);*/
|
||||
ul_slice->has_priority = 0;
|
||||
ul_slice->first_rb = flexran_get_ul_slice_first_rb(mod_id, slice_idx);
|
||||
ul_slice->has_first_rb = 1;
|
||||
/*ul_slice-> = flexran_get_ul_slice_length_rb(mod_id, slice_idx);
|
||||
ul_slice->has_length_rb = 0;*/
|
||||
ul_slice->maxmcs = flexran_get_ul_slice_maxmcs(mod_id, slice_idx);
|
||||
ul_slice->has_maxmcs = 1;
|
||||
ul_slice->n_sorting = 0;
|
||||
/*if (ul_slice->sorting) {
|
||||
free(ul_slice->sorting);
|
||||
ul_slice->sorting = NULL;
|
||||
}
|
||||
ul_slice->n_sorting = flexran_get_ul_slice_sorting(mod_id, slice_idx, &ul_slice->sorting);
|
||||
if (ul_slice->n_sorting < 1) ul_slice->sorting = NULL;*/
|
||||
/*ul_slice->accounting = flexran_get_ul_slice_accounting_policy(mod_id, slice_idx);*/
|
||||
ul_slice->has_accounting = 0;
|
||||
const char *s_name = flexran_get_ul_slice_scheduler(mod_id, slice_idx);
|
||||
if (!ul_slice->scheduler_name
|
||||
|| strcmp(ul_slice->scheduler_name, s_name) != 0) {
|
||||
ul_slice->scheduler_name = realloc(ul_slice->scheduler_name, strlen(s_name) + 1);
|
||||
strcpy(ul_slice->scheduler_name, s_name);
|
||||
}
|
||||
}
|
||||
|
||||
int check_dl_sorting_update(Protocol__FlexDlSlice *old, Protocol__FlexDlSlice *new)
|
||||
{
|
||||
/* sorting_update => true when old->n_sorting == 0 or different numbers of
|
||||
* elements; otherwise will check * element-wise */
|
||||
int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting);
|
||||
for (int i = 0; i < old->n_sorting && !sorting_update; ++i) {
|
||||
sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]);
|
||||
}
|
||||
return sorting_update;
|
||||
}
|
||||
|
||||
int check_ul_sorting_update(Protocol__FlexUlSlice *old, Protocol__FlexUlSlice *new)
|
||||
{
|
||||
/* sorting_update => true when old->n_sorting == 0 or different numbers of
|
||||
* elements; otherwise will check * element-wise */
|
||||
int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting);
|
||||
for (int i = 0; i < old->n_sorting && !sorting_update; ++i) {
|
||||
sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]);
|
||||
}
|
||||
return sorting_update;
|
||||
}
|
||||
|
||||
void overwrite_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *exist, Protocol__FlexSliceConfig *update)
|
||||
{
|
||||
if (update->has_intraslice_share_active
|
||||
&& exist->intraslice_share_active != update->intraslice_share_active) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] update intraslice_share_active: %d -> %d\n",
|
||||
mod_id, exist->intraslice_share_active, update->intraslice_share_active);
|
||||
exist->intraslice_share_active = update->intraslice_share_active;
|
||||
exist->has_intraslice_share_active = 1;
|
||||
}
|
||||
if (update->has_interslice_share_active
|
||||
&& exist->interslice_share_active != update->interslice_share_active) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] update interslice_share_active: %d -> %d\n",
|
||||
mod_id, exist->interslice_share_active, update->interslice_share_active);
|
||||
exist->interslice_share_active = update->interslice_share_active;
|
||||
exist->has_interslice_share_active = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void overwrite_slice_config_dl(mid_t mod_id, Protocol__FlexDlSlice *exist, Protocol__FlexDlSlice *update)
|
||||
{
|
||||
if (update->label != exist->label) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update label: %d -> %d\n",
|
||||
mod_id, update->id, exist->label, update->label);
|
||||
exist->label = update->label;
|
||||
exist->has_label = 1;
|
||||
}
|
||||
if (update->percentage != exist->percentage) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update percentage: %d -> %d\n",
|
||||
mod_id, update->id, exist->percentage, update->percentage);
|
||||
exist->percentage = update->percentage;
|
||||
exist->has_percentage = 1;
|
||||
}
|
||||
if (update->isolation != exist->isolation) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update isolation: %d -> %d\n",
|
||||
mod_id, update->id, exist->isolation, update->isolation);
|
||||
exist->isolation = update->isolation;
|
||||
exist->has_isolation = 1;
|
||||
}
|
||||
if (update->priority != exist->priority) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update priority: %d -> %d\n",
|
||||
mod_id, update->id, exist->priority, update->priority);
|
||||
exist->priority = update->priority;
|
||||
exist->has_priority = 1;
|
||||
}
|
||||
if (update->position_low != exist->position_low) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_low: %d -> %d\n",
|
||||
mod_id, update->id, exist->position_low, update->position_low);
|
||||
exist->position_low = update->position_low;
|
||||
exist->has_position_low = 1;
|
||||
}
|
||||
if (update->position_high != exist->position_high) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_high: %d -> %d\n",
|
||||
mod_id, update->id, exist->position_high, update->position_high);
|
||||
exist->position_high = update->position_high;
|
||||
exist->has_position_high = 1;
|
||||
}
|
||||
if (update->maxmcs != exist->maxmcs) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update maxmcs: %d -> %d\n",
|
||||
mod_id, update->id, exist->maxmcs, update->maxmcs);
|
||||
exist->maxmcs = update->maxmcs;
|
||||
exist->has_maxmcs = 1;
|
||||
}
|
||||
if (check_dl_sorting_update(exist, update)) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update sorting array\n", mod_id, update->id);
|
||||
if (exist->n_sorting != update->n_sorting) {
|
||||
exist->n_sorting = update->n_sorting;
|
||||
exist->sorting = realloc(exist->sorting, exist->n_sorting * sizeof(Protocol__FlexDlSorting));
|
||||
if (!exist->sorting) exist->n_sorting = 0;
|
||||
}
|
||||
for (int i = 0; i < exist->n_sorting; i++)
|
||||
exist->sorting[i] = update->sorting[i];
|
||||
}
|
||||
if (update->accounting != exist->accounting) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update accounting: %d -> %d\n",
|
||||
mod_id, update->id, exist->accounting, update->accounting);
|
||||
exist->accounting = update->accounting;
|
||||
exist->has_accounting = 1;
|
||||
}
|
||||
if (!exist->scheduler_name
|
||||
|| strcmp(update->scheduler_name, exist->scheduler_name) != 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update scheduler: %s -> %s\n",
|
||||
mod_id, update->id, exist->scheduler_name, update->scheduler_name);
|
||||
if (exist->scheduler_name) free(exist->scheduler_name);
|
||||
exist->scheduler_name = strdup(update->scheduler_name);
|
||||
}
|
||||
}
|
||||
|
||||
void overwrite_slice_config_ul(mid_t mod_id, Protocol__FlexUlSlice *exist, Protocol__FlexUlSlice *update)
|
||||
{
|
||||
if (update->label != exist->label) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update label: %d -> %d\n",
|
||||
mod_id, update->id, exist->label, update->label);
|
||||
exist->label = update->label;
|
||||
exist->has_label = 1;
|
||||
}
|
||||
if (update->percentage != exist->percentage) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update percentage: %d -> %d\n",
|
||||
mod_id, update->id, exist->percentage, update->percentage);
|
||||
exist->percentage = update->percentage;
|
||||
exist->has_percentage = 1;
|
||||
}
|
||||
if (update->isolation != exist->isolation) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update isolation: %d -> %d\n",
|
||||
mod_id, update->id, exist->isolation, update->isolation);
|
||||
exist->isolation = update->isolation;
|
||||
exist->has_isolation = 1;
|
||||
}
|
||||
if (update->priority != exist->priority) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update priority: %d -> %d\n",
|
||||
mod_id, update->id, exist->priority, update->priority);
|
||||
exist->priority = update->priority;
|
||||
exist->has_priority = 1;
|
||||
}
|
||||
if (update->first_rb != exist->first_rb) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update first_rb: %d -> %d\n",
|
||||
mod_id, update->id, exist->first_rb, update->first_rb);
|
||||
exist->first_rb = update ->first_rb;
|
||||
exist->has_first_rb = 1;
|
||||
}
|
||||
/*if (update->lenght_rb != exist->lenght_rb) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update lenght_rb: %d -> %d\n",
|
||||
mod_id, update->id, exist->lenght_rb, update->lenght_rb);
|
||||
exist->lenght_rb = update->lenght_rb;
|
||||
}*/
|
||||
if (update->maxmcs != exist->maxmcs) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update maxmcs: %d -> %d\n",
|
||||
mod_id, update->id, exist->maxmcs, update->maxmcs);
|
||||
exist->maxmcs = update->maxmcs;
|
||||
exist->has_maxmcs = 1;
|
||||
}
|
||||
/* TODO
|
||||
int sorting_update = 0;
|
||||
int n = min(exist->n_sorting, update->n_sorting);
|
||||
int i = 0;
|
||||
while (i < n && !sorting_update) {
|
||||
sorting_update = sorting_update || (update->sorting[i] != exist->sorting[i]);
|
||||
i++;
|
||||
}
|
||||
if (sorting_update) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update sorting array\n", update->id, mod_id);
|
||||
if (exist->n_sorting != update->n_sorting)
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] only writing %d elements\n",
|
||||
mod_id, update->id, n);
|
||||
for (i = 0; i < n; i++)
|
||||
exist->sorting[i] = update->sorting[i];
|
||||
}
|
||||
*/
|
||||
if (update->accounting != exist->accounting) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update accounting: %d -> %d\n",
|
||||
mod_id, update->id, exist->accounting, update->accounting);
|
||||
exist->accounting = update->accounting;
|
||||
exist->has_accounting = 1;
|
||||
}
|
||||
if (!exist->scheduler_name
|
||||
|| strcmp(update->scheduler_name, exist->scheduler_name) != 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update scheduler: %s -> %s\n",
|
||||
mod_id, update->id, exist->scheduler_name, update->scheduler_name);
|
||||
if (exist->scheduler_name) free(exist->scheduler_name);
|
||||
exist->scheduler_name = strdup(update->scheduler_name);
|
||||
}
|
||||
}
|
||||
|
||||
void fill_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *s, Protocol__FlexDlSlice *from)
|
||||
{
|
||||
/* function fills slice with information from another slice or with default
|
||||
* values (currently slice 0) if from is NULL */
|
||||
/* TODO fill the slice depending on the chosen label */
|
||||
if (!s->has_label) {
|
||||
s->has_label = 1;
|
||||
s->label = from ? from->label : sc_update[mod_id]->dl[0]->label;
|
||||
}
|
||||
if (!s->has_percentage) {
|
||||
s->has_percentage = 1;
|
||||
s->percentage = from ? from->percentage : sc_update[mod_id]->dl[0]->percentage;
|
||||
}
|
||||
if (!s->has_isolation) {
|
||||
s->has_isolation = 1;
|
||||
s->isolation = from ? from->isolation : sc_update[mod_id]->dl[0]->isolation;
|
||||
}
|
||||
if (!s->has_priority) {
|
||||
s->has_priority = 1;
|
||||
s->priority = from ? from->priority : sc_update[mod_id]->dl[0]->priority;
|
||||
}
|
||||
if (!s->has_position_low) {
|
||||
s->has_position_low = 1;
|
||||
s->position_low = from ? from->position_low : sc_update[mod_id]->dl[0]->position_low;
|
||||
}
|
||||
if (!s->has_position_high) {
|
||||
s->has_position_high = 1;
|
||||
s->position_high = from ? from->position_high : sc_update[mod_id]->dl[0]->position_high;
|
||||
}
|
||||
if (!s->has_maxmcs) {
|
||||
s->has_maxmcs = 1;
|
||||
s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->dl[0]->maxmcs;
|
||||
}
|
||||
if (s->n_sorting == 0) {
|
||||
s->n_sorting = from ? from->n_sorting : sc_update[mod_id]->dl[0]->n_sorting;
|
||||
s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexDlSorting));
|
||||
if (!s->sorting) s->n_sorting = 0;
|
||||
for (int i = 0; i < s->n_sorting; ++i)
|
||||
s->sorting[i] = from ? from->sorting[i] : sc_update[0]->dl[0]->sorting[i];
|
||||
}
|
||||
if (!s->has_accounting) {
|
||||
s->accounting = from ? from->accounting : sc_update[mod_id]->dl[0]->accounting;
|
||||
}
|
||||
if (!s->scheduler_name) {
|
||||
s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->dl[0]->scheduler_name);
|
||||
}
|
||||
}
|
||||
|
||||
Protocol__FlexDlSlice *get_existing_dl_slice(mid_t mod_id, int id)
|
||||
{
|
||||
for (int i = 0; i < sc_update[mod_id]->n_dl; ++i) {
|
||||
if (id == sc_update[mod_id]->dl[i]->id) {
|
||||
return sc_update[mod_id]->dl[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Protocol__FlexDlSlice *create_new_dl_slice(mid_t mod_id, int id)
|
||||
{
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"[%d] Creating DL slice with ID %d, taking default values from DL slice 0\n",
|
||||
mod_id, id);
|
||||
Protocol__FlexDlSlice *to = sc_update[mod_id]->dl[sc_update[mod_id]->n_dl];
|
||||
sc_update[mod_id]->n_dl++;
|
||||
AssertFatal(sc_update[mod_id]->n_dl <= MAX_NUM_SLICES,
|
||||
"cannot create more than MAX_NUM_SLICES\n");
|
||||
to->id = id;
|
||||
return to;
|
||||
}
|
||||
|
||||
void fill_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *s, Protocol__FlexUlSlice *from)
|
||||
{
|
||||
/* function fills slice with information from another slice or with default
|
||||
* values (currently slice 0) if from is NULL */
|
||||
/* TODO fill the slice depending on the chosen label */
|
||||
if (!s->has_label) {
|
||||
s->has_label = 1;
|
||||
s->label = from ? from->label : sc_update[mod_id]->ul[0]->label;
|
||||
}
|
||||
if (!s->has_percentage) {
|
||||
s->has_percentage = 1;
|
||||
s->percentage = from ? from->percentage : sc_update[mod_id]->ul[0]->percentage;
|
||||
}
|
||||
if (!s->has_isolation) {
|
||||
s->has_isolation = 1;
|
||||
s->isolation = from ? from->isolation : sc_update[mod_id]->ul[0]->isolation;
|
||||
}
|
||||
if (!s->has_priority) {
|
||||
s->has_priority = 1;
|
||||
s->priority = from ? from->priority : sc_update[mod_id]->ul[0]->priority;
|
||||
}
|
||||
if (!s->has_first_rb) {
|
||||
s->has_first_rb = 1;
|
||||
s->first_rb = from ? from->first_rb : sc_update[mod_id]->ul[0]->first_rb;
|
||||
}
|
||||
if (!s->has_maxmcs) {
|
||||
s->has_maxmcs = 1;
|
||||
s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->ul[0]->maxmcs;
|
||||
}
|
||||
if (s->n_sorting == 0) {
|
||||
s->n_sorting = from ? from->n_sorting : sc_update[0]->ul[0]->n_sorting;
|
||||
s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexUlSorting));
|
||||
if (!s->sorting) s->n_sorting = 0;
|
||||
for (int i = 0; i < s->n_sorting; ++i)
|
||||
s->sorting[i] = from ? from->sorting[i] : sc_update[0]->ul[0]->sorting[i];
|
||||
}
|
||||
if (!s->has_accounting) {
|
||||
s->accounting = from ? from->accounting : sc_update[0]->ul[0]->accounting;
|
||||
}
|
||||
if (!s->scheduler_name) {
|
||||
s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->ul[0]->scheduler_name);
|
||||
}
|
||||
}
|
||||
|
||||
Protocol__FlexUlSlice *get_existing_ul_slice(mid_t mod_id, int id)
|
||||
{
|
||||
for (int i = 0; i < sc_update[mod_id]->n_ul; ++i) {
|
||||
if (id == sc_update[mod_id]->ul[i]->id) {
|
||||
return sc_update[mod_id]->ul[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Protocol__FlexUlSlice *create_new_ul_slice(mid_t mod_id, int id)
|
||||
{
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"[%d] Creating UL slice with ID %d, taking default values from UL slice 0\n",
|
||||
mod_id, id);
|
||||
Protocol__FlexUlSlice *to = sc_update[mod_id]->ul[sc_update[mod_id]->n_ul];
|
||||
sc_update[mod_id]->n_ul++;
|
||||
AssertFatal(sc_update[mod_id]->n_ul <= MAX_NUM_SLICES,
|
||||
"cannot create more than MAX_NUM_SLICES\n");
|
||||
to->id = id;
|
||||
return to;
|
||||
}
|
||||
|
||||
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *sup)
|
||||
{
|
||||
int verified = 1;
|
||||
if (!sc_update[mod_id]) {
|
||||
LOG_E(FLEXRAN_AGENT, "Can not update slice policy (no existing slice profile)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&sc_update_mtx);
|
||||
/* no need for tests in the current state as there are only two protobuf
|
||||
* bools for intra-/interslice sharing. The function applies new values if
|
||||
* applicable */
|
||||
overwrite_slice_config(mod_id, sc_update[mod_id], sup);
|
||||
|
||||
if (sup->n_dl == 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] no DL slice configuration in flex_slice_config message\n", mod_id);
|
||||
void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) {
|
||||
if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET
|
||||
&& !s->label && !s->scheduler) {
|
||||
LOG_I(FLEXRAN_AGENT, "remove DL slice ID %d\n", s->id);
|
||||
const int rc = flexran_remove_dl_slice(mod_id, s);
|
||||
if (!rc)
|
||||
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
|
||||
} else {
|
||||
/* verify slice parameters */
|
||||
for (int i = 0; i < sup->n_dl; i++) {
|
||||
if (!sup->dl[i]->has_id) {
|
||||
verified = 0;
|
||||
break;
|
||||
}
|
||||
Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id);
|
||||
/* fill up so that the slice is complete. This way, we don't need to
|
||||
* worry about it later */
|
||||
fill_dl_slice(mod_id, sup->dl[i], dls);
|
||||
verified = verified && flexran_verify_dl_slice(mod_id, sup->dl[i]);
|
||||
if (!verified) break;
|
||||
}
|
||||
|
||||
/* verify group-based parameters (e.g. sum percentage should not exceed
|
||||
* 100%). Can be used to perform admission control */
|
||||
verified = verified && flexran_verify_group_dl_slices(mod_id,
|
||||
sc_update[mod_id]->dl, sc_update[mod_id]->n_dl, sup->dl, sup->n_dl);
|
||||
|
||||
if (verified) {
|
||||
for (int i = 0; i < sup->n_dl; i++) {
|
||||
/* if all verifications were successful, get existing slice for ID or
|
||||
* create new one and overwrite with the update */
|
||||
Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id);
|
||||
if (!dls) dls = create_new_dl_slice(mod_id, sup->dl[i]->id);
|
||||
overwrite_slice_config_dl(mod_id, dls, sup->dl[i]);
|
||||
}
|
||||
} else {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] DL slice verification failed, refusing application\n", mod_id);
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "updating DL slice ID %d\n", s->id);
|
||||
const int rc = flexran_create_dl_slice(mod_id, s);
|
||||
if (rc < 0)
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"error while update slice ID %d: flexran_create_dl_slice() -> %d\n",
|
||||
s->id, rc);
|
||||
}
|
||||
}
|
||||
|
||||
verified = 1;
|
||||
if (sup->n_ul == 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] no UL slice configuration in flex_slice_config message\n", mod_id);
|
||||
void update_or_remove_ul(mid_t mod_id, Protocol__FlexSlice *s) {
|
||||
if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET
|
||||
&& !s->label && !s->scheduler) {
|
||||
LOG_I(FLEXRAN_AGENT, "remove UL slice ID %d\n", s->id);
|
||||
const int rc = flexran_remove_ul_slice(mod_id, s);
|
||||
if (!rc)
|
||||
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
|
||||
} else {
|
||||
/* verify slice parameters */
|
||||
for (int i = 0; i < sup->n_ul; i++) {
|
||||
if (!sup->ul[i]->has_id) {
|
||||
verified = 0;
|
||||
break;
|
||||
}
|
||||
Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id);
|
||||
/* fill up so that the slice is complete. This way, we don't need to
|
||||
* worry about it later */
|
||||
fill_ul_slice(mod_id, sup->ul[i], uls);
|
||||
verified = verified && flexran_verify_ul_slice(mod_id, sup->ul[i]);
|
||||
if (!verified) break;
|
||||
}
|
||||
|
||||
/* verify group-based parameters (e.g. sum percentage should not exceed
|
||||
* 100%). Can be used to perform admission control */
|
||||
verified = verified && flexran_verify_group_ul_slices(mod_id,
|
||||
sc_update[mod_id]->ul, sc_update[mod_id]->n_ul, sup->ul, sup->n_ul);
|
||||
|
||||
if (verified) {
|
||||
for (int i = 0; i < sup->n_ul; i++) {
|
||||
/* if all verifications were successful, get existing slice for ID or
|
||||
* create new one and overwrite with the update */
|
||||
Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id);
|
||||
if (!uls) uls = create_new_ul_slice(mod_id, sup->ul[i]->id);
|
||||
overwrite_slice_config_ul(mod_id, uls, sup->ul[i]);
|
||||
}
|
||||
} else {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] UL slice verification failed, refusing application\n", mod_id);
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "updating UL slice ID %d\n", s->id);
|
||||
const int rc = flexran_create_ul_slice(mod_id, s);
|
||||
if (rc < 0)
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"error while updating slice ID %d: flexran_create_ul_slice() -> %d)\n",
|
||||
s->id, rc);
|
||||
}
|
||||
pthread_mutex_unlock(&sc_update_mtx);
|
||||
|
||||
perform_slice_config_update_count = 1;
|
||||
}
|
||||
|
||||
int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news)
|
||||
{
|
||||
/* not setting the old configuration is intentional, as it will be picked up
|
||||
* later when reading the configuration. There is thus a direct feedback
|
||||
* whether it has been set. */
|
||||
int changes = 0;
|
||||
if (olds->intraslice_share_active != news->intraslice_share_active) {
|
||||
flexran_set_intraslice_sharing_active(mod_id, news->intraslice_share_active);
|
||||
changes++;
|
||||
}
|
||||
if (olds->interslice_share_active != news->interslice_share_active) {
|
||||
flexran_set_interslice_sharing_active(mod_id, news->interslice_share_active);
|
||||
changes++;
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc)
|
||||
{
|
||||
/* not setting the old configuration is intentional, as it will be picked up
|
||||
* later when reading the configuration. There is thus a direct feedback
|
||||
* whether it has been set. */
|
||||
int changes = 0;
|
||||
int slice_idx = flexran_find_dl_slice(mod_id, newc->id);
|
||||
if (slice_idx < 0) {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id);
|
||||
return 0;
|
||||
}
|
||||
if (oldc->percentage != newc->percentage) {
|
||||
flexran_set_dl_slice_percentage(mod_id, slice_idx, newc->percentage);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->isolation != newc->isolation) {
|
||||
flexran_set_dl_slice_isolation(mod_id, slice_idx, newc->isolation);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->priority != newc->priority) {
|
||||
flexran_set_dl_slice_priority(mod_id, slice_idx, newc->priority);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->position_low != newc->position_low) {
|
||||
flexran_set_dl_slice_position_low(mod_id, slice_idx, newc->position_low);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->position_high != newc->position_high) {
|
||||
flexran_set_dl_slice_position_high(mod_id, slice_idx, newc->position_high);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->maxmcs != newc->maxmcs) {
|
||||
flexran_set_dl_slice_maxmcs(mod_id, slice_idx, newc->maxmcs);
|
||||
changes++;
|
||||
}
|
||||
if (check_dl_sorting_update(oldc, newc)) {
|
||||
flexran_set_dl_slice_sorting(mod_id, slice_idx, newc->sorting, newc->n_sorting);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->accounting != newc->accounting) {
|
||||
flexran_set_dl_slice_accounting_policy(mod_id, slice_idx, newc->accounting);
|
||||
changes++;
|
||||
}
|
||||
if (!oldc->scheduler_name
|
||||
|| strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) {
|
||||
int ret = flexran_set_dl_slice_scheduler(mod_id, slice_idx, newc->scheduler_name);
|
||||
AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n",
|
||||
newc->id, slice_idx);
|
||||
changes++;
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc)
|
||||
{
|
||||
/* not setting the old configuration is intentional, as it will be picked up
|
||||
* later when reading the configuration. There is thus a direct feedback
|
||||
* whether it has been set. */
|
||||
int changes = 0;
|
||||
int slice_idx = flexran_find_ul_slice(mod_id, newc->id);
|
||||
if (slice_idx < 0) {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id);
|
||||
return 0;
|
||||
}
|
||||
if (oldc->percentage != newc->percentage) {
|
||||
flexran_set_ul_slice_percentage(mod_id, slice_idx, newc->percentage);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->isolation != newc->isolation) {
|
||||
/*flexran_set_ul_slice_isolation(mod_id, slice_idx, newc->isolation);
|
||||
*changes++;*/
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting isolation is not supported\n",
|
||||
mod_id, newc->id);
|
||||
}
|
||||
if (oldc->priority != newc->priority) {
|
||||
/*flexran_set_ul_slice_priority(mod_id, slice_idx, newc->priority);
|
||||
*changes++;*/
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the priority is not supported\n",
|
||||
mod_id, newc->id);
|
||||
}
|
||||
if (oldc->first_rb != newc->first_rb) {
|
||||
flexran_set_ul_slice_first_rb(mod_id, slice_idx, newc->first_rb);
|
||||
changes++;
|
||||
}
|
||||
/*if (oldc->length_rb != newc->length_rb) {
|
||||
flexran_set_ul_slice_length_rb(mod_id, slice_idx, newc->length_rb);
|
||||
changes++;
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting length_rb is not supported\n",
|
||||
mod_id, newc->id);
|
||||
}*/
|
||||
if (oldc->maxmcs != newc->maxmcs) {
|
||||
flexran_set_ul_slice_maxmcs(mod_id, slice_idx, newc->maxmcs);
|
||||
changes++;
|
||||
}
|
||||
/*if (check_ul_sorting_update(oldc, newc)) {
|
||||
flexran_set_ul_slice_sorting(mod_id, slice_idx, newc->sorting, n);
|
||||
changes++;
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the sorting is not supported\n",
|
||||
mod_id, newc->id);
|
||||
}*/
|
||||
if (oldc->accounting != newc->accounting) {
|
||||
/*flexran_set_ul_slice_accounting_policy(mod_id, slice_idx, newc->accounting);
|
||||
*changes++;*/
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the accounting is not supported\n",
|
||||
mod_id, newc->id);
|
||||
}
|
||||
if (!oldc->scheduler_name
|
||||
|| strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) {
|
||||
int ret = flexran_set_ul_slice_scheduler(mod_id, slice_idx, newc->scheduler_name);
|
||||
AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n",
|
||||
newc->id, slice_idx);
|
||||
changes++;
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config)
|
||||
{
|
||||
if (n_ue_slice_assoc_updates == MAX_NUM_SLICES) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"[%d] can not handle flex_ue_config message, buffer is full; try again later\n",
|
||||
mod_id);
|
||||
void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *dl) {
|
||||
if (!dl)
|
||||
return;
|
||||
|
||||
Protocol__FlexSliceAlgorithm dl_algo = flexran_get_dl_slice_algo(mod_id);
|
||||
if (dl->has_algorithm && dl_algo != dl->algorithm) {
|
||||
LOG_I(FLEXRAN_AGENT, "loading new DL slice algorithm %d\n", dl->algorithm);
|
||||
dl_algo = dl->algorithm;
|
||||
flexran_set_dl_slice_algo(mod_id, dl_algo);
|
||||
}
|
||||
|
||||
/* first update existing slices, then create new. Thus, we go through the
|
||||
* list twice. First round, if a slice exists, handle and mark as such. Then,
|
||||
* apply all others in the second round */
|
||||
if (dl->n_slices > 0) {
|
||||
if (dl_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n");
|
||||
return;
|
||||
}
|
||||
int handled_dl[dl->n_slices];
|
||||
for (int i = 0; i < dl->n_slices; ++i) {
|
||||
if (flexran_find_dl_slice(mod_id, dl->slices[i]->id) < 0) {
|
||||
handled_dl[i] = 0;
|
||||
continue;
|
||||
}
|
||||
update_or_remove_dl(mod_id, dl->slices[i]);
|
||||
handled_dl[i] = 1;
|
||||
}
|
||||
for (int i = 0; i < dl->n_slices; ++i) {
|
||||
if (handled_dl[i])
|
||||
continue;
|
||||
update_or_remove_dl(mod_id, dl->slices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (dl->scheduler) {
|
||||
if (dl_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n");
|
||||
return;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "loading DL new scheduling algorithm '%s'\n", dl->scheduler);
|
||||
const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler);
|
||||
if (rc < 0) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"error while updating scheduling algorithm: "
|
||||
"flexran_update_dl_sched_algo() -> %d)\n",
|
||||
rc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *ul) {
|
||||
if (!ul)
|
||||
return;
|
||||
|
||||
Protocol__FlexSliceAlgorithm ul_algo = flexran_get_ul_slice_algo(mod_id);
|
||||
if (ul->has_algorithm && ul_algo != ul->algorithm) {
|
||||
LOG_I(FLEXRAN_AGENT, "loading new UL slice algorithm %d\n", ul->algorithm);
|
||||
ul_algo = ul->algorithm;
|
||||
flexran_set_ul_slice_algo(mod_id, ul_algo);
|
||||
}
|
||||
if (ul->n_slices > 0) {
|
||||
if (ul_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n");
|
||||
return;
|
||||
}
|
||||
int handled_ul[ul->n_slices];
|
||||
for (int i = 0; i < ul->n_slices; ++i) {
|
||||
if (flexran_find_ul_slice(mod_id, ul->slices[i]->id) < 0) {
|
||||
handled_ul[i] = 0;
|
||||
continue;
|
||||
}
|
||||
update_or_remove_ul(mod_id, ul->slices[i]);
|
||||
handled_ul[i] = 1;
|
||||
}
|
||||
for (int i = 0; i < ul->n_slices; ++i) {
|
||||
if (handled_ul[i])
|
||||
continue;
|
||||
update_or_remove_ul(mod_id, ul->slices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ul->scheduler) {
|
||||
if (ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n");
|
||||
return;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "loading new UL scheduling algorithm '%s'\n", ul->scheduler);
|
||||
const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler);
|
||||
if (rc < 0) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"error while updating scheduling algorithm: "
|
||||
"flexran_update_dl_sched_algo() -> %d)\n",
|
||||
rc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config)
|
||||
{
|
||||
if (!ue_config->has_rnti) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"[%d] cannot update UE to slice association, no RNTI in flex_ue_config message\n",
|
||||
mod_id);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (ue_config->has_dl_slice_id)
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to DL slice ID %d\n",
|
||||
mod_id, ue_config->rnti, ue_config->dl_slice_id);
|
||||
if (ue_config->has_ul_slice_id)
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to UL slice ID %d\n",
|
||||
mod_id, ue_config->rnti, ue_config->ul_slice_id);
|
||||
ue_slice_assoc_update[n_ue_slice_assoc_updates++] = ue_config;
|
||||
perform_slice_config_update_count = 2;
|
||||
}
|
||||
|
||||
int apply_ue_slice_assoc_update(mid_t mod_id)
|
||||
{
|
||||
int i;
|
||||
int changes = 0;
|
||||
for (i = 0; i < n_ue_slice_assoc_updates; i++) {
|
||||
int ue_id = find_UE_id(mod_id, ue_slice_assoc_update[i]->rnti);
|
||||
if (ue_id < 0 || ue_id > MAX_MOBILES_PER_ENB){
|
||||
LOG_E(FLEXRAN_AGENT,"UE_id %d is wrong!!\n",ue_id);
|
||||
continue;
|
||||
}
|
||||
if (ue_slice_assoc_update[i]->has_dl_slice_id) {
|
||||
int slice_idx = flexran_find_dl_slice(mod_id, ue_slice_assoc_update[i]->dl_slice_id);
|
||||
if (flexran_dl_slice_exists(mod_id, slice_idx)) {
|
||||
flexran_set_ue_dl_slice_idx(mod_id, ue_id, slice_idx);
|
||||
changes++;
|
||||
} else {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] DL slice %d does not exist, refusing change\n",
|
||||
mod_id, ue_slice_assoc_update[i]->dl_slice_id);
|
||||
}
|
||||
}
|
||||
if (ue_slice_assoc_update[i]->has_ul_slice_id) {
|
||||
int slice_idx = flexran_find_ul_slice(mod_id, ue_slice_assoc_update[i]->ul_slice_id);
|
||||
if (flexran_ul_slice_exists(mod_id, slice_idx)) {
|
||||
flexran_set_ue_ul_slice_idx(mod_id, ue_id, slice_idx);
|
||||
changes++;
|
||||
} else {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] UL slice %d does not exist, refusing change\n",
|
||||
mod_id, ue_slice_assoc_update[i]->ul_slice_id);
|
||||
}
|
||||
int UE_id = flexran_get_mac_ue_id_rnti(mod_id, ue_config->rnti);
|
||||
if (ue_config->has_dl_slice_id) {
|
||||
if (flexran_get_dl_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "no DL slice algorithm loaded\n");
|
||||
} else {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to DL slice ID %d\n",
|
||||
mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->dl_slice_id);
|
||||
flexran_set_ue_dl_slice_id(mod_id, UE_id, ue_config->dl_slice_id);
|
||||
}
|
||||
}
|
||||
n_ue_slice_assoc_updates = 0;
|
||||
return changes;
|
||||
if (ue_config->has_ul_slice_id) {
|
||||
if (flexran_get_ul_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "no UL slice algorithm loaded\n");
|
||||
} else {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to UL slice ID %d\n",
|
||||
mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->ul_slice_id);
|
||||
flexran_set_ue_ul_slice_id(mod_id, UE_id, ue_config->ul_slice_id);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -103,43 +103,11 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name);
|
||||
|
||||
/*** Functions for handling a slice config ***/
|
||||
|
||||
/* allocate memory for a Protocol__FlexSliceConfig structure with n_dl DL slice
|
||||
* configs and m_ul UL slice configs */
|
||||
Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul);
|
||||
|
||||
/* read the general slice parameters via RAN into the given
|
||||
* Protocol__FlexSliceConfig struct */
|
||||
void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s);
|
||||
|
||||
/* read the DL slice config via the RAN into a given Protocol__FlexDlSlice
|
||||
* struct */
|
||||
void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice);
|
||||
|
||||
/* read the UL slice config via the RAN into a given Protocol__FlexUlSlice
|
||||
* struct */
|
||||
void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice);
|
||||
|
||||
/* reads content of slice over the sc_update structure, so that it can be
|
||||
* applied later by performing a diff between slice_config and sc_update */
|
||||
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *slice);
|
||||
|
||||
/* apply generic slice parameters (e.g. intra-/interslice sharing activated or
|
||||
* not) if there are changes. Returns the number of changed parameters. */
|
||||
int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news);
|
||||
|
||||
/* apply new configuration of slice in DL if there are changes between the
|
||||
* parameters. Returns the number of changed parameters. */
|
||||
int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc);
|
||||
|
||||
/* apply new configuration of slice in UL if there are changes between the
|
||||
* parameters. Returns the number of changed parameters. */
|
||||
int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc);
|
||||
|
||||
/* inserts a new ue_config into the structure keeping ue to slice association
|
||||
* updates and marks so it can be applied */
|
||||
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config);
|
||||
/* Prepare the application of a slicing config */
|
||||
void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *slice);
|
||||
void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *slice);
|
||||
|
||||
/* apply a new association between a UE and a slice (both DL and UL) */
|
||||
int apply_ue_slice_assoc_update(mid_t mod_id);
|
||||
int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config);
|
||||
|
||||
#endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/
|
||||
|
||||
@@ -28,346 +28,3 @@
|
||||
|
||||
|
||||
#include "flexran_agent_mac_slice_verification.h"
|
||||
|
||||
/* overlap check for UL slices, helper type */
|
||||
struct sregion_s {
|
||||
int start;
|
||||
int length;
|
||||
};
|
||||
|
||||
/* forward declaration of locally-used verification functions */
|
||||
int flexran_dl_slice_verify_pct(int pct);
|
||||
int flexran_dl_slice_verify_priority(int prio);
|
||||
int flexran_dl_slice_verify_position(int pos_low, int pos_high);
|
||||
int flexran_dl_slice_verify_maxmcs(int maxmcs);
|
||||
int flexran_ul_slice_verify_pct(int pct);
|
||||
int flexran_ul_slice_verify_priority(int prio);
|
||||
int flexran_ul_slice_verify_first_rb(int first_rb);
|
||||
int flexran_ul_slice_verify_maxmcs(int maxmcs);
|
||||
int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n);
|
||||
|
||||
int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls)
|
||||
{
|
||||
/* check mandatory parameters */
|
||||
if (!dls->has_id) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] Incoming DL slice configuration has no ID\n", mod_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* verify parameters individualy */
|
||||
/* label is enum */
|
||||
if (!flexran_dl_slice_verify_pct(dls->percentage)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice percentage (%d)\n",
|
||||
mod_id, dls->id, dls->percentage);
|
||||
return 0;
|
||||
}
|
||||
/* isolation is a protobuf bool */
|
||||
if (!flexran_dl_slice_verify_priority(dls->priority)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice priority (%d)\n",
|
||||
mod_id, dls->id, dls->priority);
|
||||
return 0;
|
||||
}
|
||||
if (!flexran_dl_slice_verify_position(dls->position_low, dls->position_high)) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"[%d][DL slice %d] illegal DL slice position low (%d) and/or high (%d)\n",
|
||||
mod_id, dls->id, dls->position_low, dls->position_high);
|
||||
return 0;
|
||||
}
|
||||
if (!flexran_dl_slice_verify_maxmcs(dls->maxmcs)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice max mcs %d\n",
|
||||
mod_id, dls->id, dls->maxmcs);
|
||||
return 0;
|
||||
}
|
||||
if (dls->n_sorting == 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting in DL slice\n",
|
||||
mod_id, dls->id);
|
||||
return 0;
|
||||
}
|
||||
if (!dls->sorting) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting found in DL slice\n",
|
||||
mod_id, dls->id);
|
||||
return 0;
|
||||
}
|
||||
/* sorting is an enum */
|
||||
/* accounting is an enum */
|
||||
if (!dls->scheduler_name) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no scheduler name found\n",
|
||||
mod_id, dls->id);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(dls->scheduler_name, "schedule_ue_spec") != 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] setting the scheduler to something "
|
||||
"different than schedule_ue_spec is currently not allowed\n",
|
||||
mod_id, dls->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing,
|
||||
int n_ex, Protocol__FlexDlSlice **update, int n_up)
|
||||
{
|
||||
int i, j, n;
|
||||
int pct, pct_orig;
|
||||
/* for every update, array points to existing slice, or NULL if update
|
||||
* creates new slice */
|
||||
Protocol__FlexDlSlice *s[n_up];
|
||||
for (i = 0; i < n_up; i++) {
|
||||
s[i] = NULL;
|
||||
for (j = 0; j < n_ex; j++) {
|
||||
if (existing[j]->id == update[i]->id)
|
||||
s[i] = existing[j];
|
||||
}
|
||||
}
|
||||
|
||||
/* check that number of created and number of added slices in total matches
|
||||
* [1,10] */
|
||||
n = n_ex;
|
||||
for (i = 0; i < n_up; i++) {
|
||||
/* new slice */
|
||||
if (!s[i]) n += 1;
|
||||
/* slice will be deleted */
|
||||
else if (s[i]->percentage == 0) n -= 1;
|
||||
/* else "only" an update */
|
||||
}
|
||||
|
||||
if (n < 1 || n > MAX_NUM_SLICES) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting DL slices (%d -> %d)\n",
|
||||
mod_id, n_ex, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check that the sum of all slices percentages (including removed/added
|
||||
* slices) matches [1,100] */
|
||||
pct = 0;
|
||||
for (i = 0; i < n_ex; i++) {
|
||||
pct += existing[i]->percentage;
|
||||
}
|
||||
pct_orig = pct;
|
||||
for (i = 0; i < n_up; i++) {
|
||||
/* if there is an existing slice, subtract its percentage and add the
|
||||
* update's percentage */
|
||||
if (s[i])
|
||||
pct -= s[i]->percentage;
|
||||
pct += update[i]->percentage;
|
||||
}
|
||||
if (pct < 1 || pct > 100) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"[%d] invalid total RB share for DL slices (%d%% -> %d%%)\n",
|
||||
mod_id, pct_orig, pct);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls)
|
||||
{
|
||||
/* check mandatory parameters */
|
||||
if (!uls->has_id) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] Incoming UL slice configuration has no ID\n", mod_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* verify parameters individually */
|
||||
/* label is enum */
|
||||
if (!flexran_ul_slice_verify_pct(uls->percentage)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n",
|
||||
mod_id, uls->id, uls->percentage);
|
||||
return 0;
|
||||
}
|
||||
/* isolation is a protobuf bool */
|
||||
if (!flexran_ul_slice_verify_priority(uls->priority)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n",
|
||||
mod_id, uls->id, uls->priority);
|
||||
return 0;
|
||||
}
|
||||
if (!flexran_ul_slice_verify_first_rb(uls->first_rb)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice first RB (%d)\n",
|
||||
mod_id, uls->id, uls->first_rb);
|
||||
return 0;
|
||||
}
|
||||
if (!flexran_ul_slice_verify_maxmcs(uls->maxmcs)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice max mcs (%d)\n",
|
||||
mod_id, uls->id, uls->maxmcs);
|
||||
return 0;
|
||||
}
|
||||
/* TODO
|
||||
if (uls->n_sorting == 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting in UL slice\n",
|
||||
mod_id, uls->id);
|
||||
return 0;
|
||||
}
|
||||
if (!uls->sorting) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting found in UL slice\n",
|
||||
mod_id, uls->id);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
/* sorting is an enum */
|
||||
/* accounting is an enum */
|
||||
if (!uls->scheduler_name) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no scheduler name found\n",
|
||||
mod_id, uls->id);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(uls->scheduler_name, "schedule_ulsch_rnti") != 0) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] setting the scheduler to something "
|
||||
"different than schedule_ulsch_rnti is currently not allowed\n",
|
||||
mod_id, uls->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing,
|
||||
int n_ex, Protocol__FlexUlSlice **update, int n_up)
|
||||
{
|
||||
int i, j, n;
|
||||
int pct, pct_orig;
|
||||
/* for every update, array "s" points to existing slice, or NULL if update
|
||||
* creates new slice; array "offs" gives the offset of this slice */
|
||||
Protocol__FlexUlSlice *s[n_up];
|
||||
int offs[n_up];
|
||||
for (i = 0; i < n_up; i++) {
|
||||
s[i] = NULL;
|
||||
offs[i] = 0;
|
||||
for (j = 0; j < n_ex; j++) {
|
||||
if (existing[j]->id == update[i]->id) {
|
||||
s[i] = existing[j];
|
||||
offs[i] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check that number of created and number of added slices in total matches
|
||||
* [1,10] */
|
||||
n = n_ex;
|
||||
for (i = 0; i < n_up; i++) {
|
||||
/* new slice */
|
||||
if (!s[i]) n += 1;
|
||||
/* slice will be deleted */
|
||||
else if (s[i]->percentage == 0) n -= 1;
|
||||
/* else "only" an update */
|
||||
}
|
||||
|
||||
if (n < 1 || n > MAX_NUM_SLICES) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting UL slices (%d -> %d)\n",
|
||||
mod_id, n_ex, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check that the sum of all slices percentages (including removed/added
|
||||
* slices) matches [1,100] */
|
||||
pct = 0;
|
||||
for (i = 0; i < n_ex; i++) {
|
||||
pct += existing[i]->percentage;
|
||||
}
|
||||
pct_orig = pct;
|
||||
for (i = 0; i < n_up; i++) {
|
||||
/* if there is an existing slice, subtract its percentage and add the
|
||||
* update's percentage */
|
||||
if (s[i])
|
||||
pct -= s[i]->percentage;
|
||||
pct += update[i]->percentage;
|
||||
}
|
||||
if (pct < 1 || pct > 100) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] invalid total RB share (%d%% -> %d%%)\n",
|
||||
mod_id, pct_orig, pct);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check that there is no overlap in slices resulting as the combination of
|
||||
* first_rb and percentage */
|
||||
struct sregion_s sregion[n];
|
||||
const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */
|
||||
int k = n_ex;
|
||||
for (i = 0; i < n_ex; i++) {
|
||||
sregion[i].start = existing[i]->first_rb;
|
||||
sregion[i].length = existing[i]->percentage * N_RB / 100;
|
||||
}
|
||||
for (i = 0; i < n_up; i++) {
|
||||
ptrdiff_t d = s[i] ? offs[i] : k++;
|
||||
AssertFatal(d >= 0 && d < k, "illegal pointer offset (%ld, k=%d)\n", d, k);
|
||||
sregion[d].start = update[i]->first_rb;
|
||||
sregion[d].length = update[i]->percentage * N_RB / 100;
|
||||
}
|
||||
AssertFatal(k == n, "illegal number of slices while calculating overlap\n");
|
||||
if (!check_ul_slice_overlap(mod_id, sregion, k)) {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] UL slices are overlapping\n", mod_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flexran_dl_slice_verify_pct(int pct)
|
||||
{
|
||||
return pct >= 0 && pct <= 100;
|
||||
}
|
||||
|
||||
int flexran_dl_slice_verify_priority(int prio)
|
||||
{
|
||||
return prio >= 0;
|
||||
}
|
||||
|
||||
int flexran_dl_slice_verify_position(int pos_low, int pos_high)
|
||||
{
|
||||
return pos_low < pos_high && pos_low >= 0 && pos_high <= N_RBG_MAX;
|
||||
}
|
||||
|
||||
int flexran_dl_slice_verify_maxmcs(int maxmcs)
|
||||
{
|
||||
return maxmcs >= 0 && maxmcs <= 28;
|
||||
}
|
||||
|
||||
int flexran_ul_slice_verify_pct(int pct)
|
||||
{
|
||||
return pct >= 0 && pct <= 100;
|
||||
}
|
||||
|
||||
int flexran_ul_slice_verify_priority(int prio)
|
||||
{
|
||||
return prio >= 0;
|
||||
}
|
||||
|
||||
int flexran_ul_slice_verify_first_rb(int first_rb)
|
||||
{
|
||||
return first_rb >= 0 && first_rb < 100;
|
||||
}
|
||||
|
||||
int flexran_ul_slice_verify_maxmcs(int maxmcs)
|
||||
{
|
||||
return maxmcs >= 0 && maxmcs <= 20;
|
||||
}
|
||||
|
||||
int sregion_compare(const void *_a, const void *_b)
|
||||
{
|
||||
const struct sregion_s *a = (const struct sregion_s *)_a;
|
||||
const struct sregion_s *b = (const struct sregion_s *)_b;
|
||||
const int res = a->start - b->start;
|
||||
if (res < 0) return -1;
|
||||
else if (res == 0) return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n)
|
||||
{
|
||||
int i;
|
||||
int overlap, op, u;
|
||||
const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */
|
||||
qsort(sr, n, sizeof(sr[0]), sregion_compare);
|
||||
for (i = 0; i < n; i++) {
|
||||
u = i == n-1 ? N_RB : sr[i+1].start;
|
||||
AssertFatal(sr[i].start <= u, "unsorted slice list\n");
|
||||
overlap = sr[i].start + sr[i].length - u;
|
||||
if (overlap <= 0) continue;
|
||||
op = overlap * 100 / sr[i].length;
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] slice overlap of %d%% detected\n", mod_id, op);
|
||||
if (op >= 10) /* more than 10% overlap -> refuse */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -29,9 +29,3 @@
|
||||
#include "flexran_agent_common_internal.h"
|
||||
#include "flexran_agent_mac_internal.h"
|
||||
|
||||
int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls);
|
||||
int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing,
|
||||
int n_ex, Protocol__FlexDlSlice **update, int n_up);
|
||||
int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls);
|
||||
int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing,
|
||||
int n_ex, Protocol__FlexUlSlice **update, int n_up);
|
||||
|
||||
@@ -125,6 +125,63 @@ void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply) {
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_agent_handle_mme_update(mid_t mod_id,
|
||||
size_t n_mme,
|
||||
Protocol__FlexS1apMme **mme) {
|
||||
if (n_mme == 0 || n_mme > 1) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot handle %lu MMEs yet\n", n_mme);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mme[0]->s1_ip) {
|
||||
LOG_E(FLEXRAN_AGENT, "no S1 IP present, cannot handle request\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mme[0]->has_state
|
||||
&& mme[0]->state == PROTOCOL__FLEX_MME_STATE__FLMMES_DISCONNECTED) {
|
||||
int rc = flexran_remove_s1ap_mme(mod_id, 1, &mme[0]->s1_ip);
|
||||
if (rc == 0)
|
||||
LOG_I(FLEXRAN_AGENT, "remove MME at IP %s\n", mme[0]->s1_ip);
|
||||
else
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"could not remove MME: flexran_remove_s1ap_mme() returned %d\n",
|
||||
rc);
|
||||
} else {
|
||||
int rc = flexran_add_s1ap_mme(mod_id, 1, &mme[0]->s1_ip);
|
||||
if (rc == 0)
|
||||
LOG_I(FLEXRAN_AGENT, "add MME at IP %s\n", mme[0]->s1_ip);
|
||||
else
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"could not add MME: flexran_add_s1ap_mme() returned %d\n",
|
||||
rc);
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_agent_handle_plmn_update(mid_t mod_id,
|
||||
int CC_id,
|
||||
size_t n_plmn,
|
||||
Protocol__FlexPlmn **plmn_id) {
|
||||
if (n_plmn < 1 || n_plmn > 6) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot handle %lu PLMNs\n", n_plmn);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We assume the controller has checked all the parameters within each
|
||||
* plmn_id */
|
||||
int rc = flexran_set_new_plmn_id(mod_id, CC_id, n_plmn, plmn_id);
|
||||
if (rc == 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "set %lu new PLMNs:\n", n_plmn);
|
||||
for (int i = 0; i < (int)n_plmn; ++i)
|
||||
LOG_I(FLEXRAN_AGENT, " MCC %d MNC %d MNC length %d\n",
|
||||
plmn_id[i]->mcc, plmn_id[i]->mnc, plmn_id[0]->mnc_length);
|
||||
} else {
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"could not set new PLMN configuration: flexran_set_new_plmn_id() returned %d\n",
|
||||
rc);
|
||||
}
|
||||
}
|
||||
|
||||
int flexran_agent_register_s1ap_xface(mid_t mod_id) {
|
||||
if (agent_s1ap_xface[mod_id]) {
|
||||
LOG_E(FLEXRAN_AGENT, "S1AP agent CM for eNB %d is already registered\n", mod_id);
|
||||
|
||||
@@ -60,6 +60,17 @@ int flexran_agent_s1ap_stats_reply(mid_t mod_id,
|
||||
/* Free allocated S1AP stats message */
|
||||
void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply);
|
||||
|
||||
/* Add or remove MME updates */
|
||||
void flexran_agent_handle_mme_update(mid_t mod_id,
|
||||
size_t n_mme,
|
||||
Protocol__FlexS1apMme **mme);
|
||||
|
||||
/* Set a new PLMN configuration */
|
||||
void flexran_agent_handle_plmn_update(mid_t mod_id,
|
||||
int CC_id,
|
||||
size_t n_plmn,
|
||||
Protocol__FlexPlmn **plmn_id);
|
||||
|
||||
/* Register technology specific interface callbacks */
|
||||
int flexran_agent_register_s1ap_xface(mid_t mod_id);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#define CONFIG_STRING_MACRLC_SCHED_MODE "scheduler_mode"
|
||||
#define CONFIG_MACRLC_PUSCH10xSNR "puSch10xSnr"
|
||||
#define CONFIG_MACRLC_PUCCH10xSNR "puCch10xSnr"
|
||||
#define CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO "default_sched_dl_algo"
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* MacRLC configuration parameters */
|
||||
@@ -84,6 +85,7 @@
|
||||
{CONFIG_STRING_MACRLC_SCHED_MODE, NULL, 0, strptr:NULL, defstrval:"default", TYPE_STRING, 0}, \
|
||||
{CONFIG_MACRLC_PUSCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \
|
||||
{CONFIG_MACRLC_PUCCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \
|
||||
{CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO, NULL, 0, strptr:NULL, defstrval:"round_robin_dl", TYPE_STRING, 0}, \
|
||||
}
|
||||
#define MACRLC_CC_IDX 0
|
||||
#define MACRLC_TRANSPORT_N_PREFERENCE_IDX 1
|
||||
@@ -105,6 +107,7 @@
|
||||
#define MACRLC_SCHED_MODE_IDX 17
|
||||
#define MACRLC_PUSCH10xSNR_IDX 18
|
||||
#define MACRLC_PUCCH10xSNR_IDX 19
|
||||
#define MACRLC_DEFAULT_SCHED_DL_ALGO_IDX 20
|
||||
/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
|
||||
@@ -61,82 +61,30 @@ enum flex_qam {
|
||||
//
|
||||
// Slice config related structures and enums
|
||||
//
|
||||
enum flex_dl_sorting {
|
||||
|
||||
CR_ROUND = 0; // Highest HARQ first
|
||||
CR_SRB12 = 1; // Highest SRB1+2 first
|
||||
CR_HOL = 2; // Highest HOL first
|
||||
CR_LC = 3; // Greatest RLC buffer first
|
||||
CR_CQI = 4; // Highest CQI first
|
||||
CR_LCP = 5; // Highest LC priority first
|
||||
enum flex_slice_algorithm {
|
||||
None = 0;
|
||||
Static = 1;
|
||||
NVS = 2;
|
||||
}
|
||||
|
||||
enum flex_ul_sorting {
|
||||
CRU_ROUND = 0; // Highest HARQ first
|
||||
CRU_BUF = 1; // Highest BSR first
|
||||
CRU_BTS = 2; // More bytes to schedule first
|
||||
CRU_MCS = 3; // Highest MCS first
|
||||
CRU_LCP = 4; // Highest LC priority first
|
||||
CRU_HOL = 5; // Highest HOL first
|
||||
message flex_slice_static {
|
||||
optional uint32 posLow = 1;
|
||||
optional uint32 posHigh = 2;
|
||||
}
|
||||
|
||||
enum flex_dl_accounting_policy {
|
||||
POL_FAIR = 0;
|
||||
POL_GREEDY = 1;
|
||||
POL_NUM = 2;
|
||||
message flex_slice {
|
||||
optional uint32 id = 1;
|
||||
optional string label = 2;
|
||||
optional string scheduler = 3;
|
||||
oneof params {
|
||||
flex_slice_static static = 10;
|
||||
}
|
||||
}
|
||||
|
||||
enum flex_ul_accounting_policy {
|
||||
POLU_FAIR = 0;
|
||||
POLU_GREEDY = 1;
|
||||
POLU_NUM = 2;
|
||||
}
|
||||
|
||||
enum flex_slice_label {
|
||||
xMBB = 0;
|
||||
URLLC = 1;
|
||||
mMTC = 2;
|
||||
xMTC = 3;
|
||||
Other = 4;
|
||||
}
|
||||
|
||||
message flex_dl_slice {
|
||||
optional uint32 id = 1;
|
||||
optional flex_slice_label label = 2;
|
||||
// should be between 0 and 100
|
||||
optional uint32 percentage = 3;
|
||||
// whether this slice should be exempted form interslice sharing
|
||||
optional bool isolation = 4;
|
||||
// increasing value means increasing prio
|
||||
optional uint32 priority = 5;
|
||||
// min and max RB to use (in frequency) in the range [0, N_RBG_MAX]
|
||||
optional uint32 position_low = 6;
|
||||
optional uint32 position_high = 7;
|
||||
// maximum MCS to be allowed in this slice
|
||||
optional uint32 maxmcs = 8;
|
||||
repeated flex_dl_sorting sorting = 9;
|
||||
optional flex_dl_accounting_policy accounting = 10;
|
||||
optional string scheduler_name = 11;
|
||||
}
|
||||
|
||||
message flex_ul_slice {
|
||||
optional uint32 id = 1;
|
||||
optional flex_slice_label label = 2;
|
||||
// should be between 0 and 100
|
||||
optional uint32 percentage = 3;
|
||||
// whether this slice should be exempted form interslice sharing
|
||||
optional bool isolation = 4;
|
||||
// increasing value means increasing prio
|
||||
optional uint32 priority = 5;
|
||||
// RB start to use (in frequency) in the range [0, N_RB_MAX]
|
||||
optional uint32 first_rb = 6;
|
||||
// TODO RB number
|
||||
//optional uint32 length_rb = 7;
|
||||
// maximum MCS to be allowed in this slice
|
||||
optional uint32 maxmcs = 8;
|
||||
repeated flex_ul_sorting sorting = 9;
|
||||
optional flex_ul_accounting_policy accounting = 10;
|
||||
optional string scheduler_name = 11;
|
||||
message flex_slice_dl_ul_config {
|
||||
optional flex_slice_algorithm algorithm = 1;
|
||||
repeated flex_slice slices = 2;
|
||||
optional string scheduler = 3; // if no slicing
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -49,14 +49,8 @@ message flex_cell_config {
|
||||
}
|
||||
|
||||
message flex_slice_config {
|
||||
// whether remaining RBs after first intra-slice allocation will
|
||||
// be allocated to UEs of the same slice
|
||||
optional bool intraslice_share_active = 3;
|
||||
// whether remaining RBs after slice allocation will be allocated
|
||||
// to UEs of another slice. Isolated slices will be ignored.
|
||||
optional bool interslice_share_active = 4;
|
||||
repeated flex_dl_slice dl = 1;
|
||||
repeated flex_ul_slice ul = 2;
|
||||
optional flex_slice_dl_ul_config dl = 6;
|
||||
optional flex_slice_dl_ul_config ul = 7;
|
||||
}
|
||||
|
||||
message flex_ue_config {
|
||||
|
||||
@@ -273,7 +273,6 @@ void *eNB_app_task(void *args_p) {
|
||||
if (EPC_MODE_ENABLED) {
|
||||
LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
|
||||
S1AP_REGISTER_ENB_CNF(msg_p).nb_mme);
|
||||
DevAssert(register_enb_pending > 0);
|
||||
register_enb_pending--;
|
||||
|
||||
/* Check if at least eNB is registered with one MME */
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "assertions.h"
|
||||
@@ -260,6 +261,16 @@ void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) {
|
||||
global_scheduler_mode=SCHED_MODE_DEFAULT;
|
||||
printf("sched mode = default %d [%s]\n",global_scheduler_mode,*(MacRLC_ParamList.paramarray[j][MACRLC_SCHED_MODE_IDX].strptr));
|
||||
}
|
||||
|
||||
char *s = *MacRLC_ParamList.paramarray[j][MACRLC_DEFAULT_SCHED_DL_ALGO_IDX].strptr;
|
||||
void *d = dlsym(NULL, s);
|
||||
AssertFatal(d, "%s(): no default scheduler DL algo '%s' found\n", __func__, s);
|
||||
// release default, add new
|
||||
pp_impl_param_t *dl_pp = &RC.mac[j]->pre_processor_dl;
|
||||
dl_pp->dl_algo.unset(&dl_pp->dl_algo.data);
|
||||
dl_pp->dl_algo = *(default_sched_dl_algo_t *) d;
|
||||
dl_pp->dl_algo.data = dl_pp->dl_algo.setup();
|
||||
LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", dl_pp->dl_algo.name);
|
||||
}// j=0..num_inst
|
||||
} /*else {// MacRLC_ParamList.numelt > 0 // ignore it
|
||||
|
||||
|
||||
@@ -306,6 +306,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
|
||||
if (reply->cell_config[i]->mbsfn_subframe_config_sfalloc)
|
||||
free(reply->cell_config[i]->mbsfn_subframe_config_sfalloc);
|
||||
|
||||
/* si_config is shared between MAC and RRC, free here */
|
||||
if (reply->cell_config[i]->si_config) {
|
||||
for(int j = 0; j < reply->cell_config[i]->si_config->n_si_message; j++) {
|
||||
free(reply->cell_config[i]->si_config->si_message[j]);
|
||||
@@ -316,26 +317,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
|
||||
}
|
||||
|
||||
if (reply->cell_config[i]->slice_config) {
|
||||
for (int j = 0; j < reply->cell_config[i]->slice_config->n_dl; ++j) {
|
||||
if (reply->cell_config[i]->slice_config->dl[j]->n_sorting > 0)
|
||||
free(reply->cell_config[i]->slice_config->dl[j]->sorting);
|
||||
|
||||
free(reply->cell_config[i]->slice_config->dl[j]->scheduler_name);
|
||||
free(reply->cell_config[i]->slice_config->dl[j]);
|
||||
}
|
||||
|
||||
free(reply->cell_config[i]->slice_config->dl);
|
||||
|
||||
for (int j = 0; j < reply->cell_config[i]->slice_config->n_ul; ++j) {
|
||||
if (reply->cell_config[i]->slice_config->ul[j]->n_sorting > 0)
|
||||
free(reply->cell_config[i]->slice_config->ul[j]->sorting);
|
||||
|
||||
free(reply->cell_config[i]->slice_config->ul[j]->scheduler_name);
|
||||
free(reply->cell_config[i]->slice_config->ul[j]);
|
||||
}
|
||||
|
||||
free(reply->cell_config[i]->slice_config->ul);
|
||||
free(reply->cell_config[i]->slice_config);
|
||||
flexran_agent_destroy_mac_slice_config(reply->cell_config[i]);
|
||||
}
|
||||
|
||||
free(reply->cell_config[i]);
|
||||
@@ -893,31 +875,40 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot
|
||||
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
|
||||
Protocol__FlexEnbConfigReply *enb_config = input->enb_config_reply_msg;
|
||||
|
||||
if (enb_config->n_cell_config == 0) {
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"received enb_config_reply message does not contain a cell_config\n");
|
||||
*msg = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (enb_config->n_cell_config > 1)
|
||||
LOG_W(FLEXRAN_AGENT, "ignoring slice configs for other cell except cell 0\n");
|
||||
|
||||
if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) {
|
||||
prepare_update_slice_config(mod_id, enb_config->cell_config[0]->slice_config);
|
||||
} else if (enb_config->cell_config[0]->has_eutra_band
|
||||
&& enb_config->cell_config[0]->has_dl_freq
|
||||
&& enb_config->cell_config[0]->has_ul_freq
|
||||
&& enb_config->cell_config[0]->has_dl_bandwidth) {
|
||||
initiate_soft_restart(mod_id, enb_config->cell_config[0]);
|
||||
} else if (flexran_agent_get_rrc_xface(mod_id)
|
||||
&& enb_config->cell_config[0]->has_x2_ho_net_control) {
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"setting X2 HO NetControl to %d\n",
|
||||
enb_config->cell_config[0]->x2_ho_net_control);
|
||||
const int rc = flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control);
|
||||
if (rc < 0)
|
||||
LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network");
|
||||
if (enb_config->n_cell_config > 0) {
|
||||
if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) {
|
||||
prepare_update_slice_config(mod_id, &enb_config->cell_config[0]->slice_config);
|
||||
}
|
||||
if (enb_config->cell_config[0]->has_eutra_band
|
||||
&& enb_config->cell_config[0]->has_dl_freq
|
||||
&& enb_config->cell_config[0]->has_ul_freq
|
||||
&& enb_config->cell_config[0]->has_dl_bandwidth) {
|
||||
initiate_soft_restart(mod_id, enb_config->cell_config[0]);
|
||||
}
|
||||
if (flexran_agent_get_rrc_xface(mod_id)
|
||||
&& enb_config->cell_config[0]->has_x2_ho_net_control) {
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"setting X2 HO NetControl to %d\n",
|
||||
enb_config->cell_config[0]->x2_ho_net_control);
|
||||
const int rc = flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control);
|
||||
if (rc < 0)
|
||||
LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network");
|
||||
}
|
||||
if (flexran_agent_get_rrc_xface(mod_id) && enb_config->cell_config[0]->n_plmn_id > 0) {
|
||||
flexran_agent_handle_plmn_update(mod_id,
|
||||
0,
|
||||
enb_config->cell_config[0]->n_plmn_id,
|
||||
enb_config->cell_config[0]->plmn_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (flexran_agent_get_s1ap_xface(mod_id) && enb_config->s1ap) {
|
||||
flexran_agent_handle_mme_update(mod_id,
|
||||
enb_config->s1ap->n_mme,
|
||||
enb_config->s1ap->mme);
|
||||
}
|
||||
|
||||
*msg = NULL;
|
||||
@@ -930,7 +921,11 @@ int flexran_agent_handle_ue_config_reply(mid_t mod_id, const void *params, Proto
|
||||
Protocol__FlexUeConfigReply *ue_config_reply = input->ue_config_reply_msg;
|
||||
|
||||
for (i = 0; flexran_agent_get_mac_xface(mod_id) && i < ue_config_reply->n_ue_config; i++)
|
||||
prepare_ue_slice_assoc_update(mod_id, ue_config_reply->ue_config[i]);
|
||||
prepare_ue_slice_assoc_update(mod_id, &ue_config_reply->ue_config[i]);
|
||||
/* prepare_ue_slice_assoc_update takes ownership of the individual
|
||||
* FlexUeConfig messages. Therefore, mark zero messages to not accidentally
|
||||
* free them twice */
|
||||
ue_config_reply->n_ue_config = 0;
|
||||
|
||||
*msg = NULL;
|
||||
return 0;
|
||||
|
||||
@@ -44,8 +44,6 @@ AGENT_PHY_xface *flexran_agent_get_phy_xface(mid_t mod_id);
|
||||
|
||||
extern AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];
|
||||
#define flexran_agent_get_mac_xface(mod_id) (agent_mac_xface[mod_id])
|
||||
/* Control module interface for the communication of the RRC Control Module with the agent */
|
||||
|
||||
/* Control module interface for the communication of the RRC Control Module with the agent */
|
||||
// AGENT_RRC_xface *flexran_agent_get_rrc_xface(mid_t mod_id);
|
||||
extern AGENT_RRC_xface *agent_rrc_xface[NUM_MAX_ENB];
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "flexran_agent_ran_api.h"
|
||||
#include "s1ap_eNB_ue_context.h"
|
||||
#include "s1ap_eNB_management_procedures.h"
|
||||
#include "openair2/LAYER2/MAC/slicing/slicing.h"
|
||||
|
||||
static inline int phy_is_present(mid_t mod_id, uint8_t cc_id) {
|
||||
return RC.eNB && RC.eNB[mod_id] && RC.eNB[mod_id][cc_id];
|
||||
@@ -3013,471 +3014,293 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti)
|
||||
}
|
||||
|
||||
/**************************** SLICING ****************************/
|
||||
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
|
||||
|
||||
int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id];
|
||||
|
||||
if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl)
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].id;
|
||||
|
||||
return 0;
|
||||
switch (RC.mac[mod_id]->pre_processor_dl.algorithm) {
|
||||
case STATIC_SLICING:
|
||||
return PROTOCOL__FLEX_SLICE_ALGORITHM__Static;
|
||||
default:
|
||||
return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) {
|
||||
int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
eNB_MAC_INST *mac = RC.mac[mod_id];
|
||||
const int cc_id = 0;
|
||||
|
||||
pp_impl_param_t dl = mac->pre_processor_dl;
|
||||
switch (algo) {
|
||||
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
|
||||
mac->pre_processor_dl = static_dl_init(mod_id, cc_id);
|
||||
break;
|
||||
default:
|
||||
mac->pre_processor_dl.algorithm = 0;
|
||||
mac->pre_processor_dl.dl = dlsch_scheduler_pre_processor;
|
||||
mac->pre_processor_dl.dl_algo.data = mac->pre_processor_dl.dl_algo.setup();
|
||||
mac->pre_processor_dl.slices = NULL;
|
||||
break;
|
||||
}
|
||||
if (dl.slices)
|
||||
dl.destroy(&dl.slices);
|
||||
if (dl.dl_algo.data)
|
||||
dl.dl_algo.unset(&dl.dl_algo.data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
|
||||
|
||||
switch (RC.mac[mod_id]->pre_processor_ul.algorithm) {
|
||||
case STATIC_SLICING:
|
||||
return PROTOCOL__FLEX_SLICE_ALGORITHM__Static;
|
||||
default:
|
||||
return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
|
||||
}
|
||||
}
|
||||
|
||||
int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
eNB_MAC_INST *mac = RC.mac[mod_id];
|
||||
const int cc_id = 0;
|
||||
|
||||
pp_impl_param_t ul = mac->pre_processor_ul;
|
||||
switch (algo) {
|
||||
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
|
||||
mac->pre_processor_ul = static_ul_init(mod_id, cc_id);
|
||||
break;
|
||||
default:
|
||||
mac->pre_processor_ul.algorithm = 0;
|
||||
mac->pre_processor_ul.ul = ulsch_scheduler_pre_processor;
|
||||
mac->pre_processor_ul.ul_algo.data = mac->pre_processor_ul.ul_algo.setup();
|
||||
mac->pre_processor_ul.slices = NULL;
|
||||
break;
|
||||
}
|
||||
if (ul.slices)
|
||||
ul.destroy(&ul.slices);
|
||||
if (ul.ul_algo.data)
|
||||
ul.ul_algo.unset(&ul.ul_algo.data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
slice_info_t *slices = RC.mac[mod_id]->pre_processor_dl.slices;
|
||||
if (!slices) return -1;
|
||||
const int idx = slices->UE_assoc_slice[ue_id];
|
||||
return slices->s[idx]->id;
|
||||
}
|
||||
|
||||
void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return;
|
||||
|
||||
if (!flexran_dl_slice_exists(mod_id, slice_idx)) return;
|
||||
|
||||
//RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id] = slice_idx;
|
||||
int idx = flexran_find_dl_slice(mod_id, slice_id);
|
||||
if (idx < 0) return;
|
||||
pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
|
||||
dl->move_UE(dl->slices, ue_id, idx);
|
||||
}
|
||||
|
||||
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id];
|
||||
|
||||
if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul)
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].id;
|
||||
|
||||
return 0;
|
||||
slice_info_t *slices = RC.mac[mod_id]->pre_processor_ul.slices;
|
||||
if (!slices) return -1;
|
||||
const int idx = slices->UE_assoc_slice[ue_id];
|
||||
return slices->s[idx]->id;
|
||||
}
|
||||
|
||||
void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) {
|
||||
void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return;
|
||||
|
||||
if (!flexran_ul_slice_exists(mod_id, slice_idx)) return;
|
||||
|
||||
//RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id] = slice_idx;
|
||||
int idx = flexran_find_ul_slice(mod_id, slice_id);
|
||||
if (idx < 0) return;
|
||||
pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
|
||||
ul->move_UE(ul->slices, ue_id, idx);
|
||||
}
|
||||
|
||||
int flexran_dl_slice_exists(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl;
|
||||
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
void *params = NULL;
|
||||
switch (s->params_case) {
|
||||
case PROTOCOL__FLEX_SLICE__PARAMS_STATIC:
|
||||
params = malloc(sizeof(static_slice_param_t));
|
||||
if (!params) return 0;
|
||||
((static_slice_param_t *)params)->posLow = s->static_->poslow;
|
||||
((static_slice_param_t *)params)->posHigh = s->static_->poshigh;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
|
||||
char *l = s->label ? strdup(s->label) : NULL;
|
||||
void *algo = &dl->dl_algo; // default scheduler
|
||||
if (s->scheduler) {
|
||||
algo = dlsym(NULL, s->scheduler);
|
||||
if (!algo) {
|
||||
free(params);
|
||||
LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
|
||||
return -15;
|
||||
}
|
||||
}
|
||||
return dl->addmod_slice(dl->slices, s->id, l, algo, params);
|
||||
}
|
||||
|
||||
int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
int newidx = RC.mac[mod_id]->slice_info.n_dl;
|
||||
|
||||
if (newidx >= MAX_NUM_SLICES) return -1;
|
||||
|
||||
++RC.mac[mod_id]->slice_info.n_dl;
|
||||
flexran_set_dl_slice_id(mod_id, newidx, slice_id);
|
||||
return newidx;
|
||||
int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
const int idx = flexran_find_dl_slice(mod_id, s->id);
|
||||
if (idx < 0) return 0;
|
||||
pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
|
||||
return dl->remove_slice(dl->slices, idx);
|
||||
}
|
||||
|
||||
int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
|
||||
int n = sli->n_dl;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (sli->dl[i].id == slice_id) return i;
|
||||
}
|
||||
|
||||
slice_info_t *si = RC.mac[mod_id]->pre_processor_dl.slices;
|
||||
for (int i = 0; i < si->num; ++i)
|
||||
if (si->s[i]->id == slice_id)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
|
||||
|
||||
if (sli->n_dl <= 1) return -1;
|
||||
|
||||
if (sli->dl[slice_idx].sched_name) free(sli->dl[slice_idx].sched_name);
|
||||
|
||||
--sli->n_dl;
|
||||
|
||||
/* move last element to the position of the removed one */
|
||||
if (slice_idx != sli->n_dl)
|
||||
memcpy(&sli->dl[slice_idx], &sli->dl[sli->n_dl], sizeof(sli->dl[sli->n_dl]));
|
||||
|
||||
memset(&sli->dl[sli->n_dl], 0, sizeof(sli->dl[sli->n_dl]));
|
||||
/* all UEs that have been in the old slice are put into slice index 0 */
|
||||
//int *assoc_list = RC.mac[mod_id]->UE_info.assoc_dl_slice_idx;
|
||||
|
||||
//for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) {
|
||||
// if (assoc_list[i] == slice_idx)
|
||||
// assoc_list[i] = 0;
|
||||
//}
|
||||
|
||||
return 1;
|
||||
void flexran_get_dl_slice(mid_t mod_id,
|
||||
int slice_idx,
|
||||
Protocol__FlexSlice *slice,
|
||||
Protocol__FlexSliceAlgorithm algo) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
slice_t *s_ = RC.mac[mod_id]->pre_processor_dl.slices->s[slice_idx];
|
||||
slice->has_id = 1;
|
||||
slice->id = s_->id;
|
||||
slice->label = s_->label;
|
||||
slice->scheduler = s_->dl_algo.name;
|
||||
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET;
|
||||
switch (algo) {
|
||||
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
|
||||
slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic));
|
||||
if (!slice->static_) return;
|
||||
protocol__flex_slice_static__init(slice->static_);
|
||||
slice->static_->has_poslow = 1;
|
||||
slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow;
|
||||
slice->static_->has_poshigh = 1;
|
||||
slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh;
|
||||
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int flexran_get_num_dl_slices(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.n_dl;
|
||||
}
|
||||
|
||||
int flexran_get_intraslice_sharing_active(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.intraslice_share_active;
|
||||
}
|
||||
void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.intraslice_share_active = intraslice_active;
|
||||
}
|
||||
|
||||
int flexran_get_interslice_sharing_active(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.interslice_share_active;
|
||||
}
|
||||
void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.interslice_share_active = interslice_active;
|
||||
}
|
||||
|
||||
slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].id;
|
||||
}
|
||||
void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].id = slice_id;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].pct * 100.0f;
|
||||
}
|
||||
void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].pct = percentage / 100.0f;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].isol;
|
||||
}
|
||||
void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].isol = is_isolated;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].prio;
|
||||
}
|
||||
void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].prio = priority;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low;
|
||||
}
|
||||
void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low = poslow;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high;
|
||||
}
|
||||
void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high = poshigh;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs;
|
||||
}
|
||||
void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs = maxmcs;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
if (!(*sorting_list)) {
|
||||
*sorting_list = calloc(CR_NUM, sizeof(Protocol__FlexDlSorting));
|
||||
|
||||
if (!(*sorting_list)) return -1;
|
||||
}
|
||||
|
||||
uint32_t policy = RC.mac[mod_id]->slice_info.dl[slice_idx].sorting;
|
||||
|
||||
for (int i = 0; i < CR_NUM; i++) {
|
||||
switch (policy >> 4 * (CR_NUM - 1 - i) & 0xF) {
|
||||
case CR_ROUND:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND;
|
||||
break;
|
||||
|
||||
case CR_SRB12:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_SRB12;
|
||||
break;
|
||||
|
||||
case CR_HOL:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_HOL;
|
||||
break;
|
||||
|
||||
case CR_LC:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LC;
|
||||
break;
|
||||
|
||||
case CR_CQI:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_CQI;
|
||||
break;
|
||||
|
||||
case CR_LCP:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LCP;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* this should not happen, but a "default" */
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CR_NUM;
|
||||
}
|
||||
void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
uint32_t policy = 0;
|
||||
|
||||
for (int i = 0; i < n && i < CR_NUM; i++) {
|
||||
switch (sorting_list[i]) {
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_ROUND:
|
||||
policy = policy << 4 | CR_ROUND;
|
||||
break;
|
||||
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_SRB12:
|
||||
policy = policy << 4 | CR_SRB12;
|
||||
break;
|
||||
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_HOL:
|
||||
policy = policy << 4 | CR_HOL;
|
||||
break;
|
||||
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_LC:
|
||||
policy = policy << 4 | CR_LC;
|
||||
break;
|
||||
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_CQI:
|
||||
policy = policy << 4 | CR_CQI;
|
||||
break;
|
||||
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_LCP:
|
||||
policy = policy << 4 | CR_LCP;
|
||||
break;
|
||||
|
||||
default: /* suppresses warnings */
|
||||
policy = policy << 4 | CR_ROUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* fill up with 0 == CR_ROUND */
|
||||
if (CR_NUM > n) policy = policy << 4 * (CR_NUM - n);
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].sorting = policy;
|
||||
}
|
||||
|
||||
Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
|
||||
|
||||
switch (RC.mac[mod_id]->slice_info.dl[slice_idx].accounting) {
|
||||
case POL_FAIR:
|
||||
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
|
||||
|
||||
case POL_GREEDY:
|
||||
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY;
|
||||
|
||||
default:
|
||||
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
|
||||
}
|
||||
}
|
||||
void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
switch (accounting) {
|
||||
case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR:
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR;
|
||||
return;
|
||||
|
||||
case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY:
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_GREEDY;
|
||||
return;
|
||||
|
||||
default:
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return NULL;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name;
|
||||
}
|
||||
int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
|
||||
if (RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name)
|
||||
free(RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name);
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name = strdup(name);
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb = dlsym(NULL, name);
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb != NULL;
|
||||
if (!RC.mac[mod_id]->pre_processor_dl.slices) return 0;
|
||||
return RC.mac[mod_id]->pre_processor_dl.slices->num;
|
||||
}
|
||||
|
||||
int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) {
|
||||
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
void *params = NULL;
|
||||
switch (s->params_case) {
|
||||
case PROTOCOL__FLEX_SLICE__PARAMS_STATIC:
|
||||
params = malloc(sizeof(static_slice_param_t));
|
||||
if (!params) return 0;
|
||||
((static_slice_param_t *)params)->posLow = s->static_->poslow;
|
||||
((static_slice_param_t *)params)->posHigh = s->static_->poshigh;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
|
||||
char *l = s->label ? strdup(s->label) : NULL;
|
||||
void *algo = &ul->ul_algo; // default scheduler
|
||||
if (s->scheduler) {
|
||||
algo = dlsym(NULL, s->scheduler);
|
||||
if (!algo) {
|
||||
free(params);
|
||||
LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
|
||||
return -15;
|
||||
}
|
||||
}
|
||||
return ul->addmod_slice(ul->slices, s->id, l, algo, params);
|
||||
}
|
||||
|
||||
int newidx = RC.mac[mod_id]->slice_info.n_ul;
|
||||
|
||||
if (newidx >= MAX_NUM_SLICES) return -1;
|
||||
|
||||
++RC.mac[mod_id]->slice_info.n_ul;
|
||||
flexran_set_ul_slice_id(mod_id, newidx, slice_id);
|
||||
return newidx;
|
||||
int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
const int idx = flexran_find_ul_slice(mod_id, s->id);
|
||||
if (idx < 0) return 0;
|
||||
pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
|
||||
return ul->remove_slice(ul->slices, idx);
|
||||
}
|
||||
|
||||
int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
|
||||
int n = sli->n_ul;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (sli->ul[i].id == slice_id) return i;
|
||||
}
|
||||
|
||||
slice_info_t *si = RC.mac[mod_id]->pre_processor_ul.slices;
|
||||
for (int i = 0; i < si->num; ++i)
|
||||
if (si->s[i]->id == slice_id)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
void flexran_get_ul_slice(mid_t mod_id,
|
||||
int slice_idx,
|
||||
Protocol__FlexSlice *slice,
|
||||
Protocol__FlexSliceAlgorithm algo) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
slice_t *s_ = RC.mac[mod_id]->pre_processor_ul.slices->s[slice_idx];
|
||||
slice->has_id = 1;
|
||||
slice->id = s_->id;
|
||||
slice->label = s_->label;
|
||||
slice->scheduler = s_->ul_algo.name;
|
||||
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET;
|
||||
switch (algo) {
|
||||
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
|
||||
slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic));
|
||||
if (!slice->static_) return;
|
||||
protocol__flex_slice_static__init(slice->static_);
|
||||
slice->static_->has_poslow = 1;
|
||||
slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow;
|
||||
slice->static_->has_poshigh = 1;
|
||||
slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh;
|
||||
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
|
||||
|
||||
if (sli->n_ul <= 1) return -1;
|
||||
|
||||
if (sli->ul[slice_idx].sched_name) free(sli->ul[slice_idx].sched_name);
|
||||
|
||||
--sli->n_ul;
|
||||
|
||||
/* move last element to the position of the removed one */
|
||||
if (slice_idx != sli->n_ul)
|
||||
memcpy(&sli->ul[slice_idx], &sli->ul[sli->n_ul], sizeof(sli->ul[sli->n_ul]));
|
||||
|
||||
memset(&sli->ul[sli->n_ul], 0, sizeof(sli->ul[sli->n_ul]));
|
||||
/* all UEs that have been in the old slice are put into slice index 0 */
|
||||
//int *assoc_list = RC.mac[mod_id]->UE_info.assoc_ul_slice_idx;
|
||||
|
||||
//for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) {
|
||||
// if (assoc_list[i] == slice_idx)
|
||||
// assoc_list[i] = 0;
|
||||
//}
|
||||
|
||||
return sli->n_ul;
|
||||
}
|
||||
|
||||
int flexran_get_num_ul_slices(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.n_ul;
|
||||
}
|
||||
|
||||
int flexran_ul_slice_exists(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul;
|
||||
}
|
||||
|
||||
slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].id;
|
||||
}
|
||||
void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].id = slice_id;
|
||||
}
|
||||
|
||||
int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].pct * 100.0f;
|
||||
}
|
||||
void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].pct = percentage / 100.0f;
|
||||
}
|
||||
|
||||
int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb;
|
||||
}
|
||||
|
||||
void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb = first_rb;
|
||||
}
|
||||
|
||||
int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs;
|
||||
}
|
||||
void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs = maxmcs;
|
||||
}
|
||||
|
||||
char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return NULL;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name;
|
||||
}
|
||||
int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
if (!RC.mac[mod_id]->pre_processor_ul.slices) return 0;
|
||||
return RC.mac[mod_id]->pre_processor_ul.slices->num;
|
||||
}
|
||||
|
||||
if (RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name)
|
||||
free(RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name);
|
||||
char *flexran_get_dl_scheduler_name(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return NULL;
|
||||
return RC.mac[mod_id]->pre_processor_dl.dl_algo.name;
|
||||
}
|
||||
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name = strdup(name);
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb = dlsym(NULL, name);
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb != NULL;
|
||||
int flexran_set_dl_scheduler(mid_t mod_id, char *sched) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
void *d = dlsym(NULL, sched);
|
||||
if (!d) return -2;
|
||||
pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl;
|
||||
dl_pp->dl_algo.unset(&dl_pp->dl_algo.data);
|
||||
dl_pp->dl_algo = *(default_sched_dl_algo_t *) d;
|
||||
dl_pp->dl_algo.data = dl_pp->dl_algo.setup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *flexran_get_ul_scheduler_name(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return NULL;
|
||||
return RC.mac[mod_id]->pre_processor_ul.ul_algo.name;
|
||||
}
|
||||
|
||||
int flexran_set_ul_scheduler(mid_t mod_id, char *sched) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
void *d = dlsym(NULL, sched);
|
||||
if (!d) return -2;
|
||||
pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul;
|
||||
ul_pp->ul_algo.unset(&ul_pp->ul_algo.data);
|
||||
ul_pp->ul_algo = *(default_sched_ul_algo_t *) d;
|
||||
ul_pp->ul_algo.data = ul_pp->ul_algo.setup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************** S1AP **************************/
|
||||
@@ -3634,6 +3457,168 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) {
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return -1;
|
||||
if (!rrc_is_present(mod_id)) return -2;
|
||||
|
||||
/* Reconstruct S1AP_REGISTER_ENB_REQ */
|
||||
MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, S1AP_REGISTER_ENB_REQ);
|
||||
RCconfig_S1(m, mod_id);
|
||||
|
||||
const int CC_id = 0;
|
||||
eNB_RRC_INST *rrc = RC.rrc[CC_id];
|
||||
RrcConfigurationReq *conf = &rrc->configuration;
|
||||
S1AP_REGISTER_ENB_REQ(m).num_plmn = conf->num_plmn;
|
||||
for (int i = 0; i < conf->num_plmn; ++i) {
|
||||
S1AP_REGISTER_ENB_REQ(m).mcc[i] = conf->mcc[i];
|
||||
S1AP_REGISTER_ENB_REQ(m).mnc[i] = conf->mnc[i];
|
||||
S1AP_REGISTER_ENB_REQ(m).mnc_digit_length[i] = conf->mnc_digit_length[i];
|
||||
}
|
||||
|
||||
/* reconstruct MME list, it might have been updated since initial
|
||||
* configuration */
|
||||
S1AP_REGISTER_ENB_REQ(m).nb_mme = 0;
|
||||
struct s1ap_eNB_mme_data_s *mme = NULL;
|
||||
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
|
||||
const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme;
|
||||
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = mme->mme_s1_ip.ipv4;
|
||||
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme->mme_s1_ip.ipv4_address);
|
||||
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = mme->mme_s1_ip.ipv6;
|
||||
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6_address, mme->mme_s1_ip.ipv6_address);
|
||||
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = mme->broadcast_plmn_num;
|
||||
for (int i = 0; i < mme->broadcast_plmn_num; ++i)
|
||||
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = mme->broadcast_plmn_index[i];
|
||||
S1AP_REGISTER_ENB_REQ(m).nb_mme += 1;
|
||||
}
|
||||
|
||||
if (S1AP_REGISTER_ENB_REQ(m).nb_mme + n_mme > S1AP_MAX_NB_MME_IP_ADDRESS)
|
||||
return -1;
|
||||
|
||||
for (int i = 0; i < n_mme; ++i) {
|
||||
const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme;
|
||||
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme_ipv4[0]);
|
||||
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = 1;
|
||||
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = 0;
|
||||
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = S1AP_REGISTER_ENB_REQ(m).num_plmn;
|
||||
for (int i = 0; i < S1AP_REGISTER_ENB_REQ(m).num_plmn; ++i)
|
||||
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = i;
|
||||
S1AP_REGISTER_ENB_REQ(m).nb_mme += 1;
|
||||
}
|
||||
|
||||
itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) {
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return -1;
|
||||
struct s1ap_eNB_mme_data_s *mme = NULL;
|
||||
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
|
||||
if (mme->mme_s1_ip.ipv4
|
||||
&& strncmp(mme->mme_s1_ip.ipv4_address, mme_ipv4[0], 16) == 0)
|
||||
break;
|
||||
}
|
||||
if (!mme)
|
||||
return -2;
|
||||
|
||||
MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, SCTP_CLOSE_ASSOCIATION);
|
||||
SCTP_CLOSE_ASSOCIATION(m).assoc_id = mme->assoc_id;
|
||||
itti_send_msg_to_task (TASK_SCTP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m);
|
||||
|
||||
switch (mme->state) {
|
||||
case S1AP_ENB_STATE_WAITING:
|
||||
s1ap->s1ap_mme_nb -= 1;
|
||||
if (s1ap->s1ap_mme_pending_nb > 0)
|
||||
s1ap->s1ap_mme_pending_nb -= 1;
|
||||
break;
|
||||
case S1AP_ENB_STATE_CONNECTED:
|
||||
case S1AP_ENB_OVERLOAD: /* I am not sure the decrements are right here */
|
||||
s1ap->s1ap_mme_nb -= 1;
|
||||
s1ap->s1ap_mme_associated_nb -= 1;
|
||||
break;
|
||||
case S1AP_ENB_STATE_DISCONNECTED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
RB_REMOVE(s1ap_mme_map, &s1ap->s1ap_mme_head, mme);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id) {
|
||||
if (!rrc_is_present(mod_id))
|
||||
return -1;
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap)
|
||||
return -2;
|
||||
|
||||
eNB_RRC_INST *rrc = RC.rrc[CC_id];
|
||||
RrcConfigurationReq *conf = &rrc->configuration;
|
||||
|
||||
uint8_t num_plmn_old = conf->num_plmn;
|
||||
uint16_t mcc[PLMN_LIST_MAX_SIZE];
|
||||
uint16_t mnc[PLMN_LIST_MAX_SIZE];
|
||||
uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE];
|
||||
for (int i = 0; i < num_plmn_old; ++i) {
|
||||
mcc[i] = conf->mcc[i];
|
||||
mnc[i] = conf->mnc[i];
|
||||
mnc_digit_length[i] = conf->mnc_digit_length[i];
|
||||
}
|
||||
|
||||
conf->num_plmn = (uint8_t) n_plmn;
|
||||
for (int i = 0; i < conf->num_plmn; ++i) {
|
||||
conf->mcc[i] = plmn_id[i]->mcc;
|
||||
conf->mnc[i] = plmn_id[i]->mnc;
|
||||
conf->mnc_digit_length[i] = plmn_id[i]->mnc_length;
|
||||
}
|
||||
|
||||
rrc_eNB_carrier_data_t *carrier = &rrc->carrier[CC_id];
|
||||
extern uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
|
||||
int Mod_id,
|
||||
int CC_id,
|
||||
BOOLEAN_t brOption,
|
||||
RrcConfigurationReq *configuration);
|
||||
carrier->sizeof_SIB1 = do_SIB1(carrier, mod_id, CC_id, FALSE, conf);
|
||||
if (carrier->sizeof_SIB1 < 0)
|
||||
return -1337; /* SIB1 encoding failed, hell will probably break loose */
|
||||
|
||||
s1ap->num_plmn = (uint8_t) n_plmn;
|
||||
for (int i = 0; i < conf->num_plmn; ++i) {
|
||||
s1ap->mcc[i] = plmn_id[i]->mcc;
|
||||
s1ap->mnc[i] = plmn_id[i]->mnc;
|
||||
s1ap->mnc_digit_length[i] = plmn_id[i]->mnc_length;
|
||||
}
|
||||
|
||||
int bpn_failed = 0;
|
||||
struct s1ap_eNB_mme_data_s *mme = NULL;
|
||||
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
|
||||
for (int i = 0; i < mme->broadcast_plmn_num; ++i) {
|
||||
/* search the new index and update. If we don't find, we count this using
|
||||
* bpn_failed to now how many broadcast_plmns could not be updated */
|
||||
int idx = mme->broadcast_plmn_index[i];
|
||||
int omcc = mcc[idx];
|
||||
int omnc = mnc[idx];
|
||||
int omncl = mnc_digit_length[idx];
|
||||
int j = 0;
|
||||
for (j = 0; j < s1ap->num_plmn; ++j) {
|
||||
if (s1ap->mcc[j] == omcc
|
||||
&& s1ap->mnc[j] == omnc
|
||||
&& s1ap->mnc_digit_length[j] == omncl) {
|
||||
mme->broadcast_plmn_index[i] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == s1ap->num_plmn) /* could not find the old PLMN in the new ones */
|
||||
bpn_failed++;
|
||||
}
|
||||
}
|
||||
if (bpn_failed > 0)
|
||||
return -10000 - bpn_failed;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf){
|
||||
if (!rrc_is_present(mod_id)) return -1;
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
@@ -3644,7 +3629,7 @@ int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_con
|
||||
RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head){
|
||||
if (ue->eNB_ue_s1ap_id == enb_ue_s1ap_id) break;
|
||||
}
|
||||
if (ue == NULL) return -1;
|
||||
if (!ue) return 0; // UE does not exist: it might be connected but CN did not answer
|
||||
|
||||
if (ue->mme_ref->mme_s1_ip.ipv4)
|
||||
ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv4_address[0];
|
||||
|
||||
@@ -656,156 +656,66 @@ int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index);
|
||||
uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti);
|
||||
|
||||
/************************** Slice configuration **************************/
|
||||
/* Get the currently active DL slicing algorithm */
|
||||
Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id);
|
||||
/* Set the active DL slicing algorithm */
|
||||
int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo);
|
||||
|
||||
/* Get the currently active UL slicing algorithm */
|
||||
Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id);
|
||||
/* Set the active UL slicing algorithm */
|
||||
int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo);
|
||||
|
||||
/* Get the DL slice ID for a UE */
|
||||
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id);
|
||||
|
||||
/* Set the DL slice index(!) for a UE */
|
||||
void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx);
|
||||
/* Set the DL slice for a UE */
|
||||
void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id);
|
||||
|
||||
/* Get the UL slice ID for a UE */
|
||||
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id);
|
||||
/* Set the UL slice for a UE */
|
||||
void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id);
|
||||
|
||||
/* Set the UL slice index(!) for a UE */
|
||||
void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx);
|
||||
|
||||
/* Whether intraslice sharing is active, return boolean */
|
||||
int flexran_get_intraslice_sharing_active(mid_t mod_id);
|
||||
/* Set whether intraslice sharing is active */
|
||||
void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active);
|
||||
|
||||
/* Whether intraslice sharing is active, return boolean */
|
||||
int flexran_get_interslice_sharing_active(mid_t mod_id);
|
||||
/* Set whether intraslice sharing is active */
|
||||
void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active);
|
||||
/* Create slice in DL, returns the new slice index */
|
||||
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s);
|
||||
/* Remove slice in DL, returns new number of slices or -1 on error */
|
||||
int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s);
|
||||
|
||||
/* Finds slice in DL with given slice_id and returns slice index */
|
||||
int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id);
|
||||
/* Return the parameters of slice at index slice_idx */
|
||||
void flexran_get_dl_slice(mid_t mod_id,
|
||||
int slice_idx,
|
||||
Protocol__FlexSlice *slice,
|
||||
Protocol__FlexSliceAlgorithm algo);
|
||||
/* Get the number of slices in DL */
|
||||
int flexran_get_num_dl_slices(mid_t mod_id);
|
||||
|
||||
/* Query slice existence in DL. Return is boolean value */
|
||||
int flexran_dl_slice_exists(mid_t mod_id, int slice_idx);
|
||||
/* Create slice in UL, returns the new slice index */
|
||||
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s);
|
||||
/* Remove slice in UL */
|
||||
int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s);
|
||||
|
||||
/* Create slice in DL, returns the new slice index */
|
||||
int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id);
|
||||
/* Finds slice in DL with given slice_id and returns slice index */
|
||||
int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id);
|
||||
/* Remove slice in DL, returns new number of slices or -1 on error */
|
||||
int flexran_remove_dl_slice(mid_t mod_id, int slice_idx);
|
||||
|
||||
/* Get the ID of a slice in DL */
|
||||
slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx);
|
||||
/* Set the ID of a slice in DL */
|
||||
void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id);
|
||||
|
||||
/* Get the RB share a slice in DL, value 0-100 */
|
||||
int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx);
|
||||
/* Set the RB share a slice in DL, value 0-100 */
|
||||
void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage);
|
||||
|
||||
/* Whether a slice in DL is isolated */
|
||||
int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx);
|
||||
/* Set whether a slice in DL is isolated */
|
||||
void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated);
|
||||
|
||||
/* Get the priority of a slice in DL */
|
||||
int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx);
|
||||
/* Get the priority of a slice in DL */
|
||||
void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority);
|
||||
|
||||
/* Get the lower end of the frequency range for the slice positioning in DL */
|
||||
int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx);
|
||||
/* Set the lower end of the frequency range for the slice positioning in DL */
|
||||
void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow);
|
||||
|
||||
/* Get the higher end of the frequency range for the slice positioning in DL */
|
||||
int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx);
|
||||
/* Set the higher end of the frequency range for the slice positioning in DL */
|
||||
void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh);
|
||||
|
||||
/* Get the maximum MCS for slice in DL */
|
||||
int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx);
|
||||
/* Set the maximum MCS for slice in DL */
|
||||
void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs);
|
||||
|
||||
/* Get the sorting order of a slice in DL, return value is number of elements
|
||||
* in sorting_list */
|
||||
int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list);
|
||||
/* Set the sorting order of a slice in DL */
|
||||
void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n);
|
||||
|
||||
/* Get the accounting policy for a slice in DL */
|
||||
Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx);
|
||||
/* Set the accounting policy for a slice in DL */
|
||||
void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting);
|
||||
|
||||
/* Get the scheduler name for a slice in DL */
|
||||
char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx);
|
||||
/* Set the scheduler name for a slice in DL */
|
||||
int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name);
|
||||
|
||||
int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id);
|
||||
/* Return the parameters of slice at index slice_idx */
|
||||
void flexran_get_ul_slice(mid_t mod_id,
|
||||
int slice_idx,
|
||||
Protocol__FlexSlice *slice,
|
||||
Protocol__FlexSliceAlgorithm algo);
|
||||
/* Get the number of slices in UL */
|
||||
int flexran_get_num_ul_slices(mid_t mod_id);
|
||||
|
||||
/* Query slice existence in UL. Return is boolean value */
|
||||
int flexran_ul_slice_exists(mid_t mod_id, int slice_idx);
|
||||
/* Get the name of/Set the DL scheduling algorithm. If slicing is active, this
|
||||
* corresponds to the default algorithm for slices, otherwise the currently
|
||||
* used one. */
|
||||
char *flexran_get_dl_scheduler_name(mid_t mod_id);
|
||||
int flexran_set_dl_scheduler(mid_t mod_id, char *sched);
|
||||
|
||||
/* Create slice in UL, returns the new slice index */
|
||||
int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id);
|
||||
/* Finds slice in UL with given slice_id and returns slice index */
|
||||
int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id);
|
||||
/* Remove slice in UL */
|
||||
int flexran_remove_ul_slice(mid_t mod_id, int slice_idx);
|
||||
|
||||
/* Get the ID of a slice in UL */
|
||||
slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx);
|
||||
/* Set the ID of a slice in UL */
|
||||
void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id);
|
||||
|
||||
/* Get the RB share a slice in UL, value 0-100 */
|
||||
int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx);
|
||||
/* Set the RB share a slice in UL, value 0-100 */
|
||||
void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage);
|
||||
|
||||
/* TODO Whether a slice in UL is isolated */
|
||||
/*int flexran_get_ul_slice_isolation(mid_t mod_id, int slice_idx);*/
|
||||
/* TODO Set whether a slice in UL is isolated */
|
||||
/*void flexran_set_ul_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated);*/
|
||||
|
||||
/* TODO Get the priority of a slice in UL */
|
||||
/*int flexran_get_ul_slice_priority(mid_t mod_id, int slice_idx);*/
|
||||
/* TODO Set the priority of a slice in UL */
|
||||
/*void flexran_set_ul_slice_priority(mid_t mod_id, int slice_idx, int priority);*/
|
||||
|
||||
/* Get the first RB for allocation in a slice in UL */
|
||||
int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx);
|
||||
/* Set the first RB for allocation in a slice in UL */
|
||||
void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb);
|
||||
|
||||
/* TODO Get the number of RB for the allocation in a slice in UL */
|
||||
/*int flexran_get_ul_slice_length_rb(mid_t mod_id, int slice_idx);*/
|
||||
/* TODO Set the of number of RB for the allocation in a slice in UL */
|
||||
/*void flexran_set_ul_slice_length_rb(mid_t mod_id, int slice_idx, int poshigh);*/
|
||||
|
||||
/* Get the maximum MCS for slice in UL */
|
||||
int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx);
|
||||
/* Set the maximum MCS for slice in UL */
|
||||
void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs);
|
||||
|
||||
/* TODO Get the sorting order of a slice in UL, return value is number of elements
|
||||
* in sorting_list */
|
||||
/*int flexran_get_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting **sorting_list);*/
|
||||
/* TODO Set the sorting order of a slice in UL */
|
||||
/*void flexran_set_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting *sorting_list, int n);*/
|
||||
|
||||
/* TODO Get the accounting policy for a slice in UL */
|
||||
/*Protocol__UlAccountingPolicy flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx);*/
|
||||
/* TODO Set the accounting policy for a slice in UL */
|
||||
/*void flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__UlAccountingPolicy accountin);*/
|
||||
|
||||
/* Get the scheduler name for a slice in UL */
|
||||
char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx);
|
||||
/* Set the scheduler name for a slice in UL */
|
||||
int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name);
|
||||
/* Get the name of/Set the UL scheduler algorithm. Same applies as for the DL
|
||||
* case */
|
||||
char *flexran_get_ul_scheduler_name(mid_t mod_id);
|
||||
int flexran_set_ul_scheduler(mid_t mod_id, char *sched);
|
||||
|
||||
/************************** S1AP **************************/
|
||||
/* Get the number of MMEs to be connected */
|
||||
@@ -832,6 +742,15 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM
|
||||
/* Get the S1AP UE conf */
|
||||
int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf);
|
||||
|
||||
/* Add MMEs and re-issue S1AP Registration Request */
|
||||
int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4);
|
||||
|
||||
/* Remove MMEs and and cut SCTP to MME */
|
||||
int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4);
|
||||
|
||||
/* Set a new PLMN configuration */
|
||||
int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id);
|
||||
|
||||
/********************* general information *****************/
|
||||
/* get an ID for this BS (or part of a BS) */
|
||||
uint64_t flexran_get_bs_id(mid_t mod_id);
|
||||
|
||||
@@ -547,7 +547,7 @@ copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
|
||||
ul_req_tmp->ul_config_request_body.number_of_pdus = 0;
|
||||
|
||||
if (ul_req->ul_config_request_body.number_of_pdus>0) {
|
||||
LOG_D(PHY, "%s() active NOW (frameP:%d subframeP:%d) pdus:%d\n", __FUNCTION__, frameP, subframeP, ul_req->ul_config_request_body.number_of_pdus);
|
||||
LOG_D(MAC, "%s() active NOW (frameP:%d subframeP:%d) pdus:%d\n", __FUNCTION__, frameP, subframeP, ul_req->ul_config_request_body.number_of_pdus);
|
||||
}
|
||||
|
||||
memcpy((void *)ul_req->ul_config_request_body.ul_config_pdu_list,
|
||||
@@ -556,6 +556,11 @@ copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
|
||||
}
|
||||
}
|
||||
|
||||
extern int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type);
|
||||
extern int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type);
|
||||
extern void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch);
|
||||
extern void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
|
||||
|
||||
void
|
||||
eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
frame_t frameP,
|
||||
@@ -843,6 +848,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
}
|
||||
|
||||
/* Note: This should not be done in the MAC! */
|
||||
/*
|
||||
for (int ii=0; ii<MAX_MOBILES_PER_ENB; ii++) {
|
||||
LTE_eNB_ULSCH_t *ulsch = RC.eNB[module_idP][CC_id]->ulsch[ii];
|
||||
|
||||
@@ -862,6 +868,17 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
clean_eNb_dlsch(dlsch);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
int id;
|
||||
|
||||
// clean ULSCH entries for rnti
|
||||
id = find_ulsch(rnti,RC.eNB[module_idP][CC_id],SEARCH_EXIST);
|
||||
if (id>=0) clean_eNb_ulsch(RC.eNB[module_idP][CC_id]->ulsch[id]);
|
||||
|
||||
// clean DLSCH entries for rnti
|
||||
id = find_dlsch(rnti,RC.eNB[module_idP][CC_id],SEARCH_EXIST);
|
||||
if (id>=0) clean_eNb_dlsch(RC.eNB[module_idP][CC_id]->dlsch[id][0]);
|
||||
|
||||
for (int j = 0; j < 10; j++) {
|
||||
nfapi_ul_config_request_body_t *ul_req_tmp = NULL;
|
||||
|
||||
@@ -573,10 +573,7 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,
|
||||
VCD_FUNCTION_IN);
|
||||
start_meas(&eNB->schedule_dlsch_preprocessor);
|
||||
dlsch_scheduler_pre_processor(module_idP,
|
||||
CC_id,
|
||||
frameP,
|
||||
subframeP);
|
||||
eNB->pre_processor_dl.dl(module_idP, CC_id, frameP, subframeP);
|
||||
stop_meas(&eNB->schedule_dlsch_preprocessor);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,
|
||||
VCD_FUNCTION_OUT);
|
||||
@@ -588,6 +585,7 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id];
|
||||
eNB_UE_STATS *eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id];
|
||||
eNB_UE_stats->TBS = 0;
|
||||
const rnti_t rnti = ue_template->rnti;
|
||||
|
||||
// If TDD
|
||||
@@ -679,15 +677,15 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
const uint32_t rbc = allocate_prbs_sub(
|
||||
nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]);
|
||||
|
||||
if (nb_rb > ue_sched_ctrl->pre_nb_available_rbs[CC_id]) {
|
||||
LOG_D(MAC,
|
||||
"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n",
|
||||
if (nb_rb > ue_sched_ctrl->pre_nb_available_rbs[CC_id])
|
||||
LOG_W(MAC,
|
||||
"[eNB %d] %d.%d CC_id %d : should not schedule UE %d, its "
|
||||
"retransmission takes more resources than we have\n",
|
||||
module_idP,
|
||||
frameP,
|
||||
subframeP,
|
||||
CC_id,
|
||||
UE_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* CDRX */
|
||||
ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer
|
||||
@@ -799,6 +797,7 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
eNB_UE_stats->rbs_used_retx = nb_rb;
|
||||
eNB_UE_stats->total_rbs_used_retx += nb_rb;
|
||||
eNB_UE_stats->dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1;
|
||||
eNB_UE_stats->TBS = TBS;
|
||||
} else {
|
||||
// Now check RLC information to compute number of required RBs
|
||||
// get maximum TBS size for RLC request
|
||||
@@ -842,13 +841,18 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
if (ue_sched_ctrl->dl_lc_bytes[i] == 0) // no data in this LC!
|
||||
continue;
|
||||
|
||||
LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, LC%d->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
|
||||
const uint32_t data =
|
||||
min(ue_sched_ctrl->dl_lc_bytes[i],
|
||||
TBS - ta_len - header_length_total - sdu_length_total - 3);
|
||||
LOG_D(MAC,
|
||||
"[eNB %d] SFN/SF %d.%d, LC%d->DLSCH CC_id %d, Requesting %d "
|
||||
"bytes from RLC (RRC message)\n",
|
||||
module_idP,
|
||||
frameP,
|
||||
subframeP,
|
||||
lcid,
|
||||
CC_id,
|
||||
TBS - ta_len - header_length_total - sdu_length_total - 3);
|
||||
data);
|
||||
|
||||
sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
|
||||
rnti,
|
||||
@@ -857,7 +861,7 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
ENB_FLAG_YES,
|
||||
MBMS_FLAG_NO,
|
||||
lcid,
|
||||
TBS - ta_len - header_length_total - sdu_length_total - 3,
|
||||
data,
|
||||
(char *)&dlsch_buffer[sdu_length_total],
|
||||
0,
|
||||
0
|
||||
|
||||
@@ -2240,7 +2240,7 @@ void ulsch_scheduler_pre_ue_select_fairRR(
|
||||
uint8_t first_ue_total[MAX_NUM_CCs][20];
|
||||
uint8_t first_ue_id[MAX_NUM_CCs][20];
|
||||
uint8_t ul_inactivity_num[MAX_NUM_CCs];
|
||||
uint8_t ul_inactivity_id[MAX_NUM_CCs][20]={0};
|
||||
uint8_t ul_inactivity_id[MAX_NUM_CCs][20]={{0}};
|
||||
// LTE_DL_FRAME_PARMS *frame_parms;
|
||||
uint8_t ulsch_ue_max_num[MAX_NUM_CCs];
|
||||
uint16_t saved_ulsch_dci[MAX_NUM_CCs];
|
||||
|
||||
@@ -2131,33 +2131,36 @@ dump_ue_list(UE_list_t *listP) {
|
||||
* Add a UE to UE_list listP
|
||||
*/
|
||||
inline void add_ue_list(UE_list_t *listP, int UE_id) {
|
||||
if (listP->head == -1) {
|
||||
listP->head = UE_id;
|
||||
listP->next[UE_id] = -1;
|
||||
} else {
|
||||
int i = listP->head;
|
||||
while (listP->next[i] >= 0)
|
||||
i = listP->next[i];
|
||||
listP->next[i] = UE_id;
|
||||
listP->next[UE_id] = -1;
|
||||
}
|
||||
int *cur = &listP->head;
|
||||
while (*cur >= 0)
|
||||
cur = &listP->next[*cur];
|
||||
*cur = UE_id;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* Remove a UE from the UE_list listP, return the previous element
|
||||
* Remove a UE from the UE_list listP
|
||||
*/
|
||||
inline int remove_ue_list(UE_list_t *listP, int UE_id) {
|
||||
listP->next[UE_id] = -1;
|
||||
if (listP->head == UE_id) {
|
||||
listP->head = listP->next[UE_id];
|
||||
return -1;
|
||||
}
|
||||
int *cur = &listP->head;
|
||||
while (*cur != -1 && *cur != UE_id)
|
||||
cur = &listP->next[*cur];
|
||||
if (*cur == -1)
|
||||
return 0;
|
||||
int *next = &listP->next[*cur];
|
||||
*cur = listP->next[*cur];
|
||||
*next = -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int previous = prev(listP, UE_id);
|
||||
if (previous != -1)
|
||||
listP->next[previous] = listP->next[UE_id];
|
||||
return previous;
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* Initialize the UE_list listP
|
||||
*/
|
||||
inline void init_ue_list(UE_list_t *listP) {
|
||||
listP->head = -1;
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i)
|
||||
listP->next[i] = -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -2196,6 +2199,12 @@ add_new_ue(module_id_t mod_idP,
|
||||
UE_info->active[UE_id] = TRUE;
|
||||
add_ue_list(&UE_info->list, UE_id);
|
||||
dump_ue_list(&UE_info->list);
|
||||
pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl;
|
||||
if (dl->slices) // inform slice implementation about new UE
|
||||
dl->add_UE(dl->slices, UE_id);
|
||||
pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul;
|
||||
if (ul->slices) // inform slice implementation about new UE
|
||||
ul->add_UE(ul->slices, UE_id);
|
||||
if (IS_SOFTMODEM_IQPLAYER)// not specific to record/playback ?
|
||||
UE_info->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0;
|
||||
UE_info->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type;
|
||||
@@ -2259,6 +2268,12 @@ rrc_mac_remove_ue(module_id_t mod_idP,
|
||||
UE_info->num_UEs--;
|
||||
|
||||
remove_ue_list(&UE_info->list, UE_id);
|
||||
pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl;
|
||||
if (dl->slices) // inform slice implementation about new UE
|
||||
dl->remove_UE(dl->slices, UE_id);
|
||||
pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul;
|
||||
if (ul->slices) // inform slice implementation about new UE
|
||||
ul->remove_UE(ul->slices, UE_id);
|
||||
|
||||
/* Clear all remaining pending transmissions */
|
||||
memset(&UE_info->UE_template[pCC_id][UE_id], 0, sizeof(UE_TEMPLATE));
|
||||
|
||||
@@ -1301,11 +1301,11 @@ schedule_ulsch_rnti(module_id_t module_idP,
|
||||
|
||||
/*
|
||||
* ULSCH preprocessor: set UE_template->
|
||||
* pre_allocated_nb_rb_ul[slice_idx]
|
||||
* pre_allocated_nb_rb_ul
|
||||
* pre_assigned_mcs_ul
|
||||
* pre_allocated_rb_table_index_ul
|
||||
*/
|
||||
ulsch_scheduler_pre_processor(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP);
|
||||
mac->pre_processor_ul.ul(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP);
|
||||
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
if (UE_info->UE_template[CC_id][UE_id].rach_resource_type > 0)
|
||||
|
||||
+81
-105
@@ -155,9 +155,6 @@
|
||||
/*!\brief minimum MAC data needed for transmitting 1 min RLC PDU size + 1 byte MAC subHeader */
|
||||
#define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE)
|
||||
|
||||
/*!\brief maximum number of slices / groups */
|
||||
#define MAX_NUM_SLICES 10
|
||||
|
||||
|
||||
#define U_PLANE_INACTIVITY_VALUE 0 /* defined 10ms order (zero means infinity) */
|
||||
|
||||
@@ -543,7 +540,6 @@ typedef enum {
|
||||
SCHED_MODE_FAIR_RR /// fair raund robin
|
||||
} SCHEDULER_MODES;
|
||||
|
||||
|
||||
/*! \brief temporary struct for ULSCH sched */
|
||||
typedef struct {
|
||||
rnti_t rnti;
|
||||
@@ -1150,9 +1146,6 @@ typedef struct {
|
||||
UE_list_t list;
|
||||
int num_UEs;
|
||||
boolean_t active[MAX_MOBILES_PER_ENB];
|
||||
|
||||
/// Sorting criteria for the UE list in the MAC preprocessor
|
||||
uint16_t sorting_criteria[MAX_NUM_SLICES][CR_NUM];
|
||||
} UE_info_t;
|
||||
|
||||
/*! \brief deleting control information*/
|
||||
@@ -1171,101 +1164,6 @@ typedef struct {
|
||||
int tail_freelist; ///the tail position of the delete list
|
||||
} UE_free_list_t;
|
||||
|
||||
/**
|
||||
* slice specific scheduler for the DL
|
||||
*/
|
||||
typedef void (*slice_scheduler_dl)(module_id_t mod_id,
|
||||
int slice_idx,
|
||||
frame_t frame,
|
||||
sub_frame_t subframe,
|
||||
int *mbsfn_flag);
|
||||
|
||||
typedef struct {
|
||||
slice_id_t id;
|
||||
|
||||
/// RB share for each slice
|
||||
float pct;
|
||||
|
||||
/// whether this slice is isolated from the others
|
||||
int isol;
|
||||
|
||||
int prio;
|
||||
|
||||
/// Frequency ranges for slice positioning
|
||||
int pos_low;
|
||||
int pos_high;
|
||||
|
||||
// max mcs for each slice
|
||||
int maxmcs;
|
||||
|
||||
/// criteria for sorting policies of the slices
|
||||
uint32_t sorting;
|
||||
|
||||
/// Accounting policy (just greedy(1) or fair(0) setting for now)
|
||||
int accounting;
|
||||
|
||||
/// name of available scheduler
|
||||
char *sched_name;
|
||||
|
||||
/// pointer to the slice specific scheduler in DL
|
||||
slice_scheduler_dl sched_cb;
|
||||
|
||||
} slice_sched_conf_dl_t;
|
||||
|
||||
typedef void (*slice_scheduler_ul)(module_id_t mod_id,
|
||||
int slice_idx,
|
||||
frame_t frame,
|
||||
sub_frame_t subframe,
|
||||
unsigned char sched_subframe,
|
||||
uint16_t *first_rb);
|
||||
|
||||
typedef struct {
|
||||
slice_id_t id;
|
||||
|
||||
/// RB share for each slice
|
||||
float pct;
|
||||
|
||||
// MAX MCS for each slice
|
||||
int maxmcs;
|
||||
|
||||
/// criteria for sorting policies of the slices
|
||||
uint32_t sorting;
|
||||
|
||||
/// starting RB (RB offset) of UL scheduling
|
||||
int first_rb;
|
||||
|
||||
/// name of available scheduler
|
||||
char *sched_name;
|
||||
|
||||
/// pointer to the slice specific scheduler in UL
|
||||
slice_scheduler_ul sched_cb;
|
||||
|
||||
} slice_sched_conf_ul_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/// counter used to indicate when all slices have pre-allocated UEs
|
||||
//int slice_counter;
|
||||
|
||||
/// indicates whether remaining RBs after first intra-slice allocation will
|
||||
/// be allocated to UEs of the same slice
|
||||
int intraslice_share_active;
|
||||
/// indicates whether remaining RBs after slice allocation will be
|
||||
/// allocated to UEs of another slice. Isolated slices will be ignored
|
||||
int interslice_share_active;
|
||||
|
||||
/// number of active DL slices
|
||||
int n_dl;
|
||||
slice_sched_conf_dl_t dl[MAX_NUM_SLICES];
|
||||
|
||||
/// number of active UL slices
|
||||
int n_ul;
|
||||
slice_sched_conf_ul_t ul[MAX_NUM_SLICES];
|
||||
|
||||
/// common rb allocation list between slices
|
||||
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX];
|
||||
} slice_info_t;
|
||||
|
||||
/**
|
||||
* describes contiguous RBs
|
||||
*/
|
||||
@@ -1274,6 +1172,82 @@ typedef struct {
|
||||
int length;
|
||||
} contig_rbs_t;
|
||||
|
||||
/**
|
||||
* definition of a scheduling algorithm implementation used in the
|
||||
* default DL scheduler
|
||||
*/
|
||||
typedef struct {
|
||||
char *name;
|
||||
void *(*setup)(void);
|
||||
void (*unset)(void **);
|
||||
int (*run)(
|
||||
module_id_t, int, int, int, UE_list_t *, int, int, uint8_t *, void *);
|
||||
void *data;
|
||||
} default_sched_dl_algo_t;
|
||||
|
||||
/**
|
||||
* definition of a scheduling algorithm implementation used in the
|
||||
* default UL scheduler
|
||||
*/
|
||||
typedef struct {
|
||||
char *name;
|
||||
void *(*setup)(void);
|
||||
void (*unset)(void **);
|
||||
int (*run)(
|
||||
module_id_t, int, int, int, int, int, UE_list_t *, int, int, contig_rbs_t *, void *);
|
||||
void *data;
|
||||
} default_sched_ul_algo_t;
|
||||
|
||||
typedef void (*pp_impl_dl)(module_id_t mod_id,
|
||||
int CC_id,
|
||||
frame_t frame,
|
||||
sub_frame_t subframe);
|
||||
typedef void (*pp_impl_ul)(module_id_t mod_id,
|
||||
int CC_id,
|
||||
frame_t frame,
|
||||
sub_frame_t subframe,
|
||||
frame_t sched_frame,
|
||||
sub_frame_t sched_subframe);
|
||||
|
||||
struct slice_info_s;
|
||||
typedef struct {
|
||||
int algorithm;
|
||||
|
||||
/// inform the slice algorithm about a new UE
|
||||
void (*add_UE)(struct slice_info_s *s, int UE_id);
|
||||
/// inform the slice algorithm about a UE that disconnected
|
||||
void (*remove_UE)(struct slice_info_s *s, int UE_id);
|
||||
/// move a UE to a slice in DL/UL, -1 means don't move (no-op).
|
||||
void (*move_UE)(struct slice_info_s *s, int UE_id, int idx);
|
||||
|
||||
/// Adds a new slice through admission control. slice_params are
|
||||
/// algorithm-specific parameters. sched is either a default_sched_ul_algo_t
|
||||
/// or default_sched_dl_algo_t, depending on whether this implementation
|
||||
/// handles UL/DL. If slice at index exists, updates existing
|
||||
/// slice. Returns index of new slice or -1 on failure.
|
||||
int (*addmod_slice)(struct slice_info_s *s,
|
||||
int id,
|
||||
char *label,
|
||||
void *sched,
|
||||
void *slice_params);
|
||||
/// Returns slice through slice_idx. 1 if successful, 0 if not.
|
||||
int (*remove_slice)(struct slice_info_s *s, uint8_t slice_idx);
|
||||
|
||||
union {
|
||||
pp_impl_dl dl;
|
||||
pp_impl_ul ul;
|
||||
};
|
||||
|
||||
union {
|
||||
default_sched_ul_algo_t ul_algo;
|
||||
default_sched_dl_algo_t dl_algo;
|
||||
};
|
||||
|
||||
void (*destroy)(struct slice_info_s **s);
|
||||
|
||||
struct slice_info_s *slices;
|
||||
} pp_impl_param_t;
|
||||
|
||||
/*! \brief eNB common channels */
|
||||
typedef struct {
|
||||
int physCellId;
|
||||
@@ -1395,9 +1369,6 @@ typedef struct eNB_MAC_INST_s {
|
||||
uint32_t ul_handle;
|
||||
UE_info_t UE_info;
|
||||
|
||||
/// slice-related configuration
|
||||
slice_info_t slice_info;
|
||||
|
||||
///subband bitmap configuration
|
||||
SBMAP_CONF sbmap_conf;
|
||||
/// CCE table used to build DCI scheduling information
|
||||
@@ -1432,6 +1403,11 @@ typedef struct eNB_MAC_INST_s {
|
||||
UE_free_list_t UE_free_list;
|
||||
/// for scheduling selection
|
||||
SCHEDULER_MODES scheduler_mode;
|
||||
/// Default scheduler: Pre-processor implementation. Algorithms for UL/DL
|
||||
/// are called by ULSCH/DLSCH, respectively. Pro-processor implementation can
|
||||
/// encapsulate slicing.
|
||||
pp_impl_param_t pre_processor_dl;
|
||||
pp_impl_param_t pre_processor_ul;
|
||||
|
||||
int32_t puSch10xSnr;
|
||||
int32_t puCch10xSnr;
|
||||
|
||||
@@ -187,8 +187,6 @@ void add_msg3(module_id_t module_idP, int CC_id, RA_t *ra, frame_t frameP,
|
||||
|
||||
void init_UE_info(UE_info_t *UE_info);
|
||||
|
||||
void init_slice_info(slice_info_t *sli);
|
||||
|
||||
int mac_top_init(int eMBMS_active, char *uecap_xer,
|
||||
uint8_t cba_group_active, uint8_t HO_active);
|
||||
|
||||
@@ -661,6 +659,7 @@ int prev(UE_list_t *listP, int nodeP);
|
||||
void add_ue_list(UE_list_t *listP, int UE_id);
|
||||
int remove_ue_list(UE_list_t *listP, int UE_id);
|
||||
void dump_ue_list(UE_list_t *listP);
|
||||
void init_ue_list(UE_list_t *listP);
|
||||
int UE_num_active_CC(UE_info_t *listP, int ue_idP);
|
||||
int UE_PCCID(module_id_t mod_idP, int ue_idP);
|
||||
rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP);
|
||||
@@ -675,10 +674,10 @@ void set_ul_DAI(int module_idP,
|
||||
|
||||
void ulsch_scheduler_pre_processor(module_id_t module_idP,
|
||||
int CC_id,
|
||||
int frameP,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframeP,
|
||||
int sched_frameP,
|
||||
unsigned char sched_subframeP);
|
||||
frame_t sched_frameP,
|
||||
sub_frame_t sched_subframeP);
|
||||
|
||||
int phy_stats_exist(module_id_t Mod_id, int rnti);
|
||||
|
||||
|
||||
+17
-31
@@ -45,11 +45,8 @@ extern RAN_CONTEXT_t RC;
|
||||
|
||||
void init_UE_info(UE_info_t *UE_info)
|
||||
{
|
||||
int list_el;
|
||||
UE_info->num_UEs = 0;
|
||||
UE_info->list.head = -1;
|
||||
for (list_el = 0; list_el < MAX_MOBILES_PER_ENB; list_el++)
|
||||
UE_info->list.next[list_el] = -1;
|
||||
init_ue_list(&UE_info->list);
|
||||
memset(UE_info->DLSCH_pdu, 0, sizeof(UE_info->DLSCH_pdu));
|
||||
memset(UE_info->UE_template, 0, sizeof(UE_info->UE_template));
|
||||
memset(UE_info->eNB_UE_stats, 0, sizeof(UE_info->eNB_UE_stats));
|
||||
@@ -57,32 +54,6 @@ void init_UE_info(UE_info_t *UE_info)
|
||||
memset(UE_info->active, 0, sizeof(UE_info->active));
|
||||
}
|
||||
|
||||
void init_slice_info(slice_info_t *sli)
|
||||
{
|
||||
sli->intraslice_share_active = 1;
|
||||
sli->interslice_share_active = 1;
|
||||
|
||||
sli->n_dl = 1;
|
||||
memset(sli->dl, 0, sizeof(slice_sched_conf_dl_t) * MAX_NUM_SLICES);
|
||||
sli->dl[0].pct = 1.0;
|
||||
sli->dl[0].prio = 10;
|
||||
sli->dl[0].pos_high = N_RBG_MAX;
|
||||
sli->dl[0].maxmcs = 28;
|
||||
sli->dl[0].sorting = 0x012345;
|
||||
sli->dl[0].sched_name = "schedule_ue_spec";
|
||||
sli->dl[0].sched_cb = dlsym(NULL, sli->dl[0].sched_name);
|
||||
AssertFatal(sli->dl[0].sched_cb, "DLSCH scheduler callback is NULL\n");
|
||||
|
||||
sli->n_ul = 1;
|
||||
memset(sli->ul, 0, sizeof(slice_sched_conf_ul_t) * MAX_NUM_SLICES);
|
||||
sli->ul[0].pct = 1.0;
|
||||
sli->ul[0].maxmcs = 20;
|
||||
sli->ul[0].sorting = 0x0123;
|
||||
sli->ul[0].sched_name = "schedule_ulsch_rnti";
|
||||
sli->ul[0].sched_cb = dlsym(NULL, sli->ul[0].sched_name);
|
||||
AssertFatal(sli->ul[0].sched_cb, "ULSCH scheduler callback is NULL\n");
|
||||
}
|
||||
|
||||
void mac_top_init_eNB(void)
|
||||
{
|
||||
module_id_t i, j;
|
||||
@@ -129,8 +100,23 @@ void mac_top_init_eNB(void)
|
||||
|
||||
mac[i]->if_inst = IF_Module_init(i);
|
||||
|
||||
mac[i]->pre_processor_dl.algorithm = 0;
|
||||
mac[i]->pre_processor_dl.dl = dlsch_scheduler_pre_processor;
|
||||
char *s = "round_robin_dl";
|
||||
void *d = dlsym(NULL, s);
|
||||
AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s);
|
||||
mac[i]->pre_processor_dl.dl_algo = *(default_sched_dl_algo_t *) d;
|
||||
mac[i]->pre_processor_dl.dl_algo.data = mac[i]->pre_processor_dl.dl_algo.setup();
|
||||
|
||||
mac[i]->pre_processor_ul.algorithm = 0;
|
||||
mac[i]->pre_processor_ul.ul = ulsch_scheduler_pre_processor;
|
||||
s = "round_robin_ul";
|
||||
d = dlsym(NULL, s);
|
||||
AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s);
|
||||
mac[i]->pre_processor_ul.ul_algo = *(default_sched_ul_algo_t *) d;
|
||||
mac[i]->pre_processor_ul.ul_algo.data = mac[i]->pre_processor_ul.ul_algo.setup();
|
||||
|
||||
init_UE_info(&mac[i]->UE_info);
|
||||
init_slice_info(&mac[i]->slice_info);
|
||||
}
|
||||
|
||||
RC.mac = mac;
|
||||
|
||||
+475
-154
@@ -69,31 +69,367 @@ int get_rbg_size_last(module_id_t Mod_id, int CC_id) {
|
||||
return RBGsize;
|
||||
}
|
||||
|
||||
int g_start_ue_dl = -1;
|
||||
int round_robin_dl(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int n_rbg_sched,
|
||||
uint8_t *rbgalloc_mask) {
|
||||
void *rr_dl_setup(void) {
|
||||
void *data = malloc(sizeof(int));
|
||||
*(int *) data = 0;
|
||||
AssertFatal(data, "could not allocate data in %s()\n", __func__);
|
||||
return data;
|
||||
}
|
||||
void rr_dl_unset(void **data) {
|
||||
if (*data)
|
||||
free(*data);
|
||||
*data = NULL;
|
||||
}
|
||||
int rr_dl_run(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int n_rbg_sched,
|
||||
uint8_t *rbgalloc_mask,
|
||||
void *data) {
|
||||
DevAssert(UE_list->head >= 0);
|
||||
DevAssert(n_rbg_sched > 0);
|
||||
const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
const int RBGsize = get_min_rb_unit(Mod_id, CC_id);
|
||||
const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id);
|
||||
int num_ue_req = 0;
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
|
||||
int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request
|
||||
memset(rb_required, 0, sizeof(rb_required));
|
||||
|
||||
int rbg = 0;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++)
|
||||
; /* fast-forward to first allowed RBG */
|
||||
|
||||
// Calculate the amount of RBs every UE wants to send.
|
||||
/* just start with the UE after the one we had last time. If it does not
|
||||
* exist, this will start at the head */
|
||||
int *start_ue = data;
|
||||
*start_ue = next_ue_list_looped(UE_list, *start_ue);
|
||||
|
||||
int UE_id = *start_ue;
|
||||
UE_list_t UE_sched;
|
||||
int *cur_UE = &UE_sched.head;
|
||||
// Allocate retransmissions, and mark UEs with new transmissions
|
||||
do {
|
||||
// check whether there are HARQ retransmissions
|
||||
const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const uint8_t round = ue_ctrl->round[CC_id][harq_pid];
|
||||
if (round != 8) { // retransmission: allocate
|
||||
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
|
||||
if (nb_rb == 0)
|
||||
goto skip_ue;
|
||||
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
|
||||
// needs more RBGs than we can allocate
|
||||
if (nb_rbg > n_rbg_sched) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
|
||||
UE_id, nb_rbg, n_rbg_sched);
|
||||
goto skip_ue;
|
||||
}
|
||||
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
|
||||
// if we allocate the last RBG this one should have the full RBGsize
|
||||
if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched
|
||||
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
|
||||
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
|
||||
goto skip_ue;
|
||||
}
|
||||
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0)
|
||||
goto skip_ue; // cannot allocate CCE
|
||||
ue_ctrl->pre_dci_dl_pdu_idx = idx;
|
||||
// retransmissions: directly allocate
|
||||
n_rbg_sched -= nb_rbg;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
|
||||
for (; nb_rbg > 0; rbg++) {
|
||||
if (!rbgalloc_mask[rbg])
|
||||
continue;
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
nb_rbg--;
|
||||
}
|
||||
LOG_D(MAC,
|
||||
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
|
||||
"round %d retx nb_rb %d pre_nb_available_rbs %d\n",
|
||||
frame, subframe, n_rbg_sched, UE_id, round,
|
||||
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id]);
|
||||
/* if there are no more RBG to give, return */
|
||||
if (n_rbg_sched <= 0)
|
||||
return 0;
|
||||
max_num_ue--;
|
||||
/* if there are no UEs that can be allocated anymore, return */
|
||||
if (max_num_ue == 0)
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
} else {
|
||||
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) {
|
||||
*cur_UE = UE_id;
|
||||
cur_UE = &UE_sched.next[UE_id];
|
||||
}
|
||||
}
|
||||
|
||||
skip_ue:
|
||||
UE_id = next_ue_list_looped(UE_list, UE_id);
|
||||
} while (UE_id != *start_ue);
|
||||
*cur_UE = -1; // mark end
|
||||
|
||||
if (UE_sched.head < 0)
|
||||
return n_rbg_sched; // no UE has a transmission
|
||||
|
||||
// after allocating retransmissions: pre-allocate CCE, compute number of
|
||||
// requested RBGs
|
||||
max_num_ue = min(max_num_ue, n_rbg_sched);
|
||||
int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request
|
||||
cur_UE = &UE_sched.head;
|
||||
while (*cur_UE >= 0 && max_num_ue > 0) {
|
||||
const int UE_id = *cur_UE;
|
||||
cur_UE = &UE_sched.next[UE_id]; // go to next
|
||||
const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0) {
|
||||
LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id);
|
||||
continue;
|
||||
}
|
||||
UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx;
|
||||
const int mcs = cqi_to_mcs[cqi];
|
||||
UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs;
|
||||
const uint32_t B = UE_info->UE_template[CC_id][UE_id].dl_buffer_total;
|
||||
rb_required[UE_id] = find_nb_rb_DL(mcs, B, n_rbg_sched * RBGsize, RBGsize);
|
||||
max_num_ue--;
|
||||
}
|
||||
*cur_UE = -1; // not all UEs might be allocated, mark end
|
||||
|
||||
/* for one UE after the next: allocate resources */
|
||||
cur_UE = &UE_sched.head;
|
||||
while (*cur_UE >= 0) {
|
||||
const int UE_id = *cur_UE;
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG;
|
||||
rb_required[UE_id] -= sRBG;
|
||||
if (rb_required[UE_id] <= 0) {
|
||||
*cur_UE = UE_sched.next[*cur_UE];
|
||||
if (*cur_UE < 0)
|
||||
cur_UE = &UE_sched.head;
|
||||
} else {
|
||||
cur_UE = UE_sched.next[*cur_UE] < 0 ? &UE_sched.head : &UE_sched.next[*cur_UE];
|
||||
}
|
||||
n_rbg_sched--;
|
||||
if (n_rbg_sched <= 0)
|
||||
break;
|
||||
for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
}
|
||||
|
||||
return n_rbg_sched;
|
||||
}
|
||||
default_sched_dl_algo_t round_robin_dl = {
|
||||
.name = "round_robin_dl",
|
||||
.setup = rr_dl_setup,
|
||||
.unset = rr_dl_unset,
|
||||
.run = rr_dl_run,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
|
||||
void *pf_dl_setup(void) {
|
||||
void *data = calloc(MAX_MOBILES_PER_ENB, sizeof(float));
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; i++)
|
||||
*(float *) data = 0.0f;
|
||||
AssertFatal(data, "could not allocate data in %s()\n", __func__);
|
||||
return data;
|
||||
}
|
||||
void pf_dl_unset(void **data) {
|
||||
if (*data)
|
||||
free(*data);
|
||||
*data = NULL;
|
||||
}
|
||||
int pf_wbcqi_dl_run(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int n_rbg_sched,
|
||||
uint8_t *rbgalloc_mask,
|
||||
void *data) {
|
||||
DevAssert(UE_list->head >= 0);
|
||||
DevAssert(n_rbg_sched > 0);
|
||||
const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
const int RBGsize = get_min_rb_unit(Mod_id, CC_id);
|
||||
const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id);
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
|
||||
int rbg = 0;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++)
|
||||
; /* fast-forward to first allowed RBG */
|
||||
|
||||
UE_list_t UE_sched; // UEs that could be scheduled
|
||||
int *uep = &UE_sched.head;
|
||||
float *thr_ue = data;
|
||||
float coeff_ue[MAX_MOBILES_PER_ENB];
|
||||
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
const float a = 0.0005f; // corresponds to 200ms window
|
||||
const uint32_t b = UE_info->eNB_UE_stats[CC_id][UE_id].TBS;
|
||||
thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b;
|
||||
|
||||
// check whether there are HARQ retransmissions
|
||||
const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const uint8_t round = ue_ctrl->round[CC_id][harq_pid];
|
||||
if (round != 8) { // retransmission: allocate
|
||||
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
|
||||
if (nb_rb == 0)
|
||||
continue;
|
||||
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
|
||||
// needs more RBGs than we can allocate
|
||||
if (nb_rbg > n_rbg_sched) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
|
||||
UE_id, nb_rbg, n_rbg_sched);
|
||||
continue;
|
||||
}
|
||||
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
|
||||
// if we allocate the last RBG this one should have the full RBGsize
|
||||
if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched
|
||||
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
|
||||
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
|
||||
continue;
|
||||
}
|
||||
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0)
|
||||
continue; // cannot allocate CCE
|
||||
ue_ctrl->pre_dci_dl_pdu_idx = idx;
|
||||
// retransmissions: directly allocate
|
||||
n_rbg_sched -= nb_rbg;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
|
||||
for (; nb_rbg > 0; rbg++) {
|
||||
if (!rbgalloc_mask[rbg])
|
||||
continue;
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
nb_rbg--;
|
||||
}
|
||||
LOG_D(MAC,
|
||||
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
|
||||
"round %d retx nb_rb %d pre_nb_available_rbs %d\n",
|
||||
frame, subframe, n_rbg_sched, UE_id, round,
|
||||
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id]);
|
||||
/* if there are no more RBG to give, return */
|
||||
if (n_rbg_sched <= 0)
|
||||
return 0;
|
||||
max_num_ue--;
|
||||
/* if there are no UEs that can be allocated anymore, return */
|
||||
if (max_num_ue == 0)
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
} else {
|
||||
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0)
|
||||
continue;
|
||||
|
||||
const int mcs = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]];
|
||||
const uint32_t tbs = get_TBS_DL(mcs, RBGsize);
|
||||
coeff_ue[UE_id] = (float) tbs / thr_ue[UE_id];
|
||||
//LOG_I(MAC, " pf UE %d: old TBS %d thr %f MCS %d TBS %d coeff %f\n",
|
||||
// UE_id, b, thr_ue[UE_id], mcs, tbs, coeff_ue[UE_id]);
|
||||
*uep = UE_id;
|
||||
uep = &UE_sched.next[UE_id];
|
||||
}
|
||||
}
|
||||
*uep = -1;
|
||||
|
||||
while (max_num_ue > 0 && n_rbg_sched > 0 && UE_sched.head >= 0) {
|
||||
int *max = &UE_sched.head; /* assume head is max */
|
||||
int *p = &UE_sched.next[*max];
|
||||
while (*p >= 0) {
|
||||
/* if the current one has larger coeff, save for later */
|
||||
if (coeff_ue[*p] > coeff_ue[*max])
|
||||
max = p;
|
||||
p = &UE_sched.next[*p];
|
||||
}
|
||||
/* remove the max one */
|
||||
const int UE_id = *max;
|
||||
p = &UE_sched.next[*max];
|
||||
*max = UE_sched.next[*max];
|
||||
*p = -1;
|
||||
|
||||
const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0)
|
||||
continue;
|
||||
UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx;
|
||||
|
||||
max_num_ue--;
|
||||
|
||||
/* allocate as much as possible */
|
||||
const int mcs = cqi_to_mcs[cqi];
|
||||
UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs;
|
||||
int req = find_nb_rb_DL(mcs,
|
||||
UE_info->UE_template[CC_id][UE_id].dl_buffer_total,
|
||||
n_rbg_sched * RBGsize,
|
||||
RBGsize);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
while (req > 0 && n_rbg_sched > 0) {
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG;
|
||||
req -= sRBG;
|
||||
n_rbg_sched--;
|
||||
for (rbg++; n_rbg_sched > 0 && !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
}
|
||||
}
|
||||
|
||||
return n_rbg_sched;
|
||||
}
|
||||
default_sched_dl_algo_t proportional_fair_wbcqi_dl = {
|
||||
.name = "proportional_fair_wbcqi_dl",
|
||||
.setup = pf_dl_setup,
|
||||
.unset = pf_dl_unset,
|
||||
.run = pf_wbcqi_dl_run,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
void *mt_dl_setup(void) {
|
||||
return NULL;
|
||||
}
|
||||
void mt_dl_unset(void **data) {
|
||||
*data = NULL;
|
||||
}
|
||||
int mt_wbcqi_dl_run(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int n_rbg_sched,
|
||||
uint8_t *rbgalloc_mask,
|
||||
void *data) {
|
||||
DevAssert(UE_list->head >= 0);
|
||||
DevAssert(n_rbg_sched > 0);
|
||||
const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
const int RBGsize = get_min_rb_unit(Mod_id, CC_id);
|
||||
const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id);
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
|
||||
int rbg = 0;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++)
|
||||
; /* fast-forward to first allowed RBG */
|
||||
|
||||
UE_list_t UE_sched; // UEs that could be scheduled
|
||||
int *uep = &UE_sched.head;
|
||||
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
// check whether there are HARQ retransmissions
|
||||
const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||
@@ -133,6 +469,7 @@ int round_robin_dl(module_id_t Mod_id,
|
||||
if (!rbgalloc_mask[rbg])
|
||||
continue;
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
nb_rbg--;
|
||||
}
|
||||
LOG_D(MAC,
|
||||
@@ -150,90 +487,69 @@ int round_robin_dl(module_id_t Mod_id,
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
} else {
|
||||
const int dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]];
|
||||
UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = dlsch_mcs1;
|
||||
rb_required[UE_id] =
|
||||
find_nb_rb_DL(dlsch_mcs1,
|
||||
UE_info->UE_template[CC_id][UE_id].dl_buffer_total,
|
||||
n_rbg_sched * RBGsize,
|
||||
RBGsize);
|
||||
if (rb_required[UE_id] > 0)
|
||||
num_ue_req++;
|
||||
LOG_D(MAC,
|
||||
"%d/%d UE_id %d rb_required %d n_rbg_sched %d\n",
|
||||
frame,
|
||||
subframe,
|
||||
UE_id,
|
||||
rb_required[UE_id],
|
||||
n_rbg_sched);
|
||||
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0)
|
||||
continue;
|
||||
*uep = UE_id;
|
||||
uep = &UE_sched.next[UE_id];
|
||||
}
|
||||
}
|
||||
*uep = -1;
|
||||
|
||||
if (num_ue_req == 0)
|
||||
return n_rbg_sched; // no UE has a transmission
|
||||
while (max_num_ue > 0 && n_rbg_sched > 0 && UE_sched.head >= 0) {
|
||||
int *max = &UE_sched.head; /* assume head is max */
|
||||
int *p = &UE_sched.next[*max];
|
||||
while (*p >= 0) {
|
||||
/* if the current one has better CQI, or the same and more data */
|
||||
const uint8_t maxCqi = UE_info->UE_sched_ctrl[*max].dl_cqi[CC_id];
|
||||
const uint32_t maxB = UE_info->UE_template[CC_id][*max].dl_buffer_total;
|
||||
const uint8_t pCqi = UE_info->UE_sched_ctrl[*p].dl_cqi[CC_id];
|
||||
const uint32_t pB = UE_info->UE_template[CC_id][*p].dl_buffer_total;
|
||||
if (pCqi > maxCqi || (pCqi == maxCqi && pB > maxB))
|
||||
max = p;
|
||||
p = &UE_sched.next[*p];
|
||||
}
|
||||
/* remove the max one */
|
||||
const int UE_id = *max;
|
||||
p = &UE_sched.next[*max];
|
||||
*max = UE_sched.next[*max];
|
||||
*p = -1;
|
||||
|
||||
// after allocating retransmissions: build list of UE to allocate.
|
||||
// if start_UE does not exist anymore (detach etc), start at first UE
|
||||
if (g_start_ue_dl == -1)
|
||||
g_start_ue_dl = UE_list->head;
|
||||
int UE_id = g_start_ue_dl;
|
||||
UE_list_t UE_sched;
|
||||
int rb_required_total = 0;
|
||||
int num_ue_sched = 0;
|
||||
max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched);
|
||||
int *cur_UE = &UE_sched.head;
|
||||
while (num_ue_sched < max_num_ue) {
|
||||
while (rb_required[UE_id] == 0)
|
||||
UE_id = next_ue_list_looped(UE_list, UE_id);
|
||||
const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0) {
|
||||
LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id);
|
||||
num_ue_req--;
|
||||
max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched);
|
||||
UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate
|
||||
if (idx < 0)
|
||||
continue;
|
||||
}
|
||||
UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx;
|
||||
*cur_UE = UE_id;
|
||||
cur_UE = &UE_sched.next[UE_id];
|
||||
rb_required_total += rb_required[UE_id];
|
||||
num_ue_sched++;
|
||||
UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate
|
||||
}
|
||||
*cur_UE = -1;
|
||||
|
||||
/* for one UE after the next: allocate resources */
|
||||
for (int UE_id = UE_sched.head; UE_id >= 0;
|
||||
UE_id = next_ue_list_looped(&UE_sched, UE_id)) {
|
||||
if (rb_required[UE_id] <= 0)
|
||||
continue;
|
||||
max_num_ue--;
|
||||
|
||||
/* allocate as much as possible */
|
||||
const int mcs = cqi_to_mcs[cqi];
|
||||
UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs;
|
||||
int req = find_nb_rb_DL(mcs,
|
||||
UE_info->UE_template[CC_id][UE_id].dl_buffer_total,
|
||||
n_rbg_sched * RBGsize,
|
||||
RBGsize);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG;
|
||||
rb_required[UE_id] -= sRBG;
|
||||
rb_required_total -= sRBG;
|
||||
if (rb_required_total <= 0)
|
||||
break;
|
||||
n_rbg_sched--;
|
||||
if (n_rbg_sched <= 0)
|
||||
break;
|
||||
for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
}
|
||||
|
||||
/* if not all UEs could be allocated in this round */
|
||||
if (num_ue_req > max_num_ue) {
|
||||
/* go to the first one we missed */
|
||||
for (int i = 0; i < max_num_ue; ++i)
|
||||
g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl);
|
||||
} else {
|
||||
/* else, just start with the next UE next time */
|
||||
g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl);
|
||||
while (req > 0 && n_rbg_sched > 0) {
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG;
|
||||
req -= sRBG;
|
||||
n_rbg_sched--;
|
||||
for (rbg++; n_rbg_sched > 0 && !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
}
|
||||
}
|
||||
|
||||
return n_rbg_sched;
|
||||
}
|
||||
default_sched_dl_algo_t maximum_throughput_wbcqi_dl = {
|
||||
.name = "maximum_throughput_wbcqi_dl",
|
||||
.setup = mt_dl_setup,
|
||||
.unset = mt_dl_unset,
|
||||
.run = mt_wbcqi_dl_run,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
// This function stores the downlink buffer for all the logical channels
|
||||
void
|
||||
@@ -323,19 +639,18 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframeP) {
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
eNB_MAC_INST *mac = RC.mac[Mod_id];
|
||||
UE_info_t *UE_info = &mac->UE_info;
|
||||
const int N_RBG = to_rbg(mac->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
const int RBGsize = get_min_rb_unit(Mod_id, CC_id);
|
||||
|
||||
store_dlsch_buffer(Mod_id, CC_id, frameP, subframeP);
|
||||
|
||||
UE_list_t UE_to_sched;
|
||||
UE_to_sched.head = -1;
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i)
|
||||
UE_to_sched.next[i] = -1;
|
||||
int *cur = &UE_to_sched.head;
|
||||
|
||||
int first = 1;
|
||||
int last_UE_id = -1;
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id];
|
||||
@@ -368,20 +683,15 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
}
|
||||
|
||||
/* define UEs to schedule */
|
||||
if (first) {
|
||||
first = 0;
|
||||
UE_to_sched.head = UE_id;
|
||||
} else {
|
||||
UE_to_sched.next[last_UE_id] = UE_id;
|
||||
}
|
||||
UE_to_sched.next[UE_id] = -1;
|
||||
last_UE_id = UE_id;
|
||||
*cur = UE_id;
|
||||
cur = &UE_to_sched.next[UE_id];
|
||||
}
|
||||
*cur = -1;
|
||||
|
||||
if (UE_to_sched.head < 0)
|
||||
return;
|
||||
|
||||
uint8_t *vrb_map = RC.mac[Mod_id]->common_channels[CC_id].vrb_map;
|
||||
uint8_t *vrb_map = mac->common_channels[CC_id].vrb_map;
|
||||
uint8_t rbgalloc_mask[N_RBG_MAX];
|
||||
int n_rbg_sched = 0;
|
||||
for (int i = 0; i < N_RBG; i++) {
|
||||
@@ -393,14 +703,15 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
n_rbg_sched += rbgalloc_mask[i];
|
||||
}
|
||||
|
||||
round_robin_dl(Mod_id,
|
||||
CC_id,
|
||||
frameP,
|
||||
subframeP,
|
||||
&UE_to_sched,
|
||||
4, // max_num_ue
|
||||
n_rbg_sched,
|
||||
rbgalloc_mask);
|
||||
mac->pre_processor_dl.dl_algo.run(Mod_id,
|
||||
CC_id,
|
||||
frameP,
|
||||
subframeP,
|
||||
&UE_to_sched,
|
||||
4, // max_num_ue
|
||||
n_rbg_sched,
|
||||
rbgalloc_mask,
|
||||
mac->pre_processor_dl.dl_algo.data);
|
||||
|
||||
// the following block is meant for validation of the pre-processor to check
|
||||
// whether all UE allocations are non-overlapping and is not necessary for
|
||||
@@ -512,17 +823,28 @@ int pp_find_rb_table_index(int approximate) {
|
||||
return p + 1;
|
||||
}
|
||||
|
||||
int g_start_ue_ul = -1;
|
||||
int round_robin_ul(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
int sched_frame,
|
||||
int sched_subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int num_contig_rb,
|
||||
contig_rbs_t *rbs) {
|
||||
void *rr_ul_setup(void) {
|
||||
void *data = malloc(sizeof(int));
|
||||
*(int *) data = 0;
|
||||
AssertFatal(data, "could not allocate data in %s()\n", __func__);
|
||||
return data;
|
||||
}
|
||||
void rr_ul_unset(void **data) {
|
||||
if (*data)
|
||||
free(*data);
|
||||
*data = NULL;
|
||||
}
|
||||
int rr_ul_run(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
int sched_frame,
|
||||
int sched_subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int num_contig_rb,
|
||||
contig_rbs_t *rbs,
|
||||
void *data) {
|
||||
AssertFatal(num_contig_rb <= 2, "cannot handle more than two contiguous RB regions\n");
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
const int max_rb = num_contig_rb > 1 ? MAX(rbs[0].length, rbs[1].length) : rbs[0].length;
|
||||
@@ -662,9 +984,10 @@ int round_robin_ul(module_id_t Mod_id,
|
||||
end = la > lb ? 2 : -1;
|
||||
}
|
||||
|
||||
if (g_start_ue_ul == -1)
|
||||
g_start_ue_ul = UE_list->head;
|
||||
int sUE_id = g_start_ue_ul;
|
||||
int *start_ue = data;
|
||||
if (*start_ue == -1)
|
||||
*start_ue = UE_list->head;
|
||||
int sUE_id = *start_ue;
|
||||
int rb_idx_given[MAX_MOBILES_PER_ENB];
|
||||
memset(rb_idx_given, 0, sizeof(rb_idx_given));
|
||||
|
||||
@@ -742,35 +1065,35 @@ int round_robin_ul(module_id_t Mod_id,
|
||||
}
|
||||
}
|
||||
|
||||
/* if not all UEs could be allocated in this round */
|
||||
if (num_ue_req > max_num_ue) {
|
||||
/* go to the first one we missed */
|
||||
for (int i = 0; i < max_num_ue; ++i)
|
||||
g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul);
|
||||
} else {
|
||||
/* else, just start with the next UE next time */
|
||||
g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul);
|
||||
}
|
||||
/* just start with the next UE next time */
|
||||
*start_ue = next_ue_list_looped(UE_list, *start_ue);
|
||||
|
||||
return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0);
|
||||
}
|
||||
default_sched_ul_algo_t round_robin_ul = {
|
||||
.name = "round_robin_ul",
|
||||
.setup = rr_ul_setup,
|
||||
.unset = rr_ul_unset,
|
||||
.run = rr_ul_run,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
void ulsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frameP,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframeP,
|
||||
int sched_frameP,
|
||||
unsigned char sched_subframeP) {
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
const int N_RB_UL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].ul_Bandwidth);
|
||||
COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||
frame_t sched_frameP,
|
||||
sub_frame_t sched_subframeP) {
|
||||
eNB_MAC_INST *mac = RC.mac[Mod_id];
|
||||
UE_info_t *UE_info = &mac->UE_info;
|
||||
const int N_RB_UL = to_prb(mac->common_channels[CC_id].ul_Bandwidth);
|
||||
COMMON_channels_t *cc = &mac->common_channels[CC_id];
|
||||
|
||||
UE_list_t UE_to_sched;
|
||||
UE_to_sched.head = -1;
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i)
|
||||
UE_to_sched.next[i] = -1;
|
||||
int *cur = &UE_to_sched.head;
|
||||
|
||||
int last_UE_id = -1;
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id];
|
||||
UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
@@ -793,13 +1116,10 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
continue;
|
||||
|
||||
/* define UEs to schedule */
|
||||
if (UE_to_sched.head < 0)
|
||||
UE_to_sched.head = UE_id;
|
||||
else
|
||||
UE_to_sched.next[last_UE_id] = UE_id;
|
||||
UE_to_sched.next[UE_id] = -1;
|
||||
last_UE_id = UE_id;
|
||||
*cur = UE_id;
|
||||
cur = &UE_to_sched.next[UE_id];
|
||||
}
|
||||
*cur = -1;
|
||||
|
||||
if (UE_to_sched.head < 0)
|
||||
return;
|
||||
@@ -820,16 +1140,17 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
}
|
||||
}
|
||||
|
||||
round_robin_ul(Mod_id,
|
||||
CC_id,
|
||||
frameP,
|
||||
subframeP,
|
||||
sched_frameP,
|
||||
sched_subframeP,
|
||||
&UE_to_sched,
|
||||
4, // max_num_ue
|
||||
n_contig,
|
||||
rbs);
|
||||
mac->pre_processor_ul.ul_algo.run(Mod_id,
|
||||
CC_id,
|
||||
frameP,
|
||||
subframeP,
|
||||
sched_frameP,
|
||||
sched_subframeP,
|
||||
&UE_to_sched,
|
||||
4, // max_num_ue
|
||||
n_contig,
|
||||
rbs,
|
||||
mac->pre_processor_ul.ul_algo.data);
|
||||
|
||||
// the following block is meant for validation of the pre-processor to check
|
||||
// whether all UE allocations are non-overlapping and is not necessary for
|
||||
@@ -848,7 +1169,7 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
continue;
|
||||
|
||||
print = 1;
|
||||
uint8_t harq_pid = subframe2harqpid(&RC.mac[Mod_id]->common_channels[CC_id],
|
||||
uint8_t harq_pid = subframe2harqpid(&mac->common_channels[CC_id],
|
||||
sched_frameP, sched_subframeP);
|
||||
LOG_D(MAC, "%4d.%d UE%d %d RBs (index %d) at start %d, pre MCS %d %s\n",
|
||||
frameP,
|
||||
|
||||
@@ -0,0 +1,601 @@
|
||||
/*
|
||||
* 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 slicing.c
|
||||
* \brief Generic slicing helper functions and Static Slicing Implementation
|
||||
* \author Robert Schmidt
|
||||
* \date 2020
|
||||
* \email robert.schmidt@eurecom.fr
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "assertions.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
#include "slicing.h"
|
||||
#include "slicing_internal.h"
|
||||
|
||||
#include "common/ran_context.h"
|
||||
extern RAN_CONTEXT_t RC;
|
||||
|
||||
#define RET_FAIL(ret, x...) do { LOG_E(MAC, x); return ret; } while (0)
|
||||
|
||||
int slicing_get_UE_slice_idx(slice_info_t *si, int UE_id) {
|
||||
return si->UE_assoc_slice[UE_id];
|
||||
}
|
||||
|
||||
void slicing_add_UE(slice_info_t *si, int UE_id) {
|
||||
add_ue_list(&si->s[0]->UEs, UE_id);
|
||||
si->UE_assoc_slice[UE_id] = 0;
|
||||
}
|
||||
|
||||
void _remove_UE(slice_t **s, uint8_t *assoc, int UE_id) {
|
||||
const uint8_t i = assoc[UE_id];
|
||||
DevAssert(remove_ue_list(&s[i]->UEs, UE_id));
|
||||
assoc[UE_id] = -1;
|
||||
}
|
||||
|
||||
void slicing_remove_UE(slice_info_t *si, int UE_id) {
|
||||
_remove_UE(si->s, si->UE_assoc_slice, UE_id);
|
||||
}
|
||||
|
||||
void _move_UE(slice_t **s, uint8_t *assoc, int UE_id, int to) {
|
||||
const uint8_t i = assoc[UE_id];
|
||||
const int ri = remove_ue_list(&s[i]->UEs, UE_id);
|
||||
if (!ri)
|
||||
LOG_W(MAC, "did not find UE %d in DL slice index %d\n", UE_id, i);
|
||||
add_ue_list(&s[to]->UEs, UE_id);
|
||||
assoc[UE_id] = to;
|
||||
}
|
||||
|
||||
void slicing_move_UE(slice_info_t *si, int UE_id, int idx) {
|
||||
DevAssert(idx >= -1 && idx < si->num);
|
||||
if (idx >= 0)
|
||||
_move_UE(si->s, si->UE_assoc_slice, UE_id, idx);
|
||||
}
|
||||
|
||||
int _exists_slice(uint8_t n, slice_t **s, int id) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
if (s[i]->id == id)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
slice_t *_add_slice(uint8_t *n, slice_t **s) {
|
||||
s[*n] = calloc(1, sizeof(slice_t));
|
||||
if (!s[*n])
|
||||
return NULL;
|
||||
init_ue_list(&s[*n]->UEs);
|
||||
*n += 1;
|
||||
return s[*n - 1];
|
||||
}
|
||||
|
||||
slice_t *_remove_slice(uint8_t *n, slice_t **s, uint8_t *assoc, int idx) {
|
||||
if (idx >= *n)
|
||||
return NULL;
|
||||
|
||||
slice_t *sr = s[idx];
|
||||
while (sr->UEs.head >= 0)
|
||||
_move_UE(s, assoc, sr->UEs.head, 0);
|
||||
|
||||
for (int i = idx + 1; i < *n; ++i)
|
||||
s[i - 1] = s[i];
|
||||
*n -= 1;
|
||||
s[*n] = NULL;
|
||||
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i)
|
||||
if (assoc[i] > idx)
|
||||
assoc[i] -= 1;
|
||||
|
||||
if (sr->label)
|
||||
free(sr->label);
|
||||
|
||||
return sr;
|
||||
}
|
||||
|
||||
/************************ Static Slicing Implementation ************************/
|
||||
|
||||
int addmod_static_slice_dl(slice_info_t *si,
|
||||
int id,
|
||||
char *label,
|
||||
void *algo,
|
||||
void *slice_params_dl) {
|
||||
static_slice_param_t *dl = slice_params_dl;
|
||||
if (dl && dl->posLow > dl->posHigh)
|
||||
RET_FAIL(-1, "%s(): slice id %d posLow > posHigh\n", __func__, id);
|
||||
|
||||
uint8_t rbgMap[25] = { 0 };
|
||||
int index = _exists_slice(si->num, si->s, id);
|
||||
if (index >= 0) {
|
||||
for (int s = 0; s < si->num; ++s) {
|
||||
static_slice_param_t *sd = dl && si->s[s]->id == id ? dl : si->s[s]->algo_data;
|
||||
for (int i = sd->posLow; i <= sd->posHigh; ++i) {
|
||||
if (rbgMap[i])
|
||||
RET_FAIL(-33, "%s(): overlap of slices detected at RBG %d\n", __func__, i);
|
||||
rbgMap[i] = 1;
|
||||
}
|
||||
}
|
||||
/* no problem, can allocate */
|
||||
slice_t *s = si->s[index];
|
||||
if (label) {
|
||||
if (s->label) free(s->label);
|
||||
s->label = label;
|
||||
}
|
||||
if (algo) {
|
||||
s->dl_algo.unset(&s->dl_algo.data);
|
||||
s->dl_algo = *(default_sched_dl_algo_t *) algo;
|
||||
if (!s->dl_algo.data)
|
||||
s->dl_algo.data = s->dl_algo.setup();
|
||||
}
|
||||
if (dl) {
|
||||
free(s->algo_data);
|
||||
s->algo_data = dl;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
if (!dl)
|
||||
RET_FAIL(-100, "%s(): no parameters for new slice %d, aborting\n", __func__, id);
|
||||
|
||||
if (si->num >= MAX_STATIC_SLICES)
|
||||
RET_FAIL(-2, "%s(): cannot have more than %d slices\n", __func__, MAX_STATIC_SLICES);
|
||||
for (int s = 0; s < si->num; ++s) {
|
||||
static_slice_param_t *sd = si->s[s]->algo_data;
|
||||
for (int i = sd->posLow; i <= sd->posHigh; ++i)
|
||||
rbgMap[i] = 1;
|
||||
}
|
||||
|
||||
for (int i = dl->posLow; i <= dl->posHigh; ++i)
|
||||
if (rbgMap[i])
|
||||
RET_FAIL(-3, "%s(): overlap of slices detected at RBG %d\n", __func__, i);
|
||||
|
||||
if (!algo)
|
||||
RET_FAIL(-14, "%s(): no scheduler algorithm provided\n", __func__);
|
||||
|
||||
slice_t *ns = _add_slice(&si->num, si->s);
|
||||
if (!ns)
|
||||
RET_FAIL(-4, "%s(): could not create new slice\n", __func__);
|
||||
ns->id = id;
|
||||
ns->label = label;
|
||||
ns->dl_algo = *(default_sched_dl_algo_t *) algo;
|
||||
if (!ns->dl_algo.data)
|
||||
ns->dl_algo.data = ns->dl_algo.setup();
|
||||
ns->algo_data = dl;
|
||||
|
||||
return si->num - 1;
|
||||
}
|
||||
|
||||
int addmod_static_slice_ul(slice_info_t *si,
|
||||
int id,
|
||||
char *label,
|
||||
void *algo,
|
||||
void *slice_params_ul) {
|
||||
static_slice_param_t *ul = slice_params_ul;
|
||||
/* Minimum 3RBs, because LTE stack requires this */
|
||||
if (ul && ul->posLow + 2 > ul->posHigh)
|
||||
RET_FAIL(-1, "%s(): slice id %d posLow + 2 > posHigh\n", __func__, id);
|
||||
|
||||
uint8_t rbMap[110] = { 0 };
|
||||
int index = _exists_slice(si->num, si->s, id);
|
||||
if (index >= 0) {
|
||||
for (int s = 0; s < si->num; ++s) {
|
||||
static_slice_param_t *su = ul && si->s[s]->id == id && ul ? ul : si->s[s]->algo_data;
|
||||
for (int i = su->posLow; i <= su->posHigh; ++i) {
|
||||
if (rbMap[i])
|
||||
RET_FAIL(-33, "%s(): overlap of slices detected at RBG %d\n", __func__, i);
|
||||
rbMap[i] = 1;
|
||||
}
|
||||
}
|
||||
/* no problem, can allocate */
|
||||
slice_t *s = si->s[index];
|
||||
if (algo) {
|
||||
s->ul_algo.unset(&s->ul_algo.data);
|
||||
s->ul_algo = *(default_sched_ul_algo_t *) algo;
|
||||
if (!s->ul_algo.data)
|
||||
s->ul_algo.data = s->ul_algo.setup();
|
||||
}
|
||||
if (label) {
|
||||
if (s->label) free(s->label);
|
||||
s->label = label;
|
||||
}
|
||||
if (ul) {
|
||||
free(s->algo_data);
|
||||
s->algo_data = ul;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
if (!ul)
|
||||
RET_FAIL(-100, "%s(): no parameters for new slice %d, aborting\n", __func__, id);
|
||||
|
||||
if (si->num >= MAX_STATIC_SLICES)
|
||||
RET_FAIL(-2, "%s(): cannot have more than %d slices\n", __func__, MAX_STATIC_SLICES);
|
||||
for (int s = 0; s < si->num; ++s) {
|
||||
static_slice_param_t *sd = si->s[s]->algo_data;
|
||||
for (int i = sd->posLow; i <= sd->posHigh; ++i)
|
||||
rbMap[i] = 1;
|
||||
}
|
||||
|
||||
for (int i = ul->posLow; i <= ul->posHigh; ++i)
|
||||
if (rbMap[i])
|
||||
RET_FAIL(-3, "%s(): overlap of slices detected at RBG %d\n", __func__, i);
|
||||
|
||||
if (!algo)
|
||||
RET_FAIL(-14, "%s(): no scheduler algorithm provided\n", __func__);
|
||||
|
||||
slice_t *ns = _add_slice(&si->num, si->s);
|
||||
if (!ns)
|
||||
RET_FAIL(-4, "%s(): could not create new slice\n", __func__);
|
||||
ns->id = id;
|
||||
ns->label = label;
|
||||
ns->ul_algo = *(default_sched_ul_algo_t *) algo;
|
||||
if (!ns->ul_algo.data)
|
||||
ns->ul_algo.data = ns->ul_algo.setup();
|
||||
ns->algo_data = ul;
|
||||
|
||||
return si->num - 1;
|
||||
}
|
||||
|
||||
int remove_static_slice_dl(slice_info_t *si, uint8_t slice_idx) {
|
||||
if (slice_idx == 0)
|
||||
return 0;
|
||||
slice_t *sr = _remove_slice(&si->num, si->s, si->UE_assoc_slice, slice_idx);
|
||||
if (!sr)
|
||||
return 0;
|
||||
free(sr->algo_data);
|
||||
sr->dl_algo.unset(&sr->dl_algo.data);
|
||||
free(sr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int remove_static_slice_ul(slice_info_t *si, uint8_t slice_idx) {
|
||||
if (slice_idx == 0)
|
||||
return 0;
|
||||
slice_t *sr = _remove_slice(&si->num, si->s, si->UE_assoc_slice, slice_idx);
|
||||
if (!sr)
|
||||
return 0;
|
||||
free(sr->algo_data);
|
||||
sr->ul_algo.unset(&sr->ul_algo.data);
|
||||
free(sr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void static_dl(module_id_t mod_id,
|
||||
int CC_id,
|
||||
frame_t frame,
|
||||
sub_frame_t subframe) {
|
||||
UE_info_t *UE_info = &RC.mac[mod_id]->UE_info;
|
||||
|
||||
store_dlsch_buffer(mod_id, CC_id, frame, subframe);
|
||||
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
|
||||
/* initialize per-UE scheduling information */
|
||||
ue_sched_ctrl->pre_nb_available_rbs[CC_id] = 0;
|
||||
ue_sched_ctrl->dl_pow_off[CC_id] = 2;
|
||||
memset(ue_sched_ctrl->rballoc_sub_UE[CC_id], 0, sizeof(ue_sched_ctrl->rballoc_sub_UE[CC_id]));
|
||||
ue_sched_ctrl->pre_dci_dl_pdu_idx = -1;
|
||||
}
|
||||
|
||||
const int N_RBG = to_rbg(RC.mac[mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
const int RBGsize = get_min_rb_unit(mod_id, CC_id);
|
||||
uint8_t *vrb_map = RC.mac[mod_id]->common_channels[CC_id].vrb_map;
|
||||
uint8_t rbgalloc_mask[N_RBG_MAX];
|
||||
for (int i = 0; i < N_RBG; i++) {
|
||||
// calculate mask: init to one + "AND" with vrb_map:
|
||||
// if any RB in vrb_map is blocked (1), the current RBG will be 0
|
||||
rbgalloc_mask[i] = 1;
|
||||
for (int j = 0; j < RBGsize; j++)
|
||||
rbgalloc_mask[i] &= !vrb_map[RBGsize * i + j];
|
||||
}
|
||||
|
||||
slice_info_t *s = RC.mac[mod_id]->pre_processor_dl.slices;
|
||||
int max_num_ue;
|
||||
switch (s->num) {
|
||||
case 1:
|
||||
max_num_ue = 4;
|
||||
break;
|
||||
case 2:
|
||||
max_num_ue = 2;
|
||||
break;
|
||||
default:
|
||||
max_num_ue = 1;
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < s->num; ++i) {
|
||||
if (s->s[i]->UEs.head < 0)
|
||||
continue;
|
||||
uint8_t rbgalloc_slice_mask[N_RBG_MAX];
|
||||
memset(rbgalloc_slice_mask, 0, sizeof(rbgalloc_slice_mask));
|
||||
static_slice_param_t *p = s->s[i]->algo_data;
|
||||
int n_rbg_sched = 0;
|
||||
for (int rbg = p->posLow; rbg <= p->posHigh && rbg <= N_RBG; ++rbg) {
|
||||
rbgalloc_slice_mask[rbg] = rbgalloc_mask[rbg];
|
||||
n_rbg_sched += rbgalloc_mask[rbg];
|
||||
}
|
||||
|
||||
s->s[i]->dl_algo.run(mod_id,
|
||||
CC_id,
|
||||
frame,
|
||||
subframe,
|
||||
&s->s[i]->UEs,
|
||||
max_num_ue, // max_num_ue
|
||||
n_rbg_sched,
|
||||
rbgalloc_slice_mask,
|
||||
s->s[i]->dl_algo.data);
|
||||
}
|
||||
|
||||
// the following block is meant for validation of the pre-processor to check
|
||||
// whether all UE allocations are non-overlapping and is not necessary for
|
||||
// scheduling functionality
|
||||
char t[26] = "_________________________";
|
||||
t[N_RBG] = 0;
|
||||
for (int i = 0; i < N_RBG; i++)
|
||||
for (int j = 0; j < RBGsize; j++)
|
||||
if (vrb_map[RBGsize*i+j] != 0)
|
||||
t[i] = 'x';
|
||||
int print = 0;
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
const UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
|
||||
if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0)
|
||||
continue;
|
||||
|
||||
LOG_D(MAC,
|
||||
"%4d.%d UE%d %d RBs allocated, pre MCS %d\n",
|
||||
frame,
|
||||
subframe,
|
||||
UE_id,
|
||||
ue_sched_ctrl->pre_nb_available_rbs[CC_id],
|
||||
UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1);
|
||||
|
||||
print = 1;
|
||||
|
||||
for (int i = 0; i < N_RBG; i++) {
|
||||
if (!ue_sched_ctrl->rballoc_sub_UE[CC_id][i])
|
||||
continue;
|
||||
for (int j = 0; j < RBGsize; j++) {
|
||||
if (vrb_map[RBGsize*i+j] != 0) {
|
||||
LOG_I(MAC, "%4d.%d DL scheduler allocation list: %s\n", frame, subframe, t);
|
||||
LOG_E(MAC, "%4d.%d: UE %d allocated at locked RB %d/RBG %d\n", frame,
|
||||
subframe, UE_id, RBGsize * i + j, i);
|
||||
}
|
||||
vrb_map[RBGsize*i+j] = 1;
|
||||
}
|
||||
t[i] = '0' + UE_id;
|
||||
}
|
||||
}
|
||||
if (print)
|
||||
LOG_D(MAC, "%4d.%d DL scheduler allocation list: %s\n", frame, subframe, t);
|
||||
}
|
||||
|
||||
void static_ul(module_id_t mod_id,
|
||||
int CC_id,
|
||||
frame_t frame,
|
||||
sub_frame_t subframe,
|
||||
frame_t sched_frame,
|
||||
sub_frame_t sched_subframe) {
|
||||
UE_info_t *UE_info = &RC.mac[mod_id]->UE_info;
|
||||
const int N_RB_UL = to_prb(RC.mac[mod_id]->common_channels[CC_id].ul_Bandwidth);
|
||||
COMMON_channels_t *cc = &RC.mac[mod_id]->common_channels[CC_id];
|
||||
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id];
|
||||
UE_template->pre_assigned_mcs_ul = 0;
|
||||
UE_template->pre_allocated_nb_rb_ul = 0;
|
||||
UE_template->pre_allocated_rb_table_index_ul = -1;
|
||||
UE_template->pre_first_nb_rb_ul = 0;
|
||||
UE_template->pre_dci_ul_pdu_idx = -1;
|
||||
}
|
||||
|
||||
slice_info_t *s = RC.mac[mod_id]->pre_processor_ul.slices;
|
||||
int max_num_ue;
|
||||
switch (s->num) {
|
||||
case 1:
|
||||
max_num_ue = 4;
|
||||
break;
|
||||
case 2:
|
||||
max_num_ue = 2;
|
||||
break;
|
||||
default:
|
||||
max_num_ue = 1;
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < s->num; ++i) {
|
||||
if (s->s[i]->UEs.head < 0)
|
||||
continue;
|
||||
int last_rb_blocked = 1;
|
||||
int n_contig = 0;
|
||||
contig_rbs_t rbs[2]; // up to two contig RBs for PRACH in between
|
||||
static_slice_param_t *p = s->s[i]->algo_data;
|
||||
for (int rb = p->posLow; rb <= p->posHigh && rb < N_RB_UL; ++rb) {
|
||||
if (cc->vrb_map_UL[rb] == 0 && last_rb_blocked) {
|
||||
last_rb_blocked = 0;
|
||||
n_contig++;
|
||||
AssertFatal(n_contig <= 2, "cannot handle more than two contiguous RB regions\n");
|
||||
rbs[n_contig - 1].start = rb;
|
||||
}
|
||||
if (cc->vrb_map_UL[rb] == 1 && !last_rb_blocked) {
|
||||
last_rb_blocked = 1;
|
||||
rbs[n_contig - 1].length = rb - rbs[n_contig - 1].start;
|
||||
}
|
||||
}
|
||||
if (!last_rb_blocked)
|
||||
rbs[n_contig - 1].length = p->posHigh - rbs[n_contig - 1].start + 1;
|
||||
|
||||
s->s[i]->ul_algo.run(mod_id,
|
||||
CC_id,
|
||||
frame,
|
||||
subframe,
|
||||
sched_frame,
|
||||
sched_subframe,
|
||||
&s->s[i]->UEs,
|
||||
max_num_ue, // max_num_ue
|
||||
n_contig,
|
||||
rbs,
|
||||
s->s[i]->ul_algo.data);
|
||||
}
|
||||
|
||||
// the following block is meant for validation of the pre-processor to check
|
||||
// whether all UE allocations are non-overlapping and is not necessary for
|
||||
// scheduling functionality
|
||||
char t[101] = "__________________________________________________"
|
||||
"__________________________________________________";
|
||||
t[N_RB_UL] = 0;
|
||||
for (int j = 0; j < N_RB_UL; j++)
|
||||
if (cc->vrb_map_UL[j] != 0)
|
||||
t[j] = 'x';
|
||||
int print = 0;
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id];
|
||||
if (UE_template->pre_allocated_nb_rb_ul == 0)
|
||||
continue;
|
||||
|
||||
print = 1;
|
||||
uint8_t harq_pid = subframe2harqpid(&RC.mac[mod_id]->common_channels[CC_id],
|
||||
sched_frame, sched_subframe);
|
||||
LOG_D(MAC, "%4d.%d UE%d %d RBs (index %d) at start %d, pre MCS %d %s\n",
|
||||
frame,
|
||||
subframe,
|
||||
UE_id,
|
||||
UE_template->pre_allocated_nb_rb_ul,
|
||||
UE_template->pre_allocated_rb_table_index_ul,
|
||||
UE_template->pre_first_nb_rb_ul,
|
||||
UE_template->pre_assigned_mcs_ul,
|
||||
UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0 ? "(retx)" : "");
|
||||
|
||||
for (int i = 0; i < UE_template->pre_allocated_nb_rb_ul; ++i) {
|
||||
/* only check if this is not a retransmission */
|
||||
if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] == 0
|
||||
&& cc->vrb_map_UL[UE_template->pre_first_nb_rb_ul + i] == 1) {
|
||||
|
||||
LOG_I(MAC, "%4d.%d UL scheduler allocation list: %s\n", frame, subframe, t);
|
||||
LOG_E(MAC,
|
||||
"%4d.%d: UE %d allocated at locked RB %d (is: allocated start "
|
||||
"%d/length %d)\n",
|
||||
frame, subframe, UE_id, UE_template->pre_first_nb_rb_ul + i,
|
||||
UE_template->pre_first_nb_rb_ul,
|
||||
UE_template->pre_allocated_nb_rb_ul);
|
||||
}
|
||||
cc->vrb_map_UL[UE_template->pre_first_nb_rb_ul + i] = 1;
|
||||
t[UE_template->pre_first_nb_rb_ul + i] = UE_id + '0';
|
||||
}
|
||||
}
|
||||
if (print)
|
||||
LOG_D(MAC,
|
||||
"%4d.%d UL scheduler allocation list: %s\n",
|
||||
sched_frame,
|
||||
sched_subframe,
|
||||
t);
|
||||
}
|
||||
|
||||
void static_destroy(slice_info_t **si) {
|
||||
const int n = (*si)->num;
|
||||
(*si)->num = 0;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
slice_t *s = (*si)->s[i];
|
||||
if (s->label)
|
||||
free(s->label);
|
||||
free(s->algo_data);
|
||||
free(s);
|
||||
}
|
||||
free((*si)->s);
|
||||
free(*si);
|
||||
}
|
||||
|
||||
pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id) {
|
||||
slice_info_t *si = calloc(1, sizeof(slice_info_t));
|
||||
DevAssert(si);
|
||||
|
||||
si->num = 0;
|
||||
si->s = calloc(MAX_STATIC_SLICES, sizeof(slice_t));
|
||||
DevAssert(si->s);
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i)
|
||||
si->UE_assoc_slice[i] = -1;
|
||||
|
||||
/* insert default slice, all resources */
|
||||
static_slice_param_t *dlp = malloc(sizeof(static_slice_param_t));
|
||||
dlp->posLow = 0;
|
||||
dlp->posHigh = to_rbg(RC.mac[mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth) - 1;
|
||||
default_sched_dl_algo_t *algo = &RC.mac[mod_id]->pre_processor_dl.dl_algo;
|
||||
algo->data = NULL;
|
||||
DevAssert(0 == addmod_static_slice_dl(si, 0, strdup("default"), algo, dlp));
|
||||
const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list;
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id])
|
||||
slicing_add_UE(si, UE_id);
|
||||
|
||||
pp_impl_param_t sttc;
|
||||
sttc.algorithm = STATIC_SLICING;
|
||||
sttc.add_UE = slicing_add_UE;
|
||||
sttc.remove_UE = slicing_remove_UE;
|
||||
sttc.move_UE = slicing_move_UE;
|
||||
sttc.addmod_slice = addmod_static_slice_dl;
|
||||
sttc.remove_slice = remove_static_slice_dl;
|
||||
sttc.dl = static_dl;
|
||||
// current DL algo becomes default scheduler
|
||||
sttc.dl_algo = *algo;
|
||||
sttc.destroy = static_destroy;
|
||||
sttc.slices = si;
|
||||
|
||||
return sttc;
|
||||
}
|
||||
|
||||
pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id) {
|
||||
slice_info_t *si = calloc(1, sizeof(slice_info_t));
|
||||
DevAssert(si);
|
||||
|
||||
si->num = 0;
|
||||
si->s = calloc(MAX_STATIC_SLICES, sizeof(slice_t));
|
||||
DevAssert(si->s);
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i)
|
||||
si->UE_assoc_slice[i] = -1;
|
||||
|
||||
/* insert default slice, all resources */
|
||||
static_slice_param_t *ulp = malloc(sizeof(static_slice_param_t));
|
||||
ulp->posLow = 0;
|
||||
ulp->posHigh = to_prb(RC.mac[mod_id]->common_channels[CC_id].ul_Bandwidth) - 1;
|
||||
default_sched_ul_algo_t *algo = &RC.mac[mod_id]->pre_processor_ul.ul_algo;
|
||||
algo->data = NULL;
|
||||
DevAssert(0 == addmod_static_slice_ul(si, 0, strdup("default"), algo, ulp));
|
||||
const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list;
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id])
|
||||
slicing_add_UE(si, UE_id);
|
||||
|
||||
pp_impl_param_t sttc;
|
||||
sttc.algorithm = STATIC_SLICING;
|
||||
sttc.add_UE = slicing_add_UE;
|
||||
sttc.remove_UE = slicing_remove_UE;
|
||||
sttc.move_UE = slicing_move_UE;
|
||||
sttc.addmod_slice = addmod_static_slice_ul;
|
||||
sttc.remove_slice = remove_static_slice_ul;
|
||||
sttc.ul = static_ul;
|
||||
// current DL algo becomes default scheduler
|
||||
sttc.ul_algo = *algo;
|
||||
sttc.destroy = static_destroy;
|
||||
sttc.slices = si;
|
||||
|
||||
return sttc;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file slicing.h
|
||||
* \brief General slice definition and helper parameters
|
||||
* \author Robert Schmidt
|
||||
* \date 2020
|
||||
* \email robert.schmidt@eurecom.fr
|
||||
*/
|
||||
|
||||
#ifndef __SLICING_H__
|
||||
#define __SLICING_H__
|
||||
|
||||
#include "openair2/LAYER2/MAC/mac.h"
|
||||
|
||||
typedef struct slice_s {
|
||||
/// Arbitrary ID
|
||||
slice_id_t id;
|
||||
/// Arbitrary label
|
||||
char *label;
|
||||
|
||||
union {
|
||||
default_sched_dl_algo_t dl_algo;
|
||||
default_sched_ul_algo_t ul_algo;
|
||||
};
|
||||
|
||||
/// A specific algorithm's implementation parameters
|
||||
void *algo_data;
|
||||
/// Internal data that might be kept alongside a slice's params
|
||||
void *int_data;
|
||||
|
||||
// list of users in this slice
|
||||
UE_list_t UEs;
|
||||
} slice_t;
|
||||
|
||||
typedef struct slice_info_s {
|
||||
uint8_t num;
|
||||
slice_t **s;
|
||||
uint8_t UE_assoc_slice[MAX_MOBILES_PER_ENB];
|
||||
} slice_info_t;
|
||||
|
||||
int slicing_get_UE_slice_idx(slice_info_t *si, int UE_id);
|
||||
|
||||
#define STATIC_SLICING 10
|
||||
/* only four static slices for UL, DL resp. (not enough DCIs) */
|
||||
#define MAX_STATIC_SLICES 4
|
||||
typedef struct {
|
||||
uint16_t posLow;
|
||||
uint16_t posHigh;
|
||||
} static_slice_param_t;
|
||||
pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id);
|
||||
pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id);
|
||||
|
||||
|
||||
#endif /* __SLICING_H__ */
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 slicing_internal.h
|
||||
* \brief Internal slice helper functions
|
||||
* \author Robert Schmidt
|
||||
* \date 2020
|
||||
* \email robert.schmidt@eurecom.fr
|
||||
*/
|
||||
|
||||
#ifndef __SLICING_INTERNAL_H__
|
||||
#define __SLICING_INTERNAL_H__
|
||||
|
||||
#include "slicing.h"
|
||||
|
||||
void slicing_add_UE(slice_info_t *si, int UE_id);
|
||||
|
||||
void _remove_UE(slice_t **s, uint8_t *assoc, int UE_id);
|
||||
void slicing_remove_UE(slice_info_t *si, int UE_id);
|
||||
|
||||
void _move_UE(slice_t **s, uint8_t *assoc, int UE_id, int to);
|
||||
void slicing_move_UE(slice_info_t *si, int UE_id, int idx);
|
||||
|
||||
slice_t *_add_slice(uint8_t *n, slice_t **s);
|
||||
slice_t *_remove_slice(uint8_t *n, slice_t **s, uint8_t *assoc, int idx);
|
||||
|
||||
#endif /* __SLICING_INTERNAL_H__ */
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "NR_MAC_UE/mac_proto.h"
|
||||
#include "NR_MAC-CellGroupConfig.h"
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "SCHED_NR/phy_frame_config_nr.h"
|
||||
|
||||
int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg,
|
||||
int mu,
|
||||
@@ -326,6 +325,84 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
}
|
||||
|
||||
/** \brief This function is relavant for the UE procedures for control. It loads the search spaces, the BWPs and the CORESETs into the MAC instance and
|
||||
\brief performs assert checks on the relevant RRC configuration.
|
||||
@param NR_UE_MAC_INST_t mac: pointer to local MAC instance
|
||||
@returns void
|
||||
*/
|
||||
void config_control_ue(NR_UE_MAC_INST_t *mac){
|
||||
|
||||
uint8_t bwp_id = 1, coreset_id = 1, ss_id;
|
||||
NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated;
|
||||
AssertFatal(scd->downlinkBWP_ToAddModList != NULL, "downlinkBWP_ToAddModList is null\n");
|
||||
AssertFatal(scd->downlinkBWP_ToAddModList->list.count == 1, "downlinkBWP_ToAddModList->list->count is %d\n", scd->downlinkBWP_ToAddModList->list.count);
|
||||
|
||||
NR_BWP_DownlinkCommon_t *bwp_Common = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Common;
|
||||
AssertFatal(bwp_Common != NULL, "bwp_Common is null\n");
|
||||
|
||||
NR_BWP_DownlinkDedicated_t *dl_bwp_Dedicated = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Dedicated;
|
||||
AssertFatal(dl_bwp_Dedicated != NULL, "dl_bwp_Dedicated is null\n");
|
||||
|
||||
NR_SetupRelease_PDCCH_Config_t *pdcch_Config = dl_bwp_Dedicated->pdcch_Config;
|
||||
AssertFatal(pdcch_Config != NULL, "pdcch_Config is null\n");
|
||||
|
||||
NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon;
|
||||
AssertFatal(pdcch_ConfigCommon != NULL, "pdcch_ConfigCommon is null\n");
|
||||
AssertFatal(pdcch_ConfigCommon->choice.setup->ra_SearchSpace != NULL, "ra_SearchSpace must be available in DL BWP\n");
|
||||
|
||||
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
|
||||
AssertFatal(commonSearchSpaceList != NULL, "commonSearchSpaceList is null\n");
|
||||
AssertFatal(commonSearchSpaceList->list.count > 0, "PDCCH CSS list has 0 elements\n");
|
||||
|
||||
struct NR_PDCCH_Config__controlResourceSetToAddModList *controlResourceSetToAddModList = pdcch_Config->choice.setup->controlResourceSetToAddModList;
|
||||
AssertFatal(controlResourceSetToAddModList != NULL, "controlResourceSetToAddModList is null\n");
|
||||
AssertFatal(controlResourceSetToAddModList->list.count == 1, "controlResourceSetToAddModList->list.count=%d\n", controlResourceSetToAddModList->list.count);
|
||||
AssertFatal(controlResourceSetToAddModList->list.array[0] != NULL, "coreset[0][0] is null\n");
|
||||
|
||||
struct NR_PDCCH_Config__searchSpacesToAddModList *searchSpacesToAddModList = pdcch_Config->choice.setup->searchSpacesToAddModList;
|
||||
AssertFatal(searchSpacesToAddModList != NULL, "searchSpacesToAddModList is null\n");
|
||||
AssertFatal(searchSpacesToAddModList->list.count > 0, "list of UE specifically configured Search Spaces is empty\n");
|
||||
AssertFatal(searchSpacesToAddModList->list.count < FAPI_NR_MAX_SS_PER_CORESET, "too many searchpaces per coreset %d\n", searchSpacesToAddModList->list.count);
|
||||
|
||||
struct NR_UplinkConfig__uplinkBWP_ToAddModList *uplinkBWP_ToAddModList = scd->uplinkConfig->uplinkBWP_ToAddModList;
|
||||
AssertFatal(uplinkBWP_ToAddModList != NULL, "uplinkBWP_ToAddModList is null\n");
|
||||
AssertFatal(uplinkBWP_ToAddModList->list.count == 1, "uplinkBWP_ToAddModList->list->count is %d\n", uplinkBWP_ToAddModList->list.count);
|
||||
|
||||
// check pdcch_Config, pdcch_ConfigCommon and DL BWP
|
||||
mac->DLbwp[0] = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1];
|
||||
mac->coreset[bwp_id - 1][coreset_id - 1] = controlResourceSetToAddModList->list.array[0];
|
||||
|
||||
// Check dedicated UL BWP and pass to MAC
|
||||
mac->ULbwp[0] = uplinkBWP_ToAddModList->list.array[0];
|
||||
AssertFatal(mac->ULbwp[0]->bwp_Dedicated != NULL, "UL bwp_Dedicated is null\n");
|
||||
|
||||
// check available Search Spaces in the searchSpacesToAddModList and pass to MAC
|
||||
// note: the network configures at most 10 Search Spaces per BWP per cell (including UE-specific and common Search Spaces).
|
||||
for (ss_id = 0; ss_id < searchSpacesToAddModList->list.count; ss_id++) {
|
||||
NR_SearchSpace_t *ss = searchSpacesToAddModList->list.array[ss_id];
|
||||
AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n");
|
||||
AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n");
|
||||
AssertFatal(*ss->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n");
|
||||
AssertFatal(ss->monitoringSymbolsWithinSlot != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot is null\n");
|
||||
AssertFatal(ss->monitoringSymbolsWithinSlot->buf != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot->buf is null\n");
|
||||
mac->SSpace[0][0][ss_id] = ss;
|
||||
}
|
||||
|
||||
// Check available CSSs in the commonSearchSpaceList (list of additional common search spaces)
|
||||
// note: commonSearchSpaceList SIZE(1..4)
|
||||
for (int css_id = 0; css_id < commonSearchSpaceList->list.count; css_id++) {
|
||||
NR_SearchSpace_t *css = commonSearchSpaceList->list.array[css_id];
|
||||
AssertFatal(css->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n");
|
||||
AssertFatal(*css->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n");
|
||||
AssertFatal(css->searchSpaceId != 0, "css->searchSpaceId is 0\n");
|
||||
AssertFatal(css->searchSpaceType != NULL, "css->searchSpaceType is null\n");
|
||||
AssertFatal(css->monitoringSymbolsWithinSlot != NULL, "css->monitoringSymbolsWithinSlot is null\n");
|
||||
AssertFatal(css->monitoringSymbolsWithinSlot->buf != NULL, "css->monitoringSymbolsWithinSlot->buf is null\n");
|
||||
mac->SSpace[0][0][ss_id] = css;
|
||||
ss_id++;
|
||||
}
|
||||
}
|
||||
|
||||
int nr_rrc_mac_config_req_ue(
|
||||
module_id_t module_id,
|
||||
int cc_idP,
|
||||
@@ -338,16 +415,16 @@ int nr_rrc_mac_config_req_ue(
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
// NR_ServingCellConfig_t *serving_cell_config = spcell_configP->spCellConfigDedicated;
|
||||
// TODO do something FAPI-like P5 L1/L2 config interface in config_si, config_mib, etc.
|
||||
|
||||
|
||||
if(mibP != NULL){
|
||||
mac->mib = mibP; // update by every reception
|
||||
}
|
||||
|
||||
if(cell_group_config != NULL ){
|
||||
mac->scg = cell_group_config;
|
||||
mac->servCellIndex = *cell_group_config->spCellConfig->servCellIndex;
|
||||
config_control_ue(mac);
|
||||
if (cell_group_config->spCellConfig->reconfigurationWithSync) {
|
||||
mac->rach_ConfigDedicated = cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink;
|
||||
mac->scc = cell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
|
||||
@@ -355,7 +432,6 @@ int nr_rrc_mac_config_req_ue(
|
||||
mac->crnti = cell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity;
|
||||
LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti);
|
||||
}
|
||||
mac->scg = cell_group_config;
|
||||
|
||||
/*
|
||||
if(mac_cell_group_configP != NULL){
|
||||
@@ -420,8 +496,8 @@ int nr_rrc_mac_config_req_ue(
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -178,7 +178,6 @@ typedef struct {
|
||||
SFN_C_TYPE type0_pdcch_ss_sfn_c;
|
||||
uint32_t type0_pdcch_ss_n_c;
|
||||
uint32_t type0_pdcch_consecutive_slots;
|
||||
int rnti_type;
|
||||
|
||||
/* PDUs */
|
||||
/// Outgoing CCCH pdu for PHY
|
||||
@@ -222,11 +221,6 @@ typedef struct {
|
||||
uint32_t RA_tx_frame;
|
||||
/// Random-access variable for window calculation (subframe of last change in window counter)
|
||||
uint8_t RA_tx_subframe;
|
||||
/// Scheduled RX frame for RA Msg2
|
||||
uint16_t msg2_rx_frame;
|
||||
/// Scheduled RX slot for RA Msg2
|
||||
uint16_t msg2_rx_slot;
|
||||
/// Random-access Group B maximum path-loss
|
||||
/// Random-access variable for backoff (frame of last change in backoff counter)
|
||||
uint32_t RA_backoff_frame;
|
||||
/// Random-access variable for backoff (subframe of last change in backoff counter)
|
||||
|
||||
@@ -62,9 +62,8 @@
|
||||
#include "NR_MAC_COMMON/nr_mac.h"
|
||||
#include "LAYER2/NR_MAC_UE/mac_proto.h"
|
||||
|
||||
extern int64_t table_6_3_3_2_2_prachConfig_Index [256][9];
|
||||
extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9];
|
||||
extern const uint16_t nr_slots_per_frame[5];
|
||||
extern const uint8_t nr_slots_per_frame[5];
|
||||
|
||||
//extern uint8_t nfapi_mode;
|
||||
|
||||
@@ -360,11 +359,11 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
|
||||
uint8_t sdu_lcids[NB_RB_MAX] = {0};
|
||||
uint16_t sdu_lengths[NB_RB_MAX] = {0};
|
||||
int TBS_bytes = 848, header_length_total, num_sdus, offset, preambleTransMax, mac_ce_len;
|
||||
int TBS_bytes = 848, header_length_total=0, num_sdus, offset, preambleTransMax, mac_ce_len;
|
||||
|
||||
AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n");
|
||||
|
||||
if (UE_mode == PRACH && prach_resources->init_msg1) {
|
||||
if (UE_mode < PUSCH && prach_resources->init_msg1) {
|
||||
|
||||
LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active);
|
||||
|
||||
@@ -449,7 +448,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
nr_get_RA_window(mac);
|
||||
|
||||
// Fill in preamble and PRACH resources
|
||||
if (mac->generate_nr_prach)
|
||||
if (mac->generate_nr_prach == 1)
|
||||
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, rach_ConfigDedicated);
|
||||
|
||||
offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer
|
||||
@@ -471,7 +470,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
payload[offset + j] = 0; // mac_pdu[offset + j] = 0;
|
||||
}
|
||||
}
|
||||
} else { // RACH is active
|
||||
} else if (mac->RA_window_cnt != -1) { // RACH is active
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/////* Random Access Response reception (5.1.4 TS 38.321) */////
|
||||
@@ -482,7 +481,6 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
// - handle beam failure recovery request
|
||||
// - handle DL assignment on PDCCH for RA-RNTI
|
||||
// - handle backoff and raResponseWindow params
|
||||
// - disabled contention resolution as OAI NSA is contention-free based
|
||||
|
||||
// LOG_D(MAC, "[MAC][UE %d][RAPROC] frame %d, subframe %d: RA Active, window cnt %d (RA_tx_frame %d, RA_tx_subframe %d)\n",
|
||||
// mod_id, frame, nr_tti_tx, mac->RA_window_cnt, mac->RA_tx_frame, mac->RA_tx_subframe);
|
||||
@@ -495,12 +493,13 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
|
||||
if (mac->RA_window_cnt >= 0 && mac->RA_RAPID_found == 1) {
|
||||
|
||||
// mac->ra_state = WAIT_CONTENTION_RESOLUTION;
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR successfully received \n", mod_id, frame, nr_tti_tx);
|
||||
mac->RA_window_cnt = -1;
|
||||
mac->ra_state = RA_SUCCEEDED;
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR successfully received \n", mod_id, frame, nr_tti_tx);
|
||||
|
||||
} else if (mac->RA_window_cnt == 0 && !mac->RA_RAPID_found) {
|
||||
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR reception failed \n", mod_id, frame, nr_tti_tx);
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR reception failed \n", mod_id, frame, nr_tti_tx);
|
||||
|
||||
mac->ra_state = RA_UE_IDLE;
|
||||
mac->RA_PREAMBLE_TRANSMISSION_COUNTER++;
|
||||
@@ -572,21 +571,21 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
// mac->RA_tx_subframe = nr_tti_tx;
|
||||
|
||||
// Fill in preamble and PRACH resources
|
||||
if (mac->generate_nr_prach)
|
||||
if (mac->generate_nr_prach == 1)
|
||||
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated);
|
||||
|
||||
} else {
|
||||
|
||||
mac->RA_window_cnt--;
|
||||
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR reception not successful, (RA window count %d) \n",
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR reception not successful, (RA window count %d) \n",
|
||||
mod_id,
|
||||
frame,
|
||||
nr_tti_tx,
|
||||
mac->RA_window_cnt);
|
||||
|
||||
// Fill in preamble and PRACH resources
|
||||
if (mac->generate_nr_prach)
|
||||
if (mac->generate_nr_prach == 1)
|
||||
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated);
|
||||
|
||||
}
|
||||
@@ -616,28 +615,28 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac){
|
||||
mac->RA_window_cnt = mac->RA_offset*nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB
|
||||
|
||||
switch (ra_ResponseWindow) {
|
||||
case 0:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
|
||||
mac->RA_window_cnt += 1;
|
||||
break;
|
||||
case 1:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2:
|
||||
mac->RA_window_cnt += 2;
|
||||
break;
|
||||
case 2:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4:
|
||||
mac->RA_window_cnt += 4;
|
||||
break;
|
||||
case 3:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8:
|
||||
mac->RA_window_cnt += 8;
|
||||
break;
|
||||
case 4:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10:
|
||||
mac->RA_window_cnt += 10;
|
||||
break;
|
||||
case 5:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20:
|
||||
mac->RA_window_cnt += 20;
|
||||
break;
|
||||
case 6:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40:
|
||||
mac->RA_window_cnt += 40;
|
||||
break;
|
||||
case 7:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80:
|
||||
mac->RA_window_cnt += 80;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#endif
|
||||
#define LOG_DCI_PARM(a...) LOG_D(PHY,"\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci)" a)
|
||||
|
||||
// #define DEBUG_DCI
|
||||
|
||||
dci_pdu_rel15_t *def_dci_pdu_rel15;
|
||||
|
||||
void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) {
|
||||
@@ -62,217 +64,261 @@ void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pd
|
||||
|
||||
}
|
||||
|
||||
void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, fapi_nr_dl_config_request_t *dl_config, int rnti_type, int ss_id, uint8_t dci_format){
|
||||
|
||||
uint16_t monitoringSymbolsWithinSlot;
|
||||
uint8_t bwp_id = 1, coreset_id = 1;
|
||||
int sps;
|
||||
def_dci_pdu_rel15 = calloc(1,sizeof(dci_pdu_rel15_t));
|
||||
AssertFatal(mac->scc != NULL, "scc is null\n");
|
||||
NR_ServingCellConfigCommon_t *scc = mac->scc;
|
||||
NR_BWP_DownlinkCommon_t *bwp_Common = mac->DLbwp[bwp_id - 1]->bwp_Common;
|
||||
NR_BWP_DownlinkCommon_t *initialDownlinkBWP = scc->downlinkConfigCommon->initialDownlinkBWP;
|
||||
NR_SearchSpace_t *ss = mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id];
|
||||
|
||||
// DCI format configuration
|
||||
rel15->dci_format = dci_format;
|
||||
|
||||
// CORESET configuration
|
||||
NR_ControlResourceSet_t *coreset = mac->coreset[bwp_id - 1][coreset_id - 1];
|
||||
rel15->coreset.duration = coreset->duration;
|
||||
for (int i = 0; i < 6; i++)
|
||||
rel15->coreset.frequency_domain_resource[i] = coreset->frequencyDomainResources.buf[i];
|
||||
rel15->coreset.CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved ? FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED : FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED;
|
||||
if (rel15->coreset.CceRegMappingType == FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED) {
|
||||
struct NR_ControlResourceSet__cce_REG_MappingType__interleaved *interleaved = coreset->cce_REG_MappingType.choice.interleaved;
|
||||
rel15->coreset.RegBundleSize = (interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2 + interleaved->reg_BundleSize);
|
||||
rel15->coreset.InterleaverSize = (interleaved->interleaverSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2 + interleaved->interleaverSize);
|
||||
AssertFatal(scc->physCellId != NULL, "mac->scc->physCellId is null\n");
|
||||
rel15->coreset.ShiftIndex = interleaved->shiftIndex != NULL ? *interleaved->shiftIndex : *scc->physCellId;
|
||||
} else {
|
||||
rel15->coreset.RegBundleSize = 0;
|
||||
rel15->coreset.InterleaverSize = 0;
|
||||
rel15->coreset.ShiftIndex = 0;
|
||||
}
|
||||
rel15->coreset.CoreSetType = 1;
|
||||
rel15->coreset.precoder_granularity = coreset->precoderGranularity;
|
||||
|
||||
// Scrambling RNTI
|
||||
if (coreset->pdcch_DMRS_ScramblingID) {
|
||||
rel15->coreset.pdcch_dmrs_scrambling_id = *coreset->pdcch_DMRS_ScramblingID;
|
||||
rel15->coreset.scrambling_rnti = mac->t_crnti;
|
||||
} else {
|
||||
rel15->coreset.pdcch_dmrs_scrambling_id = *scc->physCellId;
|
||||
rel15->coreset.scrambling_rnti = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DCI
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure DCI PDU: ss_id %d bwp %p bwp_Id %d controlResourceSetId %d\n", ss_id, mac->DLbwp[bwp_id - 1], mac->DLbwp[bwp_id - 1]->bwp_Id, coreset->controlResourceSetId);
|
||||
#endif
|
||||
|
||||
// loop over RNTI type and configure resource allocation for DCI
|
||||
switch(rnti_type) {
|
||||
case NR_RNTI_C:
|
||||
// we use DL BWP dedicated
|
||||
sps = bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12;
|
||||
// for SPS=14 8 MSBs in positions 13 down to 6
|
||||
monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps));
|
||||
rel15->rnti = mac->crnti;
|
||||
rel15->BWPSize = NRRIV2BW(bwp_Common->genericParameters.locationAndBandwidth, 275);
|
||||
rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275);
|
||||
rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing;
|
||||
rel15->dci_length = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format, NR_RNTI_C, rel15->BWPSize, bwp_id);
|
||||
break;
|
||||
case NR_RNTI_RA:
|
||||
// we use the initial DL BWP
|
||||
sps = initialDownlinkBWP->genericParameters.cyclicPrefix == NULL ? 14 : 12;
|
||||
monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps));
|
||||
rel15->rnti = mac->ra_rnti;
|
||||
rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275);
|
||||
rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); //NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275);
|
||||
rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing;
|
||||
rel15->dci_length = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format, NR_RNTI_RA, rel15->BWPSize, bwp_id);
|
||||
break;
|
||||
case NR_RNTI_P:
|
||||
break;
|
||||
case NR_RNTI_CS:
|
||||
break;
|
||||
case NR_RNTI_TC:
|
||||
break;
|
||||
case NR_RNTI_SP_CSI:
|
||||
break;
|
||||
case NR_RNTI_SI:
|
||||
break;
|
||||
case NR_RNTI_SFI:
|
||||
break;
|
||||
case NR_RNTI_INT:
|
||||
break;
|
||||
case NR_RNTI_TPC_PUSCH:
|
||||
break;
|
||||
case NR_RNTI_TPC_PUCCH:
|
||||
break;
|
||||
case NR_RNTI_TPC_SRS:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < sps; i++) {
|
||||
if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) {
|
||||
rel15->coreset.StartSymbolIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_DCI
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure DCI PDU: rnti_type %d BWPSize %d BWPStart %d rel15->SubcarrierSpacing %d rel15->dci_format %d rel15->dci_length %d sps %d monitoringSymbolsWithinSlot %d \n",
|
||||
rnti_type,
|
||||
rel15->BWPSize,
|
||||
rel15->BWPStart,
|
||||
rel15->SubcarrierSpacing,
|
||||
rel15->dci_format,
|
||||
rel15->dci_length,
|
||||
sps,
|
||||
monitoringSymbolsWithinSlot);
|
||||
#endif
|
||||
// add DCI
|
||||
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI;
|
||||
dl_config->number_pdus = dl_config->number_pdus + 1;
|
||||
}
|
||||
|
||||
void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, frame_t frame, int slot) {
|
||||
|
||||
def_dci_pdu_rel15 = calloc(1,sizeof(dci_pdu_rel15_t));
|
||||
|
||||
NR_BWP_Downlink_t *bwp;
|
||||
NR_BWP_DownlinkCommon_t *bwp_Common;
|
||||
NR_BWP_DownlinkDedicated_t *dl_bwp_Dedicated;
|
||||
NR_SetupRelease_PDCCH_Config_t *pdcch_Config;
|
||||
NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon;
|
||||
struct NR_PDCCH_Config__controlResourceSetToAddModList *controlResourceSetToAddModList;
|
||||
struct NR_PDCCH_Config__searchSpacesToAddModList *searchSpacesToAddModList;
|
||||
struct NR_UplinkConfig__uplinkBWP_ToAddModList *uplinkBWP_ToAddModList;
|
||||
NR_SearchSpace_t *NR_SearchSpace;
|
||||
NR_ControlResourceSet_t *coreset;
|
||||
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15;
|
||||
int ss_id;
|
||||
uint8_t bwp_id = 1, coreset_id = 1;
|
||||
NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated;
|
||||
NR_BWP_Downlink_t *bwp = mac->DLbwp[bwp_id - 1];
|
||||
|
||||
uint8_t bwp_id = 1;
|
||||
int ss_id, sps;
|
||||
#ifdef DEBUG_DCI
|
||||
LOG_D(MAC, "[DCI_CONFIG] ra_rnti %p (%x) crnti %p (%x) t_crnti %p (%x)\n", &mac->ra_rnti, mac->ra_rnti, &mac->crnti, mac->crnti, &mac->t_crnti, mac->t_crnti);
|
||||
#endif
|
||||
|
||||
// get PDCCH configuration(s) (Coreset, SearchSpace, etc...) from BWP Dedicated in serving cell config dedicated (scd)
|
||||
// get BWP 1, Coreset ID 0, SearchSpace ID 0 (i.e. configured in MIB and in ServingCellConfigCommon)
|
||||
// loop over all available SS for BWP ID 1, CORESET ID 1
|
||||
for (ss_id = 0; ss_id < FAPI_NR_MAX_SS_PER_CORESET && mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id] != NULL; ss_id++){
|
||||
NR_SearchSpace_t *ss = mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id];
|
||||
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15;
|
||||
NR_BWP_DownlinkCommon_t *bwp_Common = bwp->bwp_Common;
|
||||
NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon;
|
||||
struct NR_PhysicalCellGroupConfig *phy_cgc = mac->scg->physicalCellGroupConfig;
|
||||
switch (ss->searchSpaceType->present){
|
||||
case NR_SearchSpace__searchSpaceType_PR_common:
|
||||
// this is for CSSs, we use BWP common and pdcch_ConfigCommon
|
||||
|
||||
// Check dedicated DL BWP
|
||||
if (mac->DLbwp[0] == NULL) {
|
||||
NR_SearchSpace_t *ss;
|
||||
int ss_id = 0;
|
||||
|
||||
AssertFatal(scd->downlinkBWP_ToAddModList != NULL, "downlinkBWP_ToAddModList is null\n");
|
||||
AssertFatal(scd->downlinkBWP_ToAddModList->list.count == 1, "downlinkBWP_ToAddModList->list->count is %d\n", scd->downlinkBWP_ToAddModList->list.count);
|
||||
mac->DLbwp[0] = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1];
|
||||
|
||||
dl_bwp_Dedicated = mac->DLbwp[0]->bwp_Dedicated;
|
||||
AssertFatal(dl_bwp_Dedicated != NULL, "dl_bwp_Dedicated is null\n");
|
||||
|
||||
bwp_Common = mac->DLbwp[0]->bwp_Common;
|
||||
AssertFatal(bwp_Common != NULL, "bwp_Common is null\n");
|
||||
|
||||
pdcch_Config = dl_bwp_Dedicated->pdcch_Config;
|
||||
AssertFatal(pdcch_Config != NULL, "pdcch_Config is null\n");
|
||||
|
||||
pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon;
|
||||
AssertFatal(pdcch_ConfigCommon != NULL, "pdcch_ConfigCommon is null\n");
|
||||
AssertFatal(pdcch_ConfigCommon->choice.setup->ra_SearchSpace != NULL, "ra_SearchSpace must be available in DL BWP\n");
|
||||
|
||||
controlResourceSetToAddModList = pdcch_Config->choice.setup->controlResourceSetToAddModList;
|
||||
AssertFatal(controlResourceSetToAddModList != NULL, "controlResourceSetToAddModList is null\n");
|
||||
|
||||
AssertFatal(controlResourceSetToAddModList->list.count == 1, "controlResourceSetToAddModList->list.count=%d\n", controlResourceSetToAddModList->list.count);
|
||||
|
||||
mac->coreset[0][0] = controlResourceSetToAddModList->list.array[0];
|
||||
coreset = mac->coreset[0][0];
|
||||
AssertFatal(coreset != NULL, "coreset[0][0] is null\n");
|
||||
|
||||
searchSpacesToAddModList = pdcch_Config->choice.setup->searchSpacesToAddModList;
|
||||
AssertFatal(searchSpacesToAddModList != NULL, "searchSpacesToAddModList is null\n");
|
||||
AssertFatal(searchSpacesToAddModList->list.count > 0, "searchSpacesToAddModList is empty\n");
|
||||
AssertFatal(searchSpacesToAddModList->list.count < FAPI_NR_MAX_SS_PER_CORESET, "too many searchpaces per coreset %d\n", searchSpacesToAddModList->list.count);
|
||||
|
||||
for (int i = 0; i < searchSpacesToAddModList->list.count; i++) {
|
||||
ss = searchSpacesToAddModList->list.array[i];
|
||||
AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n");
|
||||
AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n");
|
||||
AssertFatal(*ss->controlResourceSetId == coreset->controlResourceSetId, "ss->controlResourceSetId is unknown\n");
|
||||
mac->SSpace[0][0][ss_id] = ss;
|
||||
ss_id++;
|
||||
}
|
||||
}
|
||||
|
||||
// Check dedicated UL BWP
|
||||
if (mac->ULbwp[0] == NULL) {
|
||||
uplinkBWP_ToAddModList = scd->uplinkConfig->uplinkBWP_ToAddModList;
|
||||
AssertFatal(uplinkBWP_ToAddModList != NULL, "uplinkBWP_ToAddModList is null\n");
|
||||
AssertFatal(uplinkBWP_ToAddModList->list.count == 1, "uplinkBWP_ToAddModList->list->count is %d\n", uplinkBWP_ToAddModList->list.count);
|
||||
mac->ULbwp[0] = uplinkBWP_ToAddModList->list.array[bwp_id - 1];
|
||||
AssertFatal(mac->ULbwp[0]->bwp_Dedicated != NULL, "UL bwp_Dedicated is null\n");
|
||||
}
|
||||
|
||||
bwp = mac->DLbwp[0];
|
||||
bwp_Common = bwp->bwp_Common;
|
||||
pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon;
|
||||
dl_bwp_Dedicated = bwp->bwp_Dedicated;
|
||||
pdcch_Config = dl_bwp_Dedicated->pdcch_Config;
|
||||
searchSpacesToAddModList = pdcch_Config->choice.setup->searchSpacesToAddModList;
|
||||
|
||||
// check USSs
|
||||
ss_id = 0;
|
||||
NR_SearchSpace = mac->SSpace[0][0][ss_id];
|
||||
while(NR_SearchSpace != NULL && ss_id < searchSpacesToAddModList->list.count) {
|
||||
AssertFatal(NR_SearchSpace->monitoringSymbolsWithinSlot != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot is null\n");
|
||||
AssertFatal(NR_SearchSpace->monitoringSymbolsWithinSlot->buf != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot->buf is null\n");
|
||||
ss_id++;
|
||||
}
|
||||
|
||||
if (mac->crnti > 0) {
|
||||
|
||||
NR_SearchSpace_t *css;
|
||||
NR_SearchSpace_t *uss = NULL;
|
||||
NR_ServingCellConfigCommon_t *scc;
|
||||
NR_SearchSpaceId_t ra_SearchSpaceId;
|
||||
rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15;
|
||||
uint16_t monitoringSymbolsWithinSlot;
|
||||
uint8_t add_dci = 1;
|
||||
|
||||
AssertFatal(mac->scc != NULL, "scc is null\n");
|
||||
|
||||
scc = mac->scc;
|
||||
rel15->dci_format = NR_DL_DCI_FORMAT_1_1;
|
||||
|
||||
// CoReSet configuration
|
||||
coreset = mac->coreset[0][0];
|
||||
rel15->coreset.duration = coreset->duration;
|
||||
for (int i = 0; i < 6; i++)
|
||||
rel15->coreset.frequency_domain_resource[i] = coreset->frequencyDomainResources.buf[i];
|
||||
|
||||
rel15->coreset.CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved ? FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED : FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED;
|
||||
|
||||
if (rel15->coreset.CceRegMappingType == FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED) {
|
||||
struct NR_ControlResourceSet__cce_REG_MappingType__interleaved *interleaved = coreset->cce_REG_MappingType.choice.interleaved;
|
||||
rel15->coreset.RegBundleSize = (interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2 + interleaved->reg_BundleSize);
|
||||
rel15->coreset.InterleaverSize = (interleaved->interleaverSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2 + interleaved->interleaverSize);
|
||||
AssertFatal(scc->physCellId != NULL, "mac->scc->physCellId is null\n");
|
||||
rel15->coreset.ShiftIndex = interleaved->shiftIndex != NULL ? *interleaved->shiftIndex : *scc->physCellId;
|
||||
} else {
|
||||
rel15->coreset.RegBundleSize = 0;
|
||||
rel15->coreset.InterleaverSize = 0;
|
||||
rel15->coreset.ShiftIndex = 0;
|
||||
}
|
||||
|
||||
rel15->coreset.CoreSetType = 1;
|
||||
rel15->coreset.precoder_granularity = coreset->precoderGranularity;
|
||||
|
||||
if (mac->ra_state == WAIT_RAR){
|
||||
|
||||
NR_BWP_DownlinkCommon_t *initialDownlinkBWP = scc->downlinkConfigCommon->initialDownlinkBWP;
|
||||
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
|
||||
AssertFatal(commonSearchSpaceList->list.count > 0, "PDCCH CSS list has 0 elements\n");
|
||||
|
||||
ra_SearchSpaceId = *pdcch_ConfigCommon->choice.setup->ra_SearchSpace;
|
||||
|
||||
// fetch the CSS for RA from the CSS list
|
||||
for (int i = 0; i < commonSearchSpaceList->list.count; i++) {
|
||||
css = commonSearchSpaceList->list.array[i];
|
||||
if(css->searchSpaceId == ra_SearchSpaceId)
|
||||
break;
|
||||
}
|
||||
|
||||
// check CSSs
|
||||
if(css != NULL) {
|
||||
AssertFatal(css->monitoringSymbolsWithinSlot != NULL, "css->monitoringSymbolsWithinSlot is null\n");
|
||||
AssertFatal(css->monitoringSymbolsWithinSlot->buf != NULL, "css->monitoringSymbolsWithinSlot->buf is null\n");
|
||||
}
|
||||
|
||||
if (frame == mac->msg2_rx_frame && slot == mac->msg2_rx_slot){
|
||||
sps = initialDownlinkBWP->genericParameters.cyclicPrefix == NULL ? 14 : 12;
|
||||
monitoringSymbolsWithinSlot = (css->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (css->monitoringSymbolsWithinSlot->buf[1]>>(16-sps));
|
||||
rel15->rnti = mac->ra_rnti;
|
||||
rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275);
|
||||
rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); // NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275);
|
||||
rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing;
|
||||
rel15->dci_length = nr_dci_size(scc,mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id);
|
||||
for (int i = 0; i < sps; i++)
|
||||
if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) {
|
||||
rel15->coreset.StartSymbolIndex = i;
|
||||
break;
|
||||
}
|
||||
fill_dci_search_candidates(css, rel15);
|
||||
} else {
|
||||
add_dci = 0;
|
||||
// Fetch configuration for searchSpaceZero
|
||||
// note: The search space with the SearchSpaceId = 0 identifies the search space configured via PBCH (MIB) and in ServingCellConfigCommon (searchSpaceZero).
|
||||
if (pdcch_ConfigCommon->choice.setup->searchSpaceZero){
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure SearchSpace#0 of the initial BWP\n");
|
||||
LOG_W(MAC, "[DCI_CONFIG] This should not be available yet...");
|
||||
}
|
||||
} else if (mac->ra_state == WAIT_CONTENTION_RESOLUTION){
|
||||
|
||||
rel15->rnti = mac->t_crnti;
|
||||
|
||||
} else {
|
||||
|
||||
rel15->rnti = mac->crnti;
|
||||
rel15->BWPSize = NRRIV2BW(bwp_Common->genericParameters.locationAndBandwidth, 275);
|
||||
rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275);
|
||||
rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing;
|
||||
rel15->dci_length = nr_dci_size(scc,mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id);
|
||||
// get UE-specific search space
|
||||
for (ss_id = 0; ss_id < FAPI_NR_MAX_SS_PER_CORESET && mac->SSpace[0][0][ss_id] != NULL; ss_id++){
|
||||
uss = mac->SSpace[0][0][ss_id];
|
||||
if (uss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) break;
|
||||
}
|
||||
AssertFatal(ss_id < FAPI_NR_MAX_SS_PER_CORESET, "couldn't find a UE-specific SS\n");
|
||||
sps = bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12;
|
||||
// for SPS=14 8 MSBs in positions 13 down to 6
|
||||
monitoringSymbolsWithinSlot = (uss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (uss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps));
|
||||
for (int i = 0; i < sps; i++)
|
||||
if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) {
|
||||
rel15->coreset.StartSymbolIndex = i;
|
||||
break;
|
||||
if (ss->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0){
|
||||
// check available SS IDs
|
||||
if (pdcch_ConfigCommon->choice.setup->ra_SearchSpace){
|
||||
if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->ra_SearchSpace){
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type1-PDCCH common random access search space\n");
|
||||
switch(mac->ra_state){
|
||||
case WAIT_RAR:
|
||||
config_dci_pdu(mac, rel15, dl_config, NR_RNTI_RA, ss_id, NR_DL_DCI_FORMAT_1_0);
|
||||
fill_dci_search_candidates(ss, rel15);
|
||||
break;
|
||||
case WAIT_CONTENTION_RESOLUTION:
|
||||
rel15->rnti = mac->t_crnti;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fill_dci_search_candidates(uss, rel15);
|
||||
}
|
||||
if (pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){
|
||||
if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){
|
||||
// Configure monitoring of PDCCH candidates in Type0-PDCCH common search space on the MCG
|
||||
LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet...");
|
||||
}
|
||||
}
|
||||
if (pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation){
|
||||
if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation){
|
||||
// Configure monitoring of PDCCH candidates in Type0-PDCCH common search space on the MCG
|
||||
LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet...");
|
||||
}
|
||||
}
|
||||
if (pdcch_ConfigCommon->choice.setup->pagingSearchSpace){
|
||||
if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->pagingSearchSpace){
|
||||
// Configure monitoring of PDCCH candidates in Type2-PDCCH common search space on the MCG
|
||||
LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet...");
|
||||
}
|
||||
}
|
||||
if (phy_cgc){
|
||||
if (phy_cgc->cs_RNTI){
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by CS-RNTI...\n");
|
||||
LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet...");
|
||||
}
|
||||
if (phy_cgc->ext1){
|
||||
if (phy_cgc->ext1->mcs_C_RNTI){
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by MCS-C-RNTI...\n");
|
||||
LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet...");
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end DCI 00 and 01
|
||||
// DCI 2_0
|
||||
if (ss->searchSpaceType->choice.common->dci_Format2_0){
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_0 with CRC scrambled by SFI-RNTI \n");
|
||||
LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet...");
|
||||
}
|
||||
// DCI 2_1
|
||||
if (ss->searchSpaceType->choice.common->dci_Format2_1){
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_1 with CRC scrambled by INT-RNTI \n");
|
||||
LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet...");
|
||||
}
|
||||
// DCI 2_2
|
||||
if (ss->searchSpaceType->choice.common->dci_Format2_2){
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_2 with CRC scrambled by TPC-RNTI \n");
|
||||
LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet...");
|
||||
}
|
||||
// DCI 2_3
|
||||
if (ss->searchSpaceType->choice.common->dci_Format2_3){
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_3 with CRC scrambled by TPC-SRS-RNTI \n");
|
||||
LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet...");
|
||||
}
|
||||
|
||||
// Scrambling RNTI
|
||||
if (coreset->pdcch_DMRS_ScramblingID) {
|
||||
rel15->coreset.pdcch_dmrs_scrambling_id = *coreset->pdcch_DMRS_ScramblingID;
|
||||
rel15->coreset.scrambling_rnti = mac->t_crnti;
|
||||
} else {
|
||||
rel15->coreset.pdcch_dmrs_scrambling_id = *scc->physCellId;
|
||||
rel15->coreset.scrambling_rnti = 0;
|
||||
}
|
||||
break;
|
||||
case NR_SearchSpace__searchSpaceType_PR_ue_Specific:
|
||||
// this is an USS
|
||||
if (ss->searchSpaceType->choice.ue_Specific){
|
||||
if(ss->searchSpaceType->choice.ue_Specific->dci_Formats == NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_1_And_1_1){
|
||||
// Monitors DCI 01 and 11 scrambled with C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI
|
||||
if (get_softmodem_params()->phy_test == 1 && mac->crnti > 0) {
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in the user specific search space\n");
|
||||
config_dci_pdu(mac, rel15, dl_config, NR_RNTI_C, ss_id, NR_DL_DCI_FORMAT_1_1);
|
||||
fill_dci_search_candidates(ss, rel15);
|
||||
|
||||
if (add_dci){
|
||||
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI;
|
||||
dl_config->number_pdus = dl_config->number_pdus + 1;
|
||||
#ifdef DEBUG_DCI
|
||||
LOG_D(MAC, "[DCI_CONFIG] ss %d ue_Specific %p searchSpaceType->present %d dci_Formats %d\n",
|
||||
ss_id,
|
||||
ss->searchSpaceType->choice.ue_Specific,
|
||||
ss->searchSpaceType->present,
|
||||
ss->searchSpaceType->choice.ue_Specific->dci_Formats);
|
||||
#endif
|
||||
}
|
||||
if (phy_cgc){
|
||||
if (phy_cgc->cs_RNTI){
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by CS-RNTI...\n");
|
||||
LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet...");
|
||||
}
|
||||
if (phy_cgc->sp_CSI_RNTI){
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by SP-CSI-RNTI...\n");
|
||||
LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet...");
|
||||
}
|
||||
if (phy_cgc->ext1){
|
||||
if (phy_cgc->ext1->mcs_C_RNTI){
|
||||
LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by MCS-C-RNTI...\n");
|
||||
LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet...");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "[DCI_CONFIG] Unrecognized search space type...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,193 +757,183 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
|
||||
}
|
||||
*/
|
||||
}
|
||||
} else if (ul_info && ul_info->slot_tx == 8) {
|
||||
module_id_t mod_id = ul_info->module_id;
|
||||
uint32_t gNB_index = ul_info->gNB_index;
|
||||
int cc_id = ul_info->cc_id;
|
||||
frame_t rx_frame = ul_info->frame_rx;
|
||||
slot_t rx_slot = ul_info->slot_rx;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
} else if (ul_info) {
|
||||
|
||||
// program PUSCH. this should actually be done upon reception of an UL DCI
|
||||
nr_dcireq_t dcireq;
|
||||
nr_scheduled_response_t scheduled_response;
|
||||
if (get_softmodem_params()->phy_test && ul_info->slot_tx == 8) { // ULSCH is handled only in phy-test mode (consistently with OAI gNB)
|
||||
|
||||
//--------------------------Temporary configuration-----------------------------//
|
||||
uint16_t rnti = 0x1234;
|
||||
uint32_t rb_size = 50;
|
||||
uint32_t rb_start = 0;
|
||||
uint8_t nr_of_symbols = 11;
|
||||
uint8_t start_symbol_index = 0;
|
||||
uint8_t nrOfLayers = 1;
|
||||
uint8_t mcs_index = 9;
|
||||
uint8_t mcs_table = 0;
|
||||
uint8_t harq_process_id = 0;
|
||||
uint8_t rv_index = 0;
|
||||
uint16_t l_prime_mask = get_l_prime(nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1);
|
||||
uint8_t dmrs_config_type = 0;
|
||||
uint8_t ptrs_mcs1 = 2;
|
||||
uint8_t ptrs_mcs2 = 4;
|
||||
uint8_t ptrs_mcs3 = 10;
|
||||
uint16_t n_rb0 = 25;
|
||||
uint16_t n_rb1 = 75;
|
||||
uint16_t pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA;
|
||||
uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, mcs_index, mcs_table);
|
||||
uint8_t ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, rb_size);
|
||||
//------------------------------------------------------------------------------//
|
||||
uint8_t nb_dmrs_re_per_rb;
|
||||
uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES];
|
||||
uint8_t data_existing = 0;
|
||||
uint16_t TBS_bytes;
|
||||
uint32_t TBS;
|
||||
int i;
|
||||
|
||||
dcireq.module_id = mod_id;
|
||||
dcireq.gNB_index = gNB_index;
|
||||
dcireq.cc_id = cc_id;
|
||||
dcireq.frame = rx_frame;
|
||||
dcireq.slot = rx_slot;
|
||||
module_id_t mod_id = ul_info->module_id;
|
||||
uint32_t gNB_index = ul_info->gNB_index;
|
||||
int cc_id = ul_info->cc_id;
|
||||
frame_t rx_frame = ul_info->frame_rx;
|
||||
slot_t rx_slot = ul_info->slot_rx;
|
||||
frame_t frame_tx = ul_info->frame_tx;
|
||||
slot_t slot_tx = ul_info->slot_tx;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
uint8_t access_mode = SCHEDULED_ACCESS;
|
||||
|
||||
scheduled_response.dl_config = NULL;
|
||||
scheduled_response.ul_config = &dcireq.ul_config_req;
|
||||
scheduled_response.tx_request = NULL;
|
||||
scheduled_response.module_id = mod_id;
|
||||
scheduled_response.CC_id = cc_id;
|
||||
scheduled_response.frame = rx_frame;
|
||||
scheduled_response.slot = rx_slot;
|
||||
// program PUSCH. this should actually be done upon reception of an UL DCI
|
||||
nr_dcireq_t dcireq;
|
||||
nr_scheduled_response_t scheduled_response;
|
||||
fapi_nr_tx_request_t tx_req;
|
||||
fapi_nr_tx_request_body_t tx_req_body;
|
||||
|
||||
scheduled_response.ul_config->slot = ul_info->slot_tx;
|
||||
scheduled_response.ul_config->number_pdus = 1;
|
||||
scheduled_response.ul_config->ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rnti = rnti;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_size = rb_size;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_start = rb_start;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nr_of_symbols = nr_of_symbols;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.start_symbol_index = start_symbol_index;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.ul_dmrs_symb_pos = l_prime_mask << start_symbol_index;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.dmrs_config_type = dmrs_config_type;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_index = mcs_index;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_table = mcs_table;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = 1;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = 0;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = rv_index;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nrOfLayers = nrOfLayers;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.harq_process_id = harq_process_id;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map = pdu_bit_map;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list = (nfapi_nr_ue_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ue_ptrs_ports_t));
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0;
|
||||
//--------------------------Temporary configuration-----------------------------//
|
||||
uint16_t rnti = 0x1234;
|
||||
uint32_t rb_size = 50;
|
||||
uint32_t rb_start = 0;
|
||||
uint8_t nr_of_symbols = 11;
|
||||
uint8_t start_symbol_index = 0;
|
||||
uint8_t nrOfLayers = 1;
|
||||
uint8_t mcs_index = 9;
|
||||
uint8_t mcs_table = 0;
|
||||
uint8_t harq_process_id = 0;
|
||||
uint8_t rv_index = 0;
|
||||
uint16_t l_prime_mask = get_l_prime(nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1);
|
||||
uint8_t dmrs_config_type = 0;
|
||||
uint8_t ptrs_mcs1 = 2;
|
||||
uint8_t ptrs_mcs2 = 4;
|
||||
uint8_t ptrs_mcs3 = 10;
|
||||
uint16_t n_rb0 = 25;
|
||||
uint16_t n_rb1 = 75;
|
||||
uint16_t pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA;
|
||||
uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, mcs_index, mcs_table);
|
||||
uint8_t ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, rb_size);
|
||||
uint8_t no_data_in_dmrs = 1;
|
||||
uint16_t number_dmrs_symbols = 0;
|
||||
uint16_t ul_dmrs_symb_pos = l_prime_mask << start_symbol_index;
|
||||
//------------------------------------------------------------------------------//
|
||||
|
||||
if (1 << ptrs_time_density >= nr_of_symbols) {
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS
|
||||
for (i = start_symbol_index; i < start_symbol_index + nr_of_symbols; i++) {
|
||||
if((ul_dmrs_symb_pos >> i) & 0x01)
|
||||
number_dmrs_symbols += 1;
|
||||
}
|
||||
|
||||
if(no_data_in_dmrs)
|
||||
nb_dmrs_re_per_rb = 12;
|
||||
else
|
||||
nb_dmrs_re_per_rb = ((dmrs_config_type == pusch_dmrs_type1) ? 6:4);
|
||||
|
||||
TBS = nr_compute_tbs(nr_get_Qm_ul(mcs_index, 0),
|
||||
nr_get_code_rate_ul(mcs_index, 0),
|
||||
rb_size,
|
||||
nr_of_symbols,
|
||||
nb_dmrs_re_per_rb*number_dmrs_symbols,
|
||||
0,
|
||||
0,
|
||||
nrOfLayers);
|
||||
TBS_bytes = TBS/8;
|
||||
|
||||
if (IS_SOFTMODEM_NOS1){
|
||||
// Getting IP traffic to be transmitted
|
||||
data_existing = nr_ue_get_sdu(mod_id,
|
||||
cc_id,
|
||||
frame_tx,
|
||||
slot_tx,
|
||||
0,
|
||||
ulsch_input_buffer,
|
||||
TBS_bytes,
|
||||
&access_mode);
|
||||
}
|
||||
|
||||
//Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity
|
||||
if (!IS_SOFTMODEM_NOS1 || !data_existing) {
|
||||
//Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid
|
||||
//and block this traffic from being forwarded to the upper layers at the gNB
|
||||
LOG_D(PHY, "Random data to be tranmsitted: \n");
|
||||
|
||||
//Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2)
|
||||
//in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should
|
||||
//have a valid LCID (nr_process_mac_pdu function)
|
||||
ulsch_input_buffer[0] = 0x31;
|
||||
|
||||
for (i = 1; i < TBS_bytes; i++) {
|
||||
ulsch_input_buffer[i] = (unsigned char) rand();
|
||||
//printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MAC_PDU
|
||||
|
||||
LOG_D(PHY, "Is data existing ?: %d \n", data_existing);
|
||||
LOG_I(PHY, "Printing MAC PDU to be encoded, TBS is: %d \n", TBS_bytes);
|
||||
for (i = 0; i < TBS_bytes; i++) {
|
||||
printf("%02x", ulsch_input_buffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
#endif
|
||||
|
||||
dcireq.module_id = mod_id;
|
||||
dcireq.gNB_index = gNB_index;
|
||||
dcireq.cc_id = cc_id;
|
||||
dcireq.frame = rx_frame;
|
||||
dcireq.slot = rx_slot;
|
||||
|
||||
scheduled_response.dl_config = NULL;
|
||||
scheduled_response.ul_config = &dcireq.ul_config_req;
|
||||
// Config UL TX PDU
|
||||
tx_req.slot = slot_tx;
|
||||
tx_req.sfn = frame_tx;
|
||||
// tx_req->tx_config // TbD
|
||||
tx_req.number_of_pdus = 1;
|
||||
tx_req_body.pdu_length = TBS_bytes;
|
||||
tx_req_body.pdu_index = 0;
|
||||
tx_req_body.pdu = ulsch_input_buffer;
|
||||
|
||||
scheduled_response.tx_request = &tx_req;
|
||||
scheduled_response.tx_request->tx_request_body = &tx_req_body;
|
||||
scheduled_response.module_id = mod_id;
|
||||
scheduled_response.CC_id = cc_id;
|
||||
scheduled_response.frame = rx_frame;
|
||||
scheduled_response.slot = rx_slot;
|
||||
|
||||
scheduled_response.ul_config->slot = ul_info->slot_tx;
|
||||
scheduled_response.ul_config->number_pdus = 1;
|
||||
scheduled_response.ul_config->ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rnti = rnti;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_size = rb_size;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_start = rb_start;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nr_of_symbols = nr_of_symbols;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.start_symbol_index = start_symbol_index;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.ul_dmrs_symb_pos = ul_dmrs_symb_pos;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.dmrs_config_type = dmrs_config_type;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_index = mcs_index;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_table = mcs_table;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = 1;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = 0;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = rv_index;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nrOfLayers = nrOfLayers;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.harq_process_id = harq_process_id;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map = pdu_bit_map;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density;
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list = (nfapi_nr_ue_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ue_ptrs_ports_t));
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0;
|
||||
|
||||
if (1 << ptrs_time_density >= nr_of_symbols) {
|
||||
scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS
|
||||
}
|
||||
|
||||
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){
|
||||
mac->if_module->scheduled_response(&scheduled_response);
|
||||
}
|
||||
|
||||
// TODO: expand
|
||||
// Note: Contention resolution is currently not active
|
||||
if (mac->RA_contention_resolution_timer_active == 1)
|
||||
ue_contention_resolution(mod_id, gNB_index, cc_id, ul_info->frame_tx);
|
||||
}
|
||||
|
||||
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){
|
||||
mac->if_module->scheduled_response(&scheduled_response);
|
||||
}
|
||||
|
||||
// TODO: expand
|
||||
// Note: Contention resolution is currently not active
|
||||
if (mac->RA_contention_resolution_timer_active == 1)
|
||||
ue_contention_resolution(mod_id, gNB_index, cc_id, ul_info->frame_tx);
|
||||
}
|
||||
|
||||
return UE_CONNECTION_OK;
|
||||
}
|
||||
|
||||
// Notes:
|
||||
// - Type1-PDCCH CSS configuration from ra-SearchSpace.
|
||||
// - Msg2 is scheduled in the mixed slot or in the last dl slot if they are allowed by the Type 1 Common Search Space configuration
|
||||
// todo:
|
||||
// - if Type1-PDCCH CSS is not configured in RRC message (Coreset and SearchSpace), UE searches in Type 0 PDCCH CSS.
|
||||
void nr_ue_msg2_scheduler(module_id_t mod_id,
|
||||
uint16_t rach_frame,
|
||||
uint16_t rach_slot,
|
||||
uint16_t *msg2_frame,
|
||||
uint16_t *msg2_slot){
|
||||
|
||||
uint8_t bwp_id = 1;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
NR_CellGroupConfig_t *scg = mac->scg;
|
||||
NR_ServingCellConfigCommon_t *scc = mac->scc;
|
||||
NR_BWP_Downlink_t *bwp = scg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id - 1];
|
||||
NR_SearchSpace_t *ss;
|
||||
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
|
||||
uint8_t mu = *scc->ssbSubcarrierSpacing;
|
||||
uint8_t response_window = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow;
|
||||
uint8_t slot_window, slot_limit, frame_limit;
|
||||
uint16_t start_next_period, monitoring_slot_period, monitoring_offset;
|
||||
|
||||
// number of mixed slot or of last dl slot if there is no mixed slot
|
||||
uint16_t last_dl_slot_period = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
|
||||
uint16_t nr_dl_symbols = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols;
|
||||
uint16_t nr_ul_symbols = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols;
|
||||
|
||||
// lenght of tdd period in slots
|
||||
uint16_t tdd_period_slot = last_dl_slot_period + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
|
||||
|
||||
AssertFatal(commonSearchSpaceList->list.count > 0, "PDCCH common SearchSpace list has 0 elements\n");
|
||||
|
||||
LOG_D(MAC, "Frame %d, Slot %d: Scheduling Msg2 reception \n", rach_frame, rach_slot);
|
||||
|
||||
// Common searchspace list
|
||||
for (int i = 0; i < commonSearchSpaceList->list.count; i++) {
|
||||
ss = commonSearchSpaceList->list.array[i];
|
||||
if(ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace)
|
||||
// retrieving ra pdcch monitoring period and offset
|
||||
find_monitoring_periodicity_offset_common(ss, &monitoring_slot_period, &monitoring_offset);
|
||||
}
|
||||
|
||||
if (nr_dl_symbols == 0)
|
||||
last_dl_slot_period--;
|
||||
if ((nr_dl_symbols > 0) || (nr_ul_symbols > 0))
|
||||
tdd_period_slot++;
|
||||
|
||||
// computing start of next period
|
||||
start_next_period = (rach_slot - (rach_slot % tdd_period_slot) + tdd_period_slot) % nr_slots_per_frame[mu];
|
||||
*msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot
|
||||
*msg2_frame = (*msg2_slot > rach_slot) ? rach_frame : (rach_frame +1);
|
||||
|
||||
switch(response_window){
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
|
||||
slot_window = 1;
|
||||
break;
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2:
|
||||
slot_window = 2;
|
||||
break;
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4:
|
||||
slot_window = 4;
|
||||
break;
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8:
|
||||
slot_window = 8;
|
||||
break;
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10:
|
||||
slot_window = 10;
|
||||
break;
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20:
|
||||
slot_window = 20;
|
||||
break;
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40:
|
||||
slot_window = 40;
|
||||
break;
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80:
|
||||
slot_window = 80;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid response window value %d\n",response_window);
|
||||
}
|
||||
AssertFatal(slot_window<=nr_slots_per_frame[mu], "Msg2 response window needs to be lower or equal to 10ms");
|
||||
|
||||
// slot and frame limit to transmit msg2 according to response window
|
||||
slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu];
|
||||
frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1);
|
||||
|
||||
// go to previous slot if the current scheduled slot is beyond the response window
|
||||
// and if the slot is not among the PDCCH monitored ones (38.213 10.1)
|
||||
while ((*msg2_slot > slot_limit) || ((*msg2_frame*nr_slots_per_frame[mu] + *msg2_slot - monitoring_offset) % monitoring_slot_period != 0)) {
|
||||
if((*msg2_slot % tdd_period_slot) > 0)
|
||||
(*msg2_slot)--;
|
||||
else
|
||||
AssertFatal(1 == 0, "No available DL slot to schedule reception of msg2 has been found");
|
||||
}
|
||||
LOG_D(MAC, "Scheduled Msg2 reception in Frame %d, Slot %d: \n", *msg2_frame, *msg2_slot);
|
||||
}
|
||||
|
||||
// This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x
|
||||
// It fills the PRACH PDU per each FD occasion.
|
||||
// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3.
|
||||
@@ -969,6 +959,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
|
||||
config_index = rach_ConfigGeneric->prach_ConfigurationIndex;
|
||||
|
||||
mac->RA_offset = 2; // to compensate the rx frame offset at the gNB
|
||||
mac->generate_nr_prach = 0; // Reset flag for PRACH generation
|
||||
|
||||
if (is_nr_UL_slot(scc, slotP)) {
|
||||
|
||||
@@ -1090,8 +1081,8 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mac->generate_nr_prach = 0;
|
||||
} else if (mac->ra_state == RA_SUCCEEDED){
|
||||
mac->generate_nr_prach = 2;
|
||||
}
|
||||
mac->scheduled_response.ul_config = ul_config;
|
||||
}
|
||||
@@ -2235,9 +2226,14 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac,
|
||||
pdsch_TimeDomainAllocationList = mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
|
||||
if (pdsch_TimeDomainAllocationList) {
|
||||
|
||||
AssertFatal(pdsch_TimeDomainAllocationList->list.count > time_domain_ind,
|
||||
"time_domain_ind %d >= pdsch->TimeDomainAllocationList->list.count %d\n",
|
||||
time_domain_ind,pdsch_TimeDomainAllocationList->list.count);
|
||||
if (time_domain_ind >= pdsch_TimeDomainAllocationList->list.count) {
|
||||
LOG_E(MAC, "time_domain_ind %d >= pdsch->TimeDomainAllocationList->list.count %d\n",
|
||||
time_domain_ind, pdsch_TimeDomainAllocationList->list.count);
|
||||
dlsch_config_pdu->start_symbol = 0;
|
||||
dlsch_config_pdu->number_symbols = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int startSymbolAndLength = pdsch_TimeDomainAllocationList->list.array[time_domain_ind]->startSymbolAndLength;
|
||||
int S,L;
|
||||
SLIV2SL(startSymbolAndLength,&S,&L);
|
||||
@@ -2315,7 +2311,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc
|
||||
AssertFatal(mac->DLbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n");
|
||||
AssertFatal(mac->ULbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n");
|
||||
|
||||
const uint16_t n_RB_DLBWP = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275);
|
||||
const uint16_t n_RB_DLBWP = (mac->ra_state == WAIT_RAR) ? NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, 275) : NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275);
|
||||
const uint16_t n_RB_ULBWP = NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275);
|
||||
|
||||
LOG_D(MAC,"nr_ue_process_dci at MAC layer with dci_format=%d (DL BWP %d, UL BWP %d)\n",dci_format,n_RB_DLBWP,n_RB_ULBWP);
|
||||
@@ -2345,10 +2341,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc
|
||||
/* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */
|
||||
nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_0,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val);
|
||||
/* TIME_DOM_RESOURCE_ASSIGNMENT */
|
||||
nr_ue_process_dci_time_dom_resource_assignment(mac,
|
||||
pusch_config_pdu_0_0,NULL,
|
||||
dci->time_domain_assignment.val);
|
||||
|
||||
if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_0,NULL,dci->time_domain_assignment.val) < 0)
|
||||
break;
|
||||
/* FREQ_HOPPING_FLAG */
|
||||
if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) &&
|
||||
(mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0))
|
||||
@@ -2421,8 +2415,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc
|
||||
/* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */
|
||||
nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_1,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val);
|
||||
/* TIME_DOM_RESOURCE_ASSIGNMENT */
|
||||
nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_1,NULL,
|
||||
dci->time_domain_assignment.val);
|
||||
if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_1,NULL,dci->time_domain_assignment.val) < 0)
|
||||
break;
|
||||
/* FREQ_HOPPING_FLAG */
|
||||
if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) &&
|
||||
(mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0))
|
||||
@@ -2752,14 +2746,18 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc
|
||||
/* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */
|
||||
nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,n_RB_DLBWP,dci->frequency_domain_assignment.val);
|
||||
/* TIME_DOM_RESOURCE_ASSIGNMENT */
|
||||
nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,
|
||||
dci->time_domain_assignment.val);
|
||||
|
||||
if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val) < 0)
|
||||
break;
|
||||
/* dmrs symbol positions*/
|
||||
dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config,
|
||||
mac->scc->dmrs_TypeA_Position,
|
||||
dlsch_config_pdu_1_0->number_symbols);
|
||||
dlsch_config_pdu_1_0->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 1 : 2;
|
||||
dlsch_config_pdu_1_0->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1;
|
||||
/* number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214 version 15.9.0 Release 15 */
|
||||
if (dlsch_config_pdu_1_0->number_symbols == 2)
|
||||
dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 1;
|
||||
else
|
||||
dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 2;
|
||||
/* VRB_TO_PRB_MAPPING */
|
||||
dlsch_config_pdu_1_0->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved;
|
||||
/* MCS */
|
||||
@@ -2820,10 +2818,11 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc
|
||||
dlsch_config_pdu_1_0->pucch_resource_id,
|
||||
dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind);
|
||||
|
||||
if (mac->ra_rnti == rnti)
|
||||
if (mac->RA_window_cnt >= 0 && rnti == mac->ra_rnti){
|
||||
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH;
|
||||
else
|
||||
} else {
|
||||
dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH;
|
||||
}
|
||||
|
||||
// dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP = n_RB_DLBWP;
|
||||
|
||||
@@ -2872,13 +2871,16 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc
|
||||
/* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */
|
||||
nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->frequency_domain_assignment.val);
|
||||
/* TIME_DOM_RESOURCE_ASSIGNMENT */
|
||||
nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,
|
||||
dci->time_domain_assignment.val);
|
||||
if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val) < 0)
|
||||
break;
|
||||
/* dmrs symbol positions*/
|
||||
dlsch_config_pdu_1_1->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config,
|
||||
mac->scc->dmrs_TypeA_Position,
|
||||
dlsch_config_pdu_1_1->number_symbols);
|
||||
dlsch_config_pdu_1_1->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 1 : 2;
|
||||
dlsch_config_pdu_1_1->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1;
|
||||
/* TODO: fix number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214,
|
||||
using tables 7.3.1.2.2-1, 7.3.1.2.2-2, 7.3.1.2.2-3, 7.3.1.2.2-4 of 3GPP TS 38.212 */
|
||||
dlsch_config_pdu_1_1->n_dmrs_cdm_groups = 1;
|
||||
/* VRB_TO_PRB_MAPPING */
|
||||
if (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.resource_allocation != 0)
|
||||
dlsch_config_pdu_1_1->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved;
|
||||
@@ -3131,6 +3133,7 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac,
|
||||
case NR_DL_DCI_FORMAT_1_0:
|
||||
switch(rnti_type) {
|
||||
case NR_RNTI_RA:
|
||||
N_RB = NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); // TBR hotfix
|
||||
// Freq domain assignment
|
||||
fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) );
|
||||
pos=fsize;
|
||||
@@ -3142,7 +3145,7 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac,
|
||||
pos+=4;
|
||||
dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu >> (dci_size-pos))&0xf;
|
||||
#ifdef DEBUG_EXTRACT_DCI
|
||||
LOG_D(MAC,"time-domain assignment %d (3 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu);
|
||||
LOG_D(MAC,"time-domain assignment %d (4 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu);
|
||||
#endif
|
||||
// VRB to PRB mapping
|
||||
|
||||
@@ -3165,8 +3168,6 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac,
|
||||
#endif
|
||||
break;
|
||||
|
||||
mac->rnti_type = rnti_type;
|
||||
|
||||
case NR_RNTI_C:
|
||||
|
||||
// indicating a DL DCI format 1bit
|
||||
|
||||
@@ -107,9 +107,10 @@ uint16_t nr_ue_process_rar(module_id_t mod_id,
|
||||
uint8_t n_subPDUs = 0; // number of RAR payloads
|
||||
uint8_t n_subheaders = 0; // number of MAC RAR subheaders
|
||||
//uint8_t best_rx_rapid = -1; // the closest RAPID receive from all RARs
|
||||
unsigned char freq_hopping, msg3_t_alloc, mcs, tpc_command, csi_req;
|
||||
uint16_t ta_command = 0, msg3_f_alloc, bwp_size;
|
||||
int f_alloc, mask;
|
||||
//unsigned char freq_hopping, msg3_t_alloc, mcs, tpc_command, csi_req; // WIP
|
||||
//uint16_t ta_command = 0, msg3_f_alloc, bwp_size; // WIP
|
||||
uint16_t ta_command = 0;
|
||||
//int f_alloc, mask; // WIP
|
||||
|
||||
AssertFatal(CC_id == 0, "RAR reception on secondary CCs is not supported yet\n");
|
||||
|
||||
@@ -143,6 +144,7 @@ uint16_t nr_ue_process_rar(module_id_t mod_id,
|
||||
// LOG_I(MAC, "[UE %d][RAPROC] Frame %d Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n",
|
||||
// mod_id, frameP, *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], rar[4], rar[5], rarh->RAPID, preamble_index);
|
||||
|
||||
#if 0 // TbD WIP Msg3 development ongoing
|
||||
if (ue_mac->RA_RAPID_found) {
|
||||
// TC-RNTI
|
||||
*t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
|
||||
@@ -200,6 +202,7 @@ uint16_t nr_ue_process_rar(module_id_t mod_id,
|
||||
ue_mac->t_crnti = 0;
|
||||
ta_command = (0xffff);
|
||||
}
|
||||
#endif
|
||||
|
||||
// move the selected RAR to the front of the RA_PDSCH buffer
|
||||
memcpy((void *) (selected_rar_buffer + 0), (void *) rarh, 1);
|
||||
|
||||
@@ -42,8 +42,7 @@
|
||||
#include "SIMULATION/TOOLS/sim.h" // for taus
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
|
||||
const uint8_t nr_slots_per_frame_mac[5] = {10, 20, 40, 80, 160};
|
||||
extern const uint8_t nr_slots_per_frame[5];
|
||||
|
||||
uint8_t DELTA[4]= {2,3,4,6};
|
||||
|
||||
@@ -187,7 +186,7 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot,
|
||||
tdd_period_slot++;
|
||||
|
||||
// computing start of next period
|
||||
uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame_mac[mu];
|
||||
uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame[mu];
|
||||
*msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot
|
||||
*msg2_frame = (*msg2_slot>(rach_slot))? rach_frame : (rach_frame +1);
|
||||
|
||||
@@ -219,16 +218,16 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot,
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid response window value %d\n",response_window);
|
||||
}
|
||||
AssertFatal(slot_window<=nr_slots_per_frame_mac[mu],"Msg2 response window needs to be lower or equal to 10ms");
|
||||
AssertFatal(slot_window<=nr_slots_per_frame[mu],"Msg2 response window needs to be lower or equal to 10ms");
|
||||
|
||||
// slot and frame limit to transmit msg2 according to response window
|
||||
uint8_t slot_limit = (rach_slot + slot_window)%nr_slots_per_frame_mac[mu];
|
||||
uint8_t slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu];
|
||||
//uint8_t frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1);
|
||||
|
||||
|
||||
// go to previous slot if the current scheduled slot is beyond the response window
|
||||
// and if the slot is not among the PDCCH monitored ones (38.213 10.1)
|
||||
while ((*msg2_slot>slot_limit) || ((*msg2_frame*nr_slots_per_frame_mac[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0)) {
|
||||
while ((*msg2_slot>slot_limit) || ((*msg2_frame*nr_slots_per_frame[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0)) {
|
||||
if((*msg2_slot%tdd_period_slot) > 0)
|
||||
(*msg2_slot)--;
|
||||
else
|
||||
@@ -399,11 +398,11 @@ void nr_get_Msg3alloc(NR_ServingCellConfigCommon_t *scc,
|
||||
uint8_t k2 = *ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2;
|
||||
|
||||
temp_slot = current_slot + k2 + DELTA[mu]; // msg3 slot according to 8.3 in 38.213
|
||||
ra->Msg3_slot = temp_slot%nr_slots_per_frame_mac[mu];
|
||||
if (nr_slots_per_frame_mac[mu]>temp_slot)
|
||||
ra->Msg3_slot = temp_slot%nr_slots_per_frame[mu];
|
||||
if (nr_slots_per_frame[mu]>temp_slot)
|
||||
ra->Msg3_frame = current_frame;
|
||||
else
|
||||
ra->Msg3_frame = current_frame + (temp_slot/nr_slots_per_frame_mac[mu]);
|
||||
ra->Msg3_frame = current_frame + (temp_slot/nr_slots_per_frame[mu]);
|
||||
|
||||
ra->msg3_nb_rb = 18;
|
||||
ra->msg3_first_rb = 0;
|
||||
@@ -603,7 +602,11 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
|
||||
LOG_D(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw);
|
||||
|
||||
mcsIndex = 0; // Qm>2 not allowed for RAR
|
||||
// Qm>2 not allowed for RAR
|
||||
if (get_softmodem_params()->do_ra)
|
||||
mcsIndex = 9;
|
||||
else
|
||||
mcsIndex = 0;
|
||||
|
||||
pdsch_pdu_rel15->pduBitmap = 0;
|
||||
pdsch_pdu_rel15->rnti = RA_rnti;
|
||||
|
||||
@@ -997,10 +997,9 @@ void schedule_fapi_ul_pdu(int Mod_idP,
|
||||
pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t));
|
||||
pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0;
|
||||
|
||||
pusch_pdu->pdu_bit_map &= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS
|
||||
pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS
|
||||
}
|
||||
else{
|
||||
// if(1<<pusch_pdu->pusch_ptrs.ptrs_time_density >= pusch_pdu->nr_of_symbols)
|
||||
pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS
|
||||
}
|
||||
|
||||
|
||||
@@ -68,8 +68,6 @@
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
|
||||
extern int n_active_slices;
|
||||
|
||||
// Note the 2 scs values in the table names represent resp. scs_common and pdcch_scs
|
||||
/// LUT for the number of symbols in the coreset indexed by coreset index (4 MSB rmsi_pdcch_config)
|
||||
uint8_t nr_coreset_nsymb_pdcch_type_0_scs_15_15[15] = {2,2,2,3,3,3,1,1,2,2,3,3,1,2,3};
|
||||
|
||||
@@ -114,7 +114,9 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) {
|
||||
int ret=0;
|
||||
while ((sdu_p = pollNotifiedFIFO(&pdcp_sdu_list)) != NULL ) {
|
||||
pdcp_data_ind_header_t * pdcpHead=(pdcp_data_ind_header_t *)NotifiedFifoData(sdu_p);
|
||||
AssertFatal(pdcpHead->inst==ctxt_pP->module_id, "To implement correctly multi module id\n");
|
||||
|
||||
/* Note: we ignore the instance ID in the context and use the one in the
|
||||
* PDCP packet to pick the right socket below */
|
||||
|
||||
int rb_id = pdcpHead->rb_id;
|
||||
int sizeToWrite= sizeof (pdcp_data_ind_header_t) +
|
||||
@@ -130,19 +132,19 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) {
|
||||
sizeof(sidelink_pc5s_element), 0, (struct sockaddr *)&prose_pdcp_addr,sizeof(prose_pdcp_addr) );
|
||||
|
||||
} else if (UE_NAS_USE_TUN) {
|
||||
//ret = write(nas_sock_fd[ctxt_pP->module_id], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite );
|
||||
//ret = write(nas_sock_fd[pdcpHead->inst], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite );
|
||||
if(rb_id == mbms_rab_id){
|
||||
ret = write(nas_sock_mbms_fd, pdcpData,sizeToWrite );
|
||||
LOG_I(PDCP,"[PDCP_FIFOS] ret %d TRIED TO PUSH MBMS DATA TO rb_id %d handle %d sizeToWrite %d\n",
|
||||
ret,rb_id,nas_sock_fd[ctxt_pP->module_id],sizeToWrite);
|
||||
ret,rb_id,nas_sock_fd[pdcpHead->inst],sizeToWrite);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( LOG_DEBUGFLAG(DEBUG_PDCP) )
|
||||
log_dump(PDCP, pdcpData, sizeToWrite, LOG_DUMP_CHAR,"PDCP output to be sent to TUN interface: \n");
|
||||
ret = write(nas_sock_fd[ctxt_pP->module_id], pdcpData,sizeToWrite );
|
||||
ret = write(nas_sock_fd[pdcpHead->inst], pdcpData,sizeToWrite );
|
||||
LOG_T(PDCP,"[UE PDCP_FIFOS] ret %d TRIED TO PUSH DATA TO rb_id %d handle %d sizeToWrite %d\n",
|
||||
ret,rb_id,nas_sock_fd[ctxt_pP->module_id],sizeToWrite);
|
||||
ret,rb_id,nas_sock_fd[pdcpHead->inst],sizeToWrite);
|
||||
}
|
||||
} else if (ENB_NAS_USE_TUN) {
|
||||
if( LOG_DEBUGFLAG(DEBUG_PDCP) )
|
||||
|
||||
@@ -117,13 +117,6 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){
|
||||
|
||||
if (is_nr_UL_slot(mac->scc, ul_info->slot_tx) && get_softmodem_params()->do_ra){
|
||||
nr_ue_prach_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx);
|
||||
if (mac->generate_nr_prach){
|
||||
//uint16_t monitoring_slot_period, monitoring_offset;
|
||||
uint16_t rach_frame = mac->scheduled_response.ul_config->sfn;
|
||||
uint16_t rx_rach_frame = (rach_frame + mac->RA_offset) % MAX_FRAME_NUMBER; // compensate 2 frames offset delay at gNB side
|
||||
uint16_t rach_slot = mac->scheduled_response.ul_config->slot;
|
||||
nr_ue_msg2_scheduler(module_id, rx_rach_frame, rach_slot, &mac->msg2_rx_frame, &mac->msg2_rx_slot);
|
||||
}
|
||||
}
|
||||
|
||||
switch(ret){
|
||||
@@ -154,7 +147,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_
|
||||
fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request;
|
||||
|
||||
if (!dl_info->dci_ind && !dl_info->rx_ind) {
|
||||
// UL indication to schedule reception DCI reception
|
||||
// UL indication to schedule DCI reception
|
||||
nr_ue_scheduler(dl_info, NULL);
|
||||
} else {
|
||||
// UL indication after reception of DCI or DL PDU
|
||||
|
||||
@@ -2310,7 +2310,7 @@ uint8_t do_SidelinkUEInformation(uint8_t Mod_id, uint8_t *buffer, LTE_SL_Destin
|
||||
return((enc_rval.encoded+7)/8);
|
||||
}
|
||||
|
||||
uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS) {
|
||||
uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, uint8_t sel_plmn_id, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS) {
|
||||
asn_enc_rval_t enc_rval;
|
||||
LTE_UL_DCCH_Message_t ul_dcch_msg;
|
||||
LTE_RRCConnectionSetupComplete_t *rrcConnectionSetupComplete;
|
||||
@@ -2323,7 +2323,7 @@ uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uin
|
||||
rrcConnectionSetupComplete->criticalExtensions.choice.c1.present = LTE_RRCConnectionSetupComplete__criticalExtensions__c1_PR_rrcConnectionSetupComplete_r8;
|
||||
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension=CALLOC(1,
|
||||
sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension));
|
||||
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= 1;
|
||||
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= sel_plmn_id;
|
||||
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME =
|
||||
NULL;//calloc(1,sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME));
|
||||
/*
|
||||
|
||||
@@ -142,7 +142,11 @@ uint8_t do_SidelinkUEInformation(uint8_t Mod_id, uint8_t *buffer, LTE_SL_Destina
|
||||
/** \brief Generate an RRCConnectionSetupComplete UL-DCCH-Message (UE)
|
||||
@param buffer Pointer to PER-encoded ASN.1 description of UL-DCCH-Message PDU
|
||||
@returns Size of encoded bit stream in bytes*/
|
||||
uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, const int dedicatedInfoNASLength,
|
||||
uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id,
|
||||
uint8_t *buffer,
|
||||
const uint8_t Transaction_id,
|
||||
uint8_t sel_plmn_id,
|
||||
const int dedicatedInfoNASLength,
|
||||
const char *dedicatedInfoNAS);
|
||||
|
||||
/** \brief Generate an RRCConnectionReconfigurationComplete UL-DCCH-Message (UE)
|
||||
|
||||
+53
-38
@@ -128,8 +128,13 @@ static int decode_SIB1_MBMS( const protocol_ctxt_t *const ctxt_pP, const uint8_t
|
||||
* \param ctxt_pP Running context
|
||||
* \param eNB_index Index of corresponding eNB/CH
|
||||
* \param Transaction_id Transaction identifier
|
||||
* \param sel_plmn_id selected PLMN Identity
|
||||
*/
|
||||
static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id );
|
||||
static void rrc_ue_generate_RRCConnectionSetupComplete(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const uint8_t eNB_index,
|
||||
const uint8_t Transaction_id,
|
||||
uint8_t sel_plmn_id);
|
||||
|
||||
/** \brief Generates/Encodes RRCConnectionReconfigurationComplete message at UE
|
||||
* \param ctxt_pP Running context
|
||||
@@ -367,6 +372,7 @@ char openair_rrc_ue_init( const module_id_t ue_mod_idP, const unsigned char eNB_
|
||||
rrc_set_state (ue_mod_idP, RRC_STATE_INACTIVE);
|
||||
rrc_set_sub_state (ue_mod_idP, RRC_SUB_STATE_INACTIVE);
|
||||
LOG_I(RRC,"[UE %d] INIT State = RRC_IDLE (eNB %d)\n",ctxt.module_id,eNB_index);
|
||||
UE_rrc_inst[ctxt.module_id].selected_plmn_identity = 1;
|
||||
UE_rrc_inst[ctxt.module_id].Info[eNB_index].State=RRC_IDLE;
|
||||
UE_rrc_inst[ctxt.module_id].Info[eNB_index].T300_active = 0;
|
||||
UE_rrc_inst[ctxt.module_id].Info[eNB_index].T304_active = 0;
|
||||
@@ -490,7 +496,11 @@ rrc_t310_expiration(
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id ) {
|
||||
static void rrc_ue_generate_RRCConnectionSetupComplete(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const uint8_t eNB_index,
|
||||
const uint8_t Transaction_id,
|
||||
uint8_t sel_plmn_id) {
|
||||
uint8_t buffer[100];
|
||||
uint8_t size;
|
||||
const char *nas_msg;
|
||||
@@ -504,7 +514,7 @@ static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *c
|
||||
nas_msg_length = sizeof(nas_attach_req_imsi);
|
||||
}
|
||||
|
||||
size = do_RRCConnectionSetupComplete(ctxt_pP->module_id, buffer, Transaction_id, nas_msg_length, nas_msg);
|
||||
size = do_RRCConnectionSetupComplete(ctxt_pP->module_id, buffer, Transaction_id, sel_plmn_id, nas_msg_length, nas_msg);
|
||||
LOG_I(RRC,"[UE %d][RAPROC] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCConnectionSetupComplete (bytes%d, eNB %d)\n",
|
||||
ctxt_pP->module_id,ctxt_pP->frame, size, eNB_index);
|
||||
LOG_D(RLC,
|
||||
@@ -624,7 +634,8 @@ int rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const SRB_INFO *co
|
||||
rrc_ue_generate_RRCConnectionSetupComplete(
|
||||
ctxt_pP,
|
||||
eNB_index,
|
||||
dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup.rrc_TransactionIdentifier);
|
||||
dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup.rrc_TransactionIdentifier,
|
||||
UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity);
|
||||
rval = 0;
|
||||
break;
|
||||
|
||||
@@ -2794,44 +2805,43 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index,
|
||||
LTE_SystemInformationBlockType1_t *sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index];
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_IN );
|
||||
LOG_I( RRC, "[UE %d] : Dumping SIB 1\n", ctxt_pP->module_id );
|
||||
LTE_PLMN_Identity_t *PLMN_identity = &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->plmn_Identity;
|
||||
int mccdigits = PLMN_identity->mcc->list.count;
|
||||
int mncdigits = PLMN_identity->mnc.list.count;
|
||||
int mcc;
|
||||
const int n = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
LTE_PLMN_Identity_t *PLMN_identity = &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[i]->plmn_Identity;
|
||||
int mccdigits = PLMN_identity->mcc->list.count;
|
||||
int mncdigits = PLMN_identity->mnc.list.count;
|
||||
|
||||
if (mccdigits == 2) {
|
||||
mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1];
|
||||
} else {
|
||||
mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2];
|
||||
int mcc;
|
||||
if (mccdigits == 2) {
|
||||
mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1];
|
||||
} else {
|
||||
mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2];
|
||||
}
|
||||
|
||||
int mnc;
|
||||
if (mncdigits == 2) {
|
||||
mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1];
|
||||
} else {
|
||||
mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2];
|
||||
}
|
||||
|
||||
LOG_I( RRC, "PLMN %d MCC %0*d, MNC %0*d\n", i + 1, mccdigits, mcc, mncdigits, mnc);
|
||||
// search internal table for provider name
|
||||
int plmn_ind = 0;
|
||||
|
||||
while (plmn_data[plmn_ind].mcc > 0) {
|
||||
if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) {
|
||||
LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short );
|
||||
break;
|
||||
}
|
||||
|
||||
plmn_ind++;
|
||||
}
|
||||
}
|
||||
|
||||
int mnc;
|
||||
|
||||
if (mncdigits == 2) {
|
||||
mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1];
|
||||
} else {
|
||||
mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2];
|
||||
}
|
||||
|
||||
LOG_I( RRC, "PLMN MCC %0*d, MNC %0*d, TAC 0x%04x\n", mccdigits, mcc, mncdigits, mnc,
|
||||
LOG_I( RRC, "TAC 0x%04x\n",
|
||||
((sib1->cellAccessRelatedInfo.trackingAreaCode.size == 2)?((sib1->cellAccessRelatedInfo.trackingAreaCode.buf[0]<<8) + sib1->cellAccessRelatedInfo.trackingAreaCode.buf[1]):0));
|
||||
LOG_I( RRC, "cellReservedForOperatorUse : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse,
|
||||
SIBreserved(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse) );
|
||||
// search internal table for provider name
|
||||
int plmn_ind = 0;
|
||||
|
||||
while (plmn_data[plmn_ind].mcc > 0) {
|
||||
if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) {
|
||||
LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short );
|
||||
break;
|
||||
}
|
||||
|
||||
plmn_ind++;
|
||||
}
|
||||
|
||||
if (plmn_data[plmn_ind].mcc < 0) {
|
||||
LOG_I( RRC, "Found Unknown operator (no entry in internal table)\n" );
|
||||
}
|
||||
|
||||
LOG_I( RRC, "cellAccessRelatedInfo.cellIdentity : raw:%"PRIu32" decoded:%02x.%02x.%02x.%02x\n",
|
||||
BIT_STRING_to_uint32( &sib1->cellAccessRelatedInfo.cellIdentity ),
|
||||
@@ -2970,6 +2980,7 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index,
|
||||
NAS_CELL_SELECTION_CNF (msg_p).rsrp = rsrp;
|
||||
itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p);
|
||||
cell_valid = 1;
|
||||
UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity = plmn + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2980,7 +2991,11 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index,
|
||||
MessageDef *msg_p;
|
||||
msg_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_NEXT_CELL_REQ);
|
||||
itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p);
|
||||
LOG_E(RRC, "Synched with a cell, but PLMN doesn't match our SIM, the message PHY_FIND_NEXT_CELL_REQ is sent but lost in current UE implementation! \n");
|
||||
LOG_E(RRC,
|
||||
"Synched with a cell, but PLMN doesn't match our SIM "
|
||||
"(selected_plmn_identity %d), the message PHY_FIND_NEXT_CELL_REQ "
|
||||
"is sent but lost in current UE implementation!\n",
|
||||
UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -809,6 +809,7 @@ typedef struct UE_RRC_INST_s {
|
||||
Rrc_Sub_State_t RrcSubState;
|
||||
plmn_t plmnID;
|
||||
Byte_t rat;
|
||||
uint8_t selected_plmn_identity;
|
||||
as_nas_info_t initialNasMsg;
|
||||
OAI_UECapability_t *UECap;
|
||||
uint8_t *UECapability;
|
||||
|
||||
@@ -994,11 +994,14 @@ void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, boolean_t removeFlag) {
|
||||
pthread_mutex_unlock(&lock_ue_freelist);
|
||||
}
|
||||
|
||||
extern int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type);
|
||||
extern int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type);
|
||||
extern void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch);
|
||||
extern void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
|
||||
|
||||
void release_UE_in_freeList(module_id_t mod_id) {
|
||||
int i, j, CC_id, pdu_number;
|
||||
protocol_ctxt_t ctxt;
|
||||
LTE_eNB_ULSCH_t *ulsch = NULL;
|
||||
LTE_eNB_DLSCH_t *dlsch = NULL;
|
||||
nfapi_ul_config_request_body_t *ul_req_tmp = NULL;
|
||||
PHY_VARS_eNB *eNB_PHY = NULL;
|
||||
struct rrc_eNB_ue_context_s *ue_context_pP = NULL;
|
||||
@@ -1032,6 +1035,25 @@ void release_UE_in_freeList(module_id_t mod_id) {
|
||||
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
eNB_PHY = RC.eNB[mod_id][CC_id];
|
||||
|
||||
int id;
|
||||
|
||||
// clean ULSCH entries for rnti
|
||||
id = find_ulsch(rnti,eNB_PHY,SEARCH_EXIST);
|
||||
if (id>=0) clean_eNb_ulsch(eNB_PHY->ulsch[id]);
|
||||
|
||||
// clean DLSCH entries for rnti
|
||||
id = find_dlsch(rnti,eNB_PHY,SEARCH_EXIST);
|
||||
if (id>=0) clean_eNb_dlsch(eNB_PHY->dlsch[id][0]);
|
||||
|
||||
// clean UCI entries for rnti
|
||||
for (i=0; i<NUMBER_OF_UCI_VARS_MAX; i++) {
|
||||
if(eNB_PHY->uci_vars[i].rnti == rnti) {
|
||||
LOG_I(MAC, "clean eNb uci_vars[%d] UE %x \n",i, rnti);
|
||||
memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for (i=0; i<MAX_MOBILES_PER_ENB; i++) {
|
||||
ulsch = eNB_PHY->ulsch[i];
|
||||
|
||||
@@ -1064,6 +1086,7 @@ void release_UE_in_freeList(module_id_t mod_id) {
|
||||
memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (flexran_agent_get_rrc_xface(mod_id)) {
|
||||
flexran_agent_get_rrc_xface(mod_id)->flexran_agent_notify_ue_state_change(
|
||||
|
||||
@@ -96,36 +96,34 @@ void extract_imsi(uint8_t *pdu_buf, uint32_t pdu_len, rrc_eNB_ue_context_t *ue_c
|
||||
&& pdu_len > NAS_MESSAGE_SECURITY_HEADER_SIZE))
|
||||
return;
|
||||
|
||||
/* Decode plain NAS message */
|
||||
EMM_msg *e_msg = &nas_msg.plain.emm;
|
||||
emm_msg_header_t *emm_header = &e_msg->header;
|
||||
|
||||
if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED) {
|
||||
/* Decode the message authentication code */
|
||||
DECODE_U32((char *) pdu_buf+size, header->message_authentication_code, size);
|
||||
/* Decode the sequence number */
|
||||
DECODE_U8((char *) pdu_buf+size, header->sequence_number, size);
|
||||
}
|
||||
/* Decode the security header type and the protocol discriminator */
|
||||
DECODE_U8(pdu_buf + size, *(uint8_t *)(emm_header), size);
|
||||
|
||||
/* Note: the value of the pointer (i.e. the address) is given by value, so we
|
||||
* can modify it as we want. The callee retains the original address! */
|
||||
/* Check that this is the right message */
|
||||
if (emm_header->protocol_discriminator != EPS_MOBILITY_MANAGEMENT_MESSAGE)
|
||||
return;
|
||||
}
|
||||
pdu_buf += size;
|
||||
pdu_len -= size;
|
||||
/* Decode plain NAS message */
|
||||
EMM_msg *e_msg = &nas_msg.plain.emm;
|
||||
emm_msg_header_t *emm_header = &e_msg->header;
|
||||
/* First decode the EMM message header */
|
||||
int e_head_size = 0;
|
||||
|
||||
/* Check that buffer contains more than only the header */
|
||||
if (pdu_len <= sizeof(emm_msg_header_t))
|
||||
return;
|
||||
|
||||
/* Decode the security header type and the protocol discriminator */
|
||||
DECODE_U8(pdu_buf + e_head_size, *(uint8_t *)(emm_header), e_head_size);
|
||||
/* First decode the EMM message header */
|
||||
int e_head_size = 0;
|
||||
/* Decode the message type */
|
||||
DECODE_U8(pdu_buf + e_head_size, emm_header->message_type, e_head_size);
|
||||
|
||||
/* Check that this is the right message */
|
||||
if (emm_header->protocol_discriminator != EPS_MOBILITY_MANAGEMENT_MESSAGE)
|
||||
return;
|
||||
|
||||
pdu_buf += e_head_size;
|
||||
pdu_len -= e_head_size;
|
||||
|
||||
|
||||
@@ -116,7 +116,9 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
|
||||
/* some sanity check - to be refined at some point */
|
||||
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
||||
X2AP_ERROR("x2ap_enb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n");
|
||||
abort();
|
||||
// Allow for a gracious exit when we kill first the gNB, then the eNB
|
||||
//abort();
|
||||
return;
|
||||
}
|
||||
|
||||
x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams;
|
||||
|
||||
Reference in New Issue
Block a user