Merge remote-tracking branch 'origin/feature-slice+restart-w35' into develop_integration_2018_w36

Conflicts:
	openair2/ENB_APP/flexran_agent_common_internal.c
	openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
This commit is contained in:
Cedric Roux
2018-09-07 16:13:40 +02:00
46 changed files with 5510 additions and 2621 deletions
+1
View File
@@ -871,6 +871,7 @@ add_library(FLEXRAN_AGENT
${OPENAIR2_DIR}/ENB_APP/flexran_agent_net_comm.c
${OPENAIR2_DIR}/ENB_APP/flexran_agent_async.c
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c
)
set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT)
#include_directories(${OPENAIR2_DIR}/ENB_APP)
+103 -62
View File
@@ -120,75 +120,116 @@ int ret;
int load_module_shlib(char *modname,loader_shlibfunc_t *farray, int numf, void *autoinit_arg)
{
void *lib_handle;
initfunc_t fpi;
checkverfunc_t fpc;
getfarrayfunc_t fpg;
char *shlib_path;
char *afname=NULL;
int ret=0;
void *lib_handle = NULL;
initfunc_t fpi;
checkverfunc_t fpc;
getfarrayfunc_t fpg;
char *shlib_path = NULL;
char *afname = NULL;
int ret = 0;
int lib_idx = -1;
if (loader_data.shlibpath == NULL) {
loader_init();
}
if (!modname) {
fprintf(stderr, "[LOADER] load_module_shlib(): no library name given\n");
return -1;
}
shlib_path = loader_format_shlibpath(modname);
if (!loader_data.shlibpath) {
loader_init();
}
ret = 0;
lib_handle = dlopen(shlib_path, RTLD_LAZY|RTLD_NODELETE|RTLD_GLOBAL);
if (!lib_handle) {
fprintf(stderr,"[LOADER] library %s is not loaded: %s\n", shlib_path,dlerror());
shlib_path = loader_format_shlibpath(modname);
for (int i = 0; i < loader_data.numshlibs; i++) {
if (strcmp(loader_data.shlibs[i].name, modname) == 0) {
printf("[LOADER] library %s has been loaded previously, reloading function pointers\n",
shlib_path);
lib_idx = i;
break;
}
}
if (lib_idx < 0) {
lib_idx = loader_data.numshlibs;
++loader_data.numshlibs;
if (loader_data.numshlibs > loader_data.maxshlibs) {
fprintf(stderr, "[LOADER] can not load more than %d shlibs\n",
loader_data.maxshlibs);
ret = -1;
} else {
printf("[LOADER] library %s successfully loaded\n", shlib_path);
afname=malloc(strlen(modname)+15);
sprintf(afname,"%s_checkbuildver",modname);
fpc = dlsym(lib_handle,afname);
if (fpc != NULL ){
int chkver_ret = fpc(loader_data.mainexec_buildversion, &(loader_data.shlibs[loader_data.numshlibs].shlib_buildversion));
if (chkver_ret < 0) {
fprintf(stderr,"[LOADER] %s %d lib %s, version mismatch",__FILE__, __LINE__, modname);
exit_fun("[LOADER] unrecoverable error");
}
goto load_module_shlib_exit;
}
loader_data.shlibs[lib_idx].name = strdup(modname);
loader_data.shlibs[lib_idx].thisshlib_path = strdup(shlib_path);
}
lib_handle = dlopen(shlib_path, RTLD_LAZY|RTLD_NODELETE|RTLD_GLOBAL);
if (!lib_handle) {
fprintf(stderr,"[LOADER] library %s is not loaded: %s\n", shlib_path,dlerror());
ret = -1;
goto load_module_shlib_exit;
}
printf("[LOADER] library %s successfully loaded\n", shlib_path);
afname = malloc(strlen(modname)+15);
if (!afname) {
fprintf(stderr, "[LOADER] unable to allocate memory for library %s\n", shlib_path);
ret = -1;
goto load_module_shlib_exit;
}
sprintf(afname,"%s_checkbuildver",modname);
fpc = dlsym(lib_handle,afname);
if (fpc) {
int chkver_ret = fpc(loader_data.mainexec_buildversion,
&(loader_data.shlibs[lib_idx].shlib_buildversion));
if (chkver_ret < 0) {
fprintf(stderr, "[LOADER] %s %d lib %s, version mismatch",
__FILE__, __LINE__, modname);
ret = -1;
goto load_module_shlib_exit;
}
}
sprintf(afname,"%s_autoinit",modname);
fpi = dlsym(lib_handle,afname);
if (fpi) {
fpi(autoinit_arg);
}
if (farray) {
if (!loader_data.shlibs[lib_idx].funcarray) {
loader_data.shlibs[lib_idx].funcarray = malloc(numf*sizeof(loader_shlibfunc_t));
if (!loader_data.shlibs[lib_idx].funcarray) {
fprintf(stderr, "[LOADER] load_module_shlib(): unable to allocate memory\n");
ret = -1;
goto load_module_shlib_exit;
}
sprintf(afname,"%s_autoinit",modname);
fpi = dlsym(lib_handle,afname);
if (fpi != NULL ) {
fpi(autoinit_arg);
}
loader_data.shlibs[lib_idx].numfunc = 0;
for (int i = 0; i < numf; i++) {
farray[i].fptr = dlsym(lib_handle,farray[i].fname);
if (!farray[i].fptr) {
fprintf(stderr, "[LOADER] load_module_shlib(): function %s not found: %s\n",
farray[i].fname, dlerror());
ret = -1;
goto load_module_shlib_exit;
}
loader_data.shlibs[lib_idx].funcarray[i].fname=strdup(farray[i].fname);
loader_data.shlibs[lib_idx].funcarray[i].fptr = farray[i].fptr;
loader_data.shlibs[lib_idx].numfunc++;
} /* for int i... */
} else { /* farray ! NULL */
sprintf(afname,"%s_getfarray",modname);
fpg = dlsym(lib_handle,afname);
if (fpg) {
loader_data.shlibs[lib_idx].numfunc =
fpg(&(loader_data.shlibs[lib_idx].funcarray));
}
} /* farray ! NULL */
if (farray != NULL) {
loader_data.shlibs[loader_data.numshlibs].funcarray=malloc(numf*sizeof(loader_shlibfunc_t));
loader_data.shlibs[loader_data.numshlibs].numfunc=0;
for (int i=0; i<numf; i++) {
farray[i].fptr = dlsym(lib_handle,farray[i].fname);
if (farray[i].fptr == NULL ) {
fprintf(stderr,"[LOADER] %s %d %s function not found %s\n",__FILE__, __LINE__, dlerror(),farray[i].fname);
ret= -1;
} else { /* farray[i].fptr == NULL */
loader_data.shlibs[loader_data.numshlibs].funcarray[i].fname=strdup(farray[i].fname);
loader_data.shlibs[loader_data.numshlibs].funcarray[i].fptr = farray[i].fptr;
loader_data.shlibs[loader_data.numshlibs].numfunc++;
}/* farray[i].fptr != NULL */
} /* for int i... */
} else { /* farray ! NULL */
sprintf(afname,"%s_getfarray",modname);
fpg = dlsym(lib_handle,afname);
if (fpg != NULL ) {
loader_data.shlibs[loader_data.numshlibs].numfunc = fpg(&(loader_data.shlibs[loader_data.numshlibs].funcarray));
}
} /* farray ! NULL */
loader_data.shlibs[loader_data.numshlibs].name=strdup(modname);
loader_data.shlibs[loader_data.numshlibs].thisshlib_path=strdup(shlib_path);
(loader_data.numshlibs)++;
} /* lib_handle != NULL */
if ( shlib_path!= NULL) free(shlib_path);
if ( afname!= NULL) free(afname);
if (lib_handle != NULL) dlclose(lib_handle);
return ret;
load_module_shlib_exit:
if (shlib_path) free(shlib_path);
if (afname) free(afname);
if (lib_handle) dlclose(lib_handle);
return ret;
}
void * get_shlibmodule_fptr(char *modname, char *fname)
+16 -11
View File
@@ -995,9 +995,10 @@ static inline void wait_sync(char *thread_name) {
}
static inline int wakeup_thread(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
if (pthread_mutex_lock(mutex) != 0) {
LOG_E( PHY, "error locking mutex for %s\n",name);
int rc;
if ((rc = pthread_mutex_lock(mutex)) != 0) {
LOG_E(PHY, "wakeup_thread(): error locking mutex for %s (%d %s, %p)\n",
name, rc, strerror(rc), (void *)mutex);
exit_fun("nothing to add");
return(-1);
}
@@ -1014,8 +1015,10 @@ static inline int wakeup_thread(pthread_mutex_t *mutex,pthread_cond_t *cond,int
}
static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
if (pthread_mutex_lock(mutex) != 0) {
LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
int rc;
if ((rc = pthread_mutex_lock(mutex)) != 0) {
LOG_E(PHY, "[SCHED][eNB] wait_on_condition(): error locking mutex for %s (%d %s, %p)\n",
name, rc, strerror(rc), (void *)mutex);
exit_fun("nothing to add");
return(-1);
}
@@ -1035,9 +1038,10 @@ static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,
}
static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
if (pthread_mutex_lock(mutex) != 0) {
LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
int rc;
if ((rc = pthread_mutex_lock(mutex)) != 0) {
LOG_E(PHY, "[SCHED][eNB] wait_on_busy_condition(): error locking mutex for %s (%d %s, %p)\n",
name, rc, strerror(rc), (void *)mutex);
exit_fun("nothing to add");
return(-1);
}
@@ -1057,9 +1061,10 @@ static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *
}
static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) {
if (pthread_mutex_lock(mutex) != 0) {
LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
int rc;
if ((rc = pthread_mutex_lock(mutex)) != 0) {
LOG_E(PHY, "[SCHED][eNB] release_thread(): error locking mutex for %s (%d %s, %p)\n",
name, rc, strerror(rc), (void *)mutex);
exit_fun("nothing to add");
return(-1);
}
+29
View File
@@ -0,0 +1,29 @@
/*
* 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
*/
/*
* flexran_messages_def.h
*
* Created on: Apr 26, 2018
* Author: R. Schmidt
*/
MESSAGE_DEF(SOFT_RESTART_MESSAGE, MESSAGE_PRIORITY_MED_PLUS, IttiMsgEmpty, soft_restart_message)
+1 -1
View File
@@ -38,4 +38,4 @@
#include "sctp_messages_def.h"
#include "udp_messages_def.h"
#include "gtpv1_u_messages_def.h"
#include "flexran_messages_def.h"
+7 -1
View File
@@ -107,9 +107,15 @@ typedef enum {
CR_HOL = 2,
CR_LC = 3,
CR_CQI = 4,
CR_NUM = 5
CR_LCP = 5,
CR_NUM = 6
} sorting_criterion_t;
typedef enum {
POL_FAIR = 0,
POL_GREEDY = 1,
POL_NUM = 2
} accounting_policy_t;
//-----------------------------------------------------------------------------
// PHY TYPES
//-----------------------------------------------------------------------------
@@ -52,6 +52,18 @@ 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;
int flexran_agent_mac_stats_reply(mid_t mod_id,
const report_config_t *report_config,
@@ -61,6 +73,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
// Protocol__FlexHeader *header;
int i, j, k;
int UE_id;
int cc_id = 0;
int enb_id = mod_id;
@@ -70,6 +83,8 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
for (i = 0; i < report_config->nr_ue; i++) {
UE_id = flexran_get_ue_id(mod_id, i);
ue_report[i]->rnti = report_config->ue_report_type[i].ue_rnti;
ue_report[i]->has_rnti = 1;
@@ -91,7 +106,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
/* Check flag for creation of PHR report */
if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PHR) {
ue_report[i]->phr = flexran_get_ue_phr (enb_id, i); // eNB_UE_list->UE_template[UE_PCCID(enb_id,i)][i].phr_info;
ue_report[i]->phr = flexran_get_ue_phr (enb_id, UE_id); // eNB_UE_list->UE_template[UE_PCCID(enb_id,UE_id)][UE_id].phr_info;
ue_report[i]->has_phr = 1;
}
@@ -113,11 +128,11 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
protocol__flex_rlc_bsr__init(rlc_reports[j]);
rlc_reports[j]->lc_id = j+1;
rlc_reports[j]->has_lc_id = 1;
rlc_reports[j]->tx_queue_size = flexran_get_tx_queue_size(enb_id, i, j + 1);
rlc_reports[j]->tx_queue_size = flexran_get_tx_queue_size(enb_id, UE_id, j + 1);
rlc_reports[j]->has_tx_queue_size = 1;
//TODO:Set tx queue head of line delay in ms
rlc_reports[j]->tx_queue_hol_delay = flexran_get_hol_delay(enb_id, i, j + 1);
rlc_reports[j]->tx_queue_hol_delay = flexran_get_hol_delay(enb_id, UE_id, j + 1);
rlc_reports[j]->has_tx_queue_hol_delay = 1;
//TODO:Set retransmission queue size in bytes
rlc_reports[j]->retransmission_queue_size = 10;
@@ -126,7 +141,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
rlc_reports[j]->retransmission_queue_hol_delay = 100;
rlc_reports[j]->has_retransmission_queue_hol_delay = 0;
//TODO DONE:Set current size of the pending message in bytes
rlc_reports[j]->status_pdu_size = flexran_get_num_pdus_buffer(enb_id , i, j + 1);
rlc_reports[j]->status_pdu_size = flexran_get_num_pdus_buffer(enb_id, UE_id, j + 1);
rlc_reports[j]->has_status_pdu_size = 1;
}
@@ -140,7 +155,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
/* Check flag for creation of MAC CE buffer status report */
if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_CE_BS) {
// TODO: Fill in the actual MAC CE buffer status report
ue_report[i]->pending_mac_ces = (flexran_get_MAC_CE_bitmap_TA(enb_id,i,0) | (0 << 1) | (0 << 2) | (0 << 3)) & 15;
ue_report[i]->pending_mac_ces = (flexran_get_MAC_CE_bitmap_TA(enb_id, UE_id, 0) | (0 << 1) | (0 << 2) | (0 << 3)) & 15;
// Use as bitmap. Set one or more of the; /* Use as bitmap. Set one or more of the
// PROTOCOL__FLEX_CE_TYPE__FLPCET_ values
// found in stats_common.pb-c.h. See
@@ -161,7 +176,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
dl_report->sfn_sn = flexran_get_sfn_sf(enb_id);
dl_report->has_sfn_sn = 1;
//Set the number of DL CQI reports for this UE. One for each CC
dl_report->n_csi_report = flexran_get_active_CC(enb_id,i);
dl_report->n_csi_report = flexran_get_active_CC(enb_id, UE_id);
dl_report->n_csi_report = 1 ;
//Create the actual CSI reports.
Protocol__FlexDlCsi **csi_reports;
@@ -178,7 +193,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
csi_reports[j]->serv_cell_index = j;
csi_reports[j]->has_serv_cell_index = 1;
//The rank indicator value for this cc
csi_reports[j]->ri = flexran_get_current_RI(enb_id,i,j);
csi_reports[j]->ri = flexran_get_current_RI(enb_id, UE_id, j);
csi_reports[j]->has_ri = 1;
//TODO: the type of CSI report based on the configuration of the UE
//For now we only support type P10, which only needs a wideband value
@@ -197,7 +212,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
protocol__flex_csi_p10__init(csi10);
//TODO: set the wideband value
// NN: this is also depends on cc_id
csi10->wb_cqi = flexran_get_ue_wcqi (enb_id, i); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].dl_cqi;
csi10->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,UE_id)][UE_id].dl_cqi;
csi10->has_wb_cqi = 1;
//Add the type of measurements to the csi report in the proper union type
csi_reports[j]->p10csi = csi10;
@@ -214,26 +229,26 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
csi11->wb_cqi = malloc(sizeof(csi11->wb_cqi));
csi11->n_wb_cqi = 1;
csi11->wb_cqi[0] = flexran_get_ue_wcqi (enb_id, i);
csi11->wb_cqi[0] = flexran_get_ue_wcqi (enb_id, UE_id);
// According To spec 36.213
if (flexran_get_antenna_ports(enb_id, j) == 2 && csi_reports[j]->ri == 1) {
// TODO PMI
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, i, 0);
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, UE_id, 0);
csi11->has_wb_pmi = 1;
}
else if (flexran_get_antenna_ports(enb_id, j) == 2 && csi_reports[j]->ri == 2){
// TODO PMI
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, i, 0);
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, UE_id, 0);
csi11->has_wb_pmi = 1;
}
else if (flexran_get_antenna_ports(enb_id, j) == 4 && csi_reports[j]->ri == 2){
// TODO PMI
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, i, 0);
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, UE_id, 0);
csi11->has_wb_pmi = 1;
@@ -257,7 +272,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
goto error;
protocol__flex_csi_p20__init(csi20);
csi20->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
csi20->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id);
csi20->has_wb_cqi = 1;
@@ -281,7 +296,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
// goto error;
// protocol__flex_csi_p21__init(csi21);
// csi21->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
// csi21->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id);
// csi21->wb_pmi = flexran_get_ue_pmi(enb_id); //TDO inside
@@ -309,7 +324,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
// goto error;
// protocol__flex_csi_a12__init(csi12);
// csi12->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
// csi12->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id);
// csi12->sb_pmi = 1 ; //TODO inside
@@ -324,17 +339,17 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
// goto error;
// protocol__flex_csi_a22__init(csi22);
// csi22->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
// csi22->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id);
// csi22->sb_cqi = 1 ; //TODO inside
// csi22->wb_pmi = flexran_get_ue_wcqi (enb_id, i);
// csi22->wb_pmi = flexran_get_ue_wcqi (enb_id, UE_id);
// csi22->has_wb_pmi = 1;
// csi22->sb_pmi = 1 ; //TODO inside
// csi22->has_wb_pmi = 1;
// csi22->sb_list = flexran_get_ue_wcqi (enb_id, i);
// csi22->sb_list = flexran_get_ue_wcqi (enb_id, UE_id);
}
@@ -347,7 +362,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
// goto error;
// protocol__flex_csi_a20__init(csi20);
// csi20->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
// csi20->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id);
// csi20->has_wb_cqi = 1;
// csi20>sb_cqi = 1 ; //TODO inside
@@ -477,8 +492,8 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
full_ul_report->pucch_dbm[j]->has_serv_cell_index = 1;
full_ul_report->pucch_dbm[j]->serv_cell_index = j;
if(flexran_get_p0_pucch_dbm(enb_id,i, j) != -1){
full_ul_report->pucch_dbm[j]->p0_pucch_dbm = flexran_get_p0_pucch_dbm(enb_id,i,j);
if(flexran_get_p0_pucch_dbm(enb_id, UE_id, j) != -1){
full_ul_report->pucch_dbm[j]->p0_pucch_dbm = flexran_get_p0_pucch_dbm(enb_id, UE_id, j);
full_ul_report->pucch_dbm[j]->has_p0_pucch_dbm = 1;
}
}
@@ -499,69 +514,69 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
protocol__flex_mac_stats__init(macstats);
macstats->total_bytes_sdus_dl = flexran_get_total_size_dl_mac_sdus(mod_id, i, cc_id);
macstats->total_bytes_sdus_dl = flexran_get_total_size_dl_mac_sdus(mod_id, UE_id, cc_id);
macstats->has_total_bytes_sdus_dl = 1;
macstats->total_bytes_sdus_ul = flexran_get_total_size_ul_mac_sdus(mod_id, i, cc_id);
macstats->total_bytes_sdus_ul = flexran_get_total_size_ul_mac_sdus(mod_id, UE_id, cc_id);
macstats->has_total_bytes_sdus_ul = 1;
macstats->tbs_dl = flexran_get_TBS_dl(mod_id, i, cc_id);
macstats->tbs_dl = flexran_get_TBS_dl(mod_id, UE_id, cc_id);
macstats->has_tbs_dl = 1;
macstats->tbs_ul = flexran_get_TBS_ul(mod_id, i, cc_id);
macstats->tbs_ul = flexran_get_TBS_ul(mod_id, UE_id, cc_id);
macstats->has_tbs_ul = 1;
macstats->prb_retx_dl = flexran_get_num_prb_retx_dl_per_ue(mod_id, i, cc_id);
macstats->prb_retx_dl = flexran_get_num_prb_retx_dl_per_ue(mod_id, UE_id, cc_id);
macstats->has_prb_retx_dl = 1;
macstats->prb_retx_ul = flexran_get_num_prb_retx_ul_per_ue(mod_id, i, cc_id);
macstats->prb_retx_ul = flexran_get_num_prb_retx_ul_per_ue(mod_id, UE_id, cc_id);
macstats->has_prb_retx_ul = 1;
macstats->prb_dl = flexran_get_num_prb_dl_tx_per_ue(mod_id, i, cc_id);
macstats->prb_dl = flexran_get_num_prb_dl_tx_per_ue(mod_id, UE_id, cc_id);
macstats->has_prb_dl = 1;
macstats->prb_ul = flexran_get_num_prb_ul_rx_per_ue(mod_id, i, cc_id);
macstats->prb_ul = flexran_get_num_prb_ul_rx_per_ue(mod_id, UE_id, cc_id);
macstats->has_prb_ul = 1;
macstats->mcs1_dl = flexran_get_mcs1_dl(mod_id, i, cc_id);
macstats->mcs1_dl = flexran_get_mcs1_dl(mod_id, UE_id, cc_id);
macstats->has_mcs1_dl = 1;
macstats->mcs2_dl = flexran_get_mcs2_dl(mod_id, i, cc_id);
macstats->mcs2_dl = flexran_get_mcs2_dl(mod_id, UE_id, cc_id);
macstats->has_mcs2_dl = 1;
macstats->mcs1_ul = flexran_get_mcs1_ul(mod_id, i, cc_id);
macstats->mcs1_ul = flexran_get_mcs1_ul(mod_id, UE_id, cc_id);
macstats->has_mcs1_ul = 1;
macstats->mcs2_ul = flexran_get_mcs2_ul(mod_id, i, cc_id);
macstats->mcs2_ul = flexran_get_mcs2_ul(mod_id, UE_id, cc_id);
macstats->has_mcs2_ul = 1;
macstats->total_prb_dl = flexran_get_total_prb_dl_tx_per_ue(mod_id, i, cc_id);
macstats->total_prb_dl = flexran_get_total_prb_dl_tx_per_ue(mod_id, UE_id, cc_id);
macstats->has_total_prb_dl = 1;
macstats->total_prb_ul = flexran_get_total_prb_ul_rx_per_ue(mod_id, i, cc_id);
macstats->total_prb_ul = flexran_get_total_prb_ul_rx_per_ue(mod_id, UE_id, cc_id);
macstats->has_total_prb_ul = 1;
macstats->total_pdu_dl = flexran_get_total_num_pdu_dl(mod_id, i, cc_id);
macstats->total_pdu_dl = flexran_get_total_num_pdu_dl(mod_id, UE_id, cc_id);
macstats->has_total_pdu_dl = 1;
macstats->total_pdu_ul = flexran_get_total_num_pdu_ul(mod_id, i, cc_id);
macstats->total_pdu_ul = flexran_get_total_num_pdu_ul(mod_id, UE_id, cc_id);
macstats->has_total_pdu_ul = 1;
macstats->total_tbs_dl = flexran_get_total_TBS_dl(mod_id, i, cc_id);
macstats->total_tbs_dl = flexran_get_total_TBS_dl(mod_id, UE_id, cc_id);
macstats->has_total_tbs_dl = 1;
macstats->total_tbs_ul = flexran_get_total_TBS_ul(mod_id, i, cc_id);
macstats->total_tbs_ul = flexran_get_total_TBS_ul(mod_id, UE_id, cc_id);
macstats->has_total_tbs_ul = 1;
macstats->harq_round = flexran_get_harq_round(mod_id, cc_id, i);
macstats->harq_round = flexran_get_harq_round(mod_id, cc_id, UE_id);
macstats->has_harq_round = 1;
Protocol__FlexMacSdusDl ** mac_sdus;
mac_sdus = malloc(sizeof(Protocol__FlexMacSdusDl) * flexran_get_num_mac_sdu_tx(mod_id, i, cc_id));
mac_sdus = malloc(sizeof(Protocol__FlexMacSdusDl) * flexran_get_num_mac_sdu_tx(mod_id, UE_id, cc_id));
if (mac_sdus == NULL)
goto error;
macstats->n_mac_sdus_dl = flexran_get_num_mac_sdu_tx(mod_id, i, cc_id);
macstats->n_mac_sdus_dl = flexran_get_num_mac_sdu_tx(mod_id, UE_id, cc_id);
for (j = 0; j < macstats->n_mac_sdus_dl; j++){
@@ -569,10 +584,10 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
mac_sdus[j] = malloc(sizeof(Protocol__FlexMacSdusDl));
protocol__flex_mac_sdus_dl__init(mac_sdus[j]);
mac_sdus[j]->lcid = flexran_get_mac_sdu_lcid_index(mod_id, i, cc_id, j);
mac_sdus[j]->lcid = flexran_get_mac_sdu_lcid_index(mod_id, UE_id, cc_id, j);
mac_sdus[j]->has_lcid = 1;
mac_sdus[j]->sdu_length = flexran_get_mac_sdu_size(mod_id, i, cc_id, mac_sdus[j]->lcid);
mac_sdus[j]->sdu_length = flexran_get_mac_sdu_size(mod_id, UE_id, cc_id, mac_sdus[j]->lcid);
mac_sdus[j]->has_sdu_length = 1;
@@ -882,7 +897,6 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
for (j = 0; j < 8; j++) {
if (RC.mac && RC.mac[mod_id] && RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid == 1) {
available_harq[i] = j;
sf_trigger_msg->n_dl_info++;
break;
}
}
@@ -891,10 +905,7 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
// LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10);
/*TODO: Fill in the number of dl HARQ related info, based on the number of currently
*transmitting UEs
*/
// sf_trigger_msg->n_dl_info = flexran_get_num_ues(mod_id);
sf_trigger_msg->n_dl_info = flexran_get_num_ues(mod_id);
Protocol__FlexDlInfo **dl_info = NULL;
@@ -904,33 +915,31 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
goto error;
i = -1;
//Fill the status of the current HARQ process for each UE
for(UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
if (available_harq[UE_id] < 0) {
for(i = 0; i < sf_trigger_msg->n_dl_info; i++) {
if (available_harq[i] < 0)
continue;
} else {
i++;
}
dl_info[i] = malloc(sizeof(Protocol__FlexDlInfo));
if(dl_info[i] == NULL)
goto error;
UE_id = flexran_get_ue_id(mod_id, i);
protocol__flex_dl_info__init(dl_info[i]);
dl_info[i]->rnti = flexran_get_ue_crnti(mod_id, UE_id);
dl_info[i]->has_rnti = 1;
/*Fill in the right id of this round's HARQ process for this UE*/
// uint8_t harq_id;
//uint8_t harq_status;
// flexran_get_harq(mod_id, UE_PCCID(mod_id,i), i, frame, subframe, &harq_id, &harq_status);
// flexran_get_harq(mod_id, UE_PCCID(mod_id, UE_id), i, frame, subframe, &harq_id, &harq_status);
dl_info[i]->harq_process_id = available_harq[UE_id];
if (RC.mac && RC.mac[mod_id])
RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id,i)][UE_id].harq_pid = 0;
RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id, UE_id)][UE_id].harq_pid = 0;
dl_info[i]->has_harq_process_id = 1;
/* Fill in the status of the HARQ process (2 TBs)*/
dl_info[i]->n_harq_status = 2;
dl_info[i]->harq_status = malloc(sizeof(uint32_t) * dl_info[i]->n_harq_status);
for (j = 0; j < dl_info[i]->n_harq_status; j++) {
dl_info[i]->harq_status[j] = RC.mac[mod_id]->UE_list.UE_sched_ctrl[i].round[UE_PCCID(mod_id,i)][j];
dl_info[i]->harq_status[j] = RC.mac[mod_id]->UE_list.UE_sched_ctrl[UE_id].round[UE_PCCID(mod_id, UE_id)][j];
// TODO: This should be different per TB
}
// LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d and harq %d (round %d)\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10, dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]);
@@ -938,7 +947,7 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
// LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d]Need to make a retransmission for harq %d (round %d)\n", flexran_get_current_frame(mod_id), flexran_get_current_subframe(mod_id), dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]);
}
/*Fill in the serving cell index for this UE */
dl_info[i]->serv_cell_index = UE_PCCID(mod_id,i);
dl_info[i]->serv_cell_index = UE_PCCID(mod_id, UE_id);
dl_info[i]->has_serv_cell_index = 1;
}
}
@@ -962,18 +971,21 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
if(ul_info[i] == NULL)
goto error;
protocol__flex_ul_info__init(ul_info[i]);
ul_info[i]->rnti = flexran_get_ue_crnti(mod_id, i);
UE_id = flexran_get_ue_id(mod_id, i);
ul_info[i]->rnti = flexran_get_ue_crnti(mod_id, UE_id);
ul_info[i]->has_rnti = 1;
/* Fill in the Tx power control command for this UE (if available),
* primary carrier */
if(flexran_get_tpc(mod_id, i, 0) != 1){
if(flexran_get_tpc(mod_id, UE_id, 0) != 1){
/* assume primary carrier */
ul_info[i]->tpc = flexran_get_tpc(mod_id, i, 0);
ul_info[i]->tpc = flexran_get_tpc(mod_id, UE_id, 0);
ul_info[i]->has_tpc = 1;
}
else{
/* assume primary carrier */
ul_info[i]->tpc = flexran_get_tpc(mod_id, i, 0);
ul_info[i]->tpc = flexran_get_tpc(mod_id, UE_id, 0);
ul_info[i]->has_tpc = 0;
}
/*TODO: fill in the amount of data in bytes in the MAC SDU received in this subframe for the
@@ -987,7 +999,7 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
ul_info[i]->reception_status = PROTOCOL__FLEX_RECEPTION_STATUS__FLRS_OK;
ul_info[i]->has_reception_status = 1;
/*Fill in the serving cell index for this UE */
ul_info[i]->serv_cell_index = UE_PCCID(mod_id,i);
ul_info[i]->serv_cell_index = UE_PCCID(mod_id, UE_id);
ul_info[i]->has_serv_cell_index = 1;
}
}
@@ -1260,8 +1272,17 @@ void flexran_agent_init_mac_agent(mid_t mod_id) {
lfds700_misc_prng_init(&ps[mod_id]);
int num_elements = RINGBUFFER_SIZE + 1;
//Allow RINGBUFFER_SIZE messages to be stored in the ringbuffer at any time
dl_mac_config_array[mod_id] = malloc( sizeof(struct lfds700_ringbuffer_element) * num_elements);
lfds700_ringbuffer_init_valid_on_current_logical_core( &ringbuffer_state[mod_id], dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL );
/* lfds700_ringbuffer_init_valid_on_current_logical_core()'s second argument
* must be aligned to LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES. From the
* documentation: "Heap allocated variables however will by no means be
* correctly aligned and an aligned malloc must be used." Therefore, we use
* posix_memalign */
i = posix_memalign((void **)&dl_mac_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 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);
for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
for (j = 0; j < 8; j++) {
if (RC.mac && RC.mac[mod_id])
@@ -1372,8 +1393,229 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) {
return 0;
}
void flexran_create_config_structures(mid_t mod_id)
{
int i;
int n_dl = flexran_get_num_dl_slices(mod_id);
int m_ul = flexran_get_num_ul_slices(mod_id);
slice_config[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul);
sc_update[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul);
if (!slice_config[mod_id] || !sc_update[mod_id]) return;
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]);
}
for (i = 0; i < m_ul; i++) {
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]);
}
}
void flexran_check_and_remove_slices(mid_t mod_id)
{
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 flexran_agent_slice_update(mid_t mod_id)
{
int i;
int changes = 0;
if (perform_slice_config_update_count <= 0) return;
perform_slice_config_update_count--;
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;
}
/********* read existing config *********/
/* simply update slice_config all the time and write new config
* (apply_new_slice_dl_config() only updates if changes are necessary) */
slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id);
slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id);
for (i = 0; i < slice_config[mod_id]->n_dl; i++) {
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
}
for (i = 0; i < slice_config[mod_id]->n_ul; i++) {
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
}
/********* 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;
}
@@ -87,4 +87,14 @@ int flexran_agent_register_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface);
/*Unregister technology specific callbacks*/
int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface*xface);
/***************************************
* FlexRAN agent - slice configuration *
***************************************/
/* Inform controller about possibility to update slice configuration */
void flexran_agent_slice_update(mid_t mod_id);
/* return a pointer to the current config */
Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id);
#endif
@@ -31,6 +31,15 @@
#include "flexran_agent_common_internal.h"
#include "flexran_agent_mac_internal.h"
#include "flexran_agent_mac_slice_verification.h"
/* from flexran_agent_mac.c */
extern Protocol__FlexSliceConfig *slice_config[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) {
@@ -899,3 +908,721 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
return -1;
}
Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul)
{
int i;
Protocol__FlexSliceConfig *fsc = malloc(sizeof(Protocol__FlexSliceConfig));
if (!fsc) return NULL;
protocol__flex_slice_config__init(fsc);
/* say there are n_dl slices but reserve memory for up to MAX_NUM_SLICES so
* we don't need to reserve again later */
fsc->n_dl = n_dl;
fsc->dl = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexDlSlice *));
if (!fsc->dl) fsc->n_dl = 0;
for (i = 0; i < MAX_NUM_SLICES; i++) {
fsc->dl[i] = malloc(sizeof(Protocol__FlexDlSlice));
if (!fsc->dl[i]) continue;
protocol__flex_dl_slice__init(fsc->dl[i]);
}
/* as above */
fsc->n_ul = m_ul;
fsc->ul = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexUlSlice *));
if (!fsc->ul) fsc->n_ul = 0;
for (i = 0; i < MAX_NUM_SLICES; i++) {
fsc->ul[i] = malloc(sizeof(Protocol__FlexUlSlice));
if (!fsc->ul[i]) continue;
protocol__flex_ul_slice__init(fsc->ul[i]);
}
return fsc;
}
void flexran_agent_read_slice_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);
} 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);
}
}
verified = 1;
if (sup->n_ul == 0) {
LOG_I(FLEXRAN_AGENT, "[%d] no UL slice configuration in flex_slice_config message\n", mod_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);
}
}
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);
return;
}
if (!ue_config->has_rnti) {
LOG_E(FLEXRAN_AGENT,
"[%d] cannot update UE to slice association, no RNTI in flex_ue_config message\n",
mod_id);
return;
}
if (ue_config->has_dl_slice_id)
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to DL slice ID %d\n",
mod_id, ue_config->rnti, ue_config->dl_slice_id);
if (ue_config->has_ul_slice_id)
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to UL slice ID %d\n",
mod_id, ue_config->rnti, ue_config->ul_slice_id);
ue_slice_assoc_update[n_ue_slice_assoc_updates++] = ue_config;
perform_slice_config_update_count = 2;
}
int apply_ue_slice_assoc_update(mid_t mod_id)
{
int i;
int changes = 0;
for (i = 0; i < n_ue_slice_assoc_updates; i++) {
int ue_id = find_UE_id(mod_id, ue_slice_assoc_update[i]->rnti);
if (ue_slice_assoc_update[i]->has_dl_slice_id) {
int slice_idx = flexran_find_dl_slice(mod_id, ue_slice_assoc_update[i]->dl_slice_id);
if (flexran_dl_slice_exists(mod_id, slice_idx)) {
flexran_set_ue_dl_slice_idx(mod_id, ue_id, slice_idx);
changes++;
} else {
LOG_W(FLEXRAN_AGENT, "[%d] DL slice %d does not exist, refusing change\n",
mod_id, ue_slice_assoc_update[i]->dl_slice_id);
}
}
if (ue_slice_assoc_update[i]->has_ul_slice_id) {
int slice_idx = flexran_find_ul_slice(mod_id, ue_slice_assoc_update[i]->ul_slice_id);
if (flexran_ul_slice_exists(mod_id, slice_idx)) {
flexran_set_ue_ul_slice_idx(mod_id, ue_id, slice_idx);
changes++;
} else {
LOG_W(FLEXRAN_AGENT, "[%d] UL slice %d does not exist, refusing change\n",
mod_id, ue_slice_assoc_update[i]->ul_slice_id);
}
}
}
n_ue_slice_assoc_updates = 0;
return changes;
}
@@ -107,4 +107,45 @@ int parse_ul_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser);
int load_dl_scheduler_function(mid_t mod_id, const char *function_name);
/*** Functions for handling a slice config ***/
/* allocate memory for a Protocol__FlexSliceConfig structure with n_dl DL slice
* configs and m_ul UL slice configs */
Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul);
/* read the 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);
/* apply a new association between a UE and a slice (both DL and UL) */
int apply_ue_slice_assoc_update(mid_t mod_id);
#endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/
@@ -0,0 +1,373 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file flexran_agent_mac_slice_verification.c
* \brief MAC Agent slice verification helper functions
* \author Robert Schmidt
* \date 2018
* \version 0.1
*/
#include "flexran_agent_mac_slice_verification.h"
/* overlap check for UL slices, helper type */
struct sregion_s {
int start;
int length;
};
/* forward declaration of locally-used verification functions */
int flexran_dl_slice_verify_pct(int pct);
int flexran_dl_slice_verify_priority(int prio);
int flexran_dl_slice_verify_position(int pos_low, int pos_high);
int flexran_dl_slice_verify_maxmcs(int maxmcs);
int flexran_ul_slice_verify_pct(int pct);
int flexran_ul_slice_verify_priority(int prio);
int flexran_ul_slice_verify_first_rb(int first_rb);
int flexran_ul_slice_verify_maxmcs(int maxmcs);
int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n);
int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls)
{
/* check mandatory parameters */
if (!dls->has_id) {
LOG_E(FLEXRAN_AGENT, "[%d] Incoming DL slice configuration has no ID\n", mod_id);
return 0;
}
/* verify parameters individualy */
/* label is enum */
if (!flexran_dl_slice_verify_pct(dls->percentage)) {
LOG_E(FLEXRAN_AGENT, "[%d][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;
}
@@ -0,0 +1,37 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file flexran_agent_mac_slice_verification.h
* \brief MAC Agent slice verification helper functions
* \author Robert Schmidt
* \date 2018
* \version 0.1
*/
#include "flexran_agent_common_internal.h"
#include "flexran_agent_mac_internal.h"
int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls);
int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing,
int n_ex, Protocol__FlexDlSlice **update, int n_up);
int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls);
int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing,
int n_ex, Protocol__FlexUlSlice **update, int n_up);
@@ -78,6 +78,7 @@ int flexran_agent_pdcp_stats_reply(mid_t mod_id,
// Protocol__FlexHeader *header;
int i;
int UE_id;
// int cc_id = 0;
@@ -85,6 +86,7 @@ int flexran_agent_pdcp_stats_reply(mid_t mod_id,
if (report_config->nr_ue > 0) {
for (i = 0; i < report_config->nr_ue; i++) {
UE_id = flexran_get_ue_id(mod_id, i);
/* Check flag for creation of buffer status report */
if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PDCP_STATS) {
@@ -95,7 +97,7 @@ int flexran_agent_pdcp_stats_reply(mid_t mod_id,
goto error;
protocol__flex_pdcp_stats__init(pdcp_aggr_stats);
flexran_agent_pdcp_aggregate_stats(mod_id, i, pdcp_aggr_stats);
flexran_agent_pdcp_aggregate_stats(mod_id, UE_id, pdcp_aggr_stats);
pdcp_aggr_stats->has_pkt_tx=1;
pdcp_aggr_stats->has_pkt_tx_bytes =1;
@@ -104,7 +106,7 @@ int flexran_agent_pdcp_stats_reply(mid_t mod_id,
pdcp_aggr_stats->has_pkt_tx_aiat =1;
pdcp_aggr_stats->has_pkt_tx_aiat_w =1;
pdcp_aggr_stats->pkt_tx_sn = flexran_get_pdcp_tx_sn(mod_id, i, DEFAULT_DRB);
pdcp_aggr_stats->pkt_tx_sn = flexran_get_pdcp_tx_sn(mod_id, UE_id, DEFAULT_DRB);
pdcp_aggr_stats->has_pkt_tx_sn =1;
pdcp_aggr_stats->has_pkt_rx =1;
@@ -115,7 +117,7 @@ int flexran_agent_pdcp_stats_reply(mid_t mod_id,
pdcp_aggr_stats->has_pkt_rx_aiat_w =1;
pdcp_aggr_stats->has_pkt_rx_oo =1;
pdcp_aggr_stats->pkt_rx_sn = flexran_get_pdcp_rx_sn(mod_id, i, DEFAULT_DRB);
pdcp_aggr_stats->pkt_rx_sn = flexran_get_pdcp_rx_sn(mod_id, UE_id, DEFAULT_DRB);
pdcp_aggr_stats->has_pkt_rx_sn =1;
pdcp_aggr_stats->sfn = flexran_get_pdcp_sfn(mod_id);
@@ -76,147 +76,147 @@ void flexran_agent_ue_state_change(mid_t mod_id, uint32_t rnti, uint8_t state_ch
config->has_rnti = 1;
config->rnti = rnti;
} else if (state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED
|| state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED) {
int i = find_UE_id(mod_id, rnti);
config->has_rnti = 1;
config->rnti = rnti;
if(flexran_get_time_alignment_timer(mod_id,i) != -1) {
config->time_alignment_timer = flexran_get_time_alignment_timer(mod_id,i);
config->has_time_alignment_timer = 1;
}
if(flexran_get_meas_gap_config(mod_id,i) != -1){
config->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id,i);
config->has_meas_gap_config_pattern = 1;
}
if(config->has_meas_gap_config_pattern == 1 &&
config->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
config->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id,i);
config->has_meas_gap_config_sf_offset = 1;
}
//TODO: Set the SPS configuration (Optional)
//Not supported for now, so we do not set it
|| state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED) {
int i = find_UE_id(mod_id, rnti);
config->has_rnti = 1;
config->rnti = rnti;
config->imsi = flexran_get_ue_imsi(mod_id, i);
config->has_imsi = 1;
config->dl_slice_id = flexran_get_ue_dl_slice_id(mod_id, i);
config->has_dl_slice_id = 1;
config->ul_slice_id = flexran_get_ue_ul_slice_id(mod_id, i);
config->has_ul_slice_id = 1;
if(flexran_get_time_alignment_timer(mod_id,i) != -1) {
config->time_alignment_timer = flexran_get_time_alignment_timer(mod_id,i);
config->has_time_alignment_timer = 1;
}
if(flexran_get_meas_gap_config(mod_id,i) != -1){
config->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id,i);
config->has_meas_gap_config_pattern = 1;
}
if(config->has_meas_gap_config_pattern == 1 &&
config->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
config->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id,i);
config->has_meas_gap_config_sf_offset = 1;
}
//TODO: Set the SPS configuration (Optional)
//Not supported for now, so we do not set it
//TODO: Set the SR configuration (Optional)
//We do not set it for now
//TODO: Set the SR configuration (Optional)
//We do not set it for now
//TODO: Set the CQI configuration (Optional)
//We do not set it for now
if(flexran_get_ue_transmission_mode(mod_id,i) != -1) {
config->transmission_mode = flexran_get_ue_transmission_mode(mod_id,i);
config->has_transmission_mode = 1;
}
//TODO: Set the CQI configuration (Optional)
//We do not set it for now
config->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id,i);
config->has_ue_aggregated_max_bitrate_ul = 1;
if(flexran_get_ue_transmission_mode(mod_id,i) != -1) {
config->transmission_mode = flexran_get_ue_transmission_mode(mod_id,i);
config->has_transmission_mode = 1;
}
config->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id,i);
config->has_ue_aggregated_max_bitrate_dl = 1;
config->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id,i);
config->has_ue_aggregated_max_bitrate_ul = 1;
//TODO: Set the UE capabilities
Protocol__FlexUeCapabilities *c_capabilities;
c_capabilities = malloc(sizeof(Protocol__FlexUeCapabilities));
protocol__flex_ue_capabilities__init(c_capabilities);
//TODO: Set half duplex (FDD operation)
c_capabilities->has_half_duplex = 0;
c_capabilities->half_duplex = 1;//flexran_get_half_duplex(i);
//TODO: Set intra-frame hopping flag
c_capabilities->has_intra_sf_hopping = 0;
c_capabilities->intra_sf_hopping = 1;//flexran_get_intra_sf_hopping(i);
//TODO: Set support for type 2 hopping with n_sb > 1
c_capabilities->has_type2_sb_1 = 0;
c_capabilities->type2_sb_1 = 1;//flexran_get_type2_sb_1(i);
//TODO: Set ue category
c_capabilities->has_ue_category = 0;
c_capabilities->ue_category = 1;//flexran_get_ue_category(i);
//TODO: Set UE support for resource allocation type 1
c_capabilities->has_res_alloc_type1 = 0;
c_capabilities->res_alloc_type1 = 1;//flexran_get_res_alloc_type1(i);
//Set the capabilites to the message
config->capabilities = c_capabilities;
if(flexran_get_ue_transmission_antenna(mod_id,i) != -1) {
config->has_ue_transmission_antenna = 1;
config->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id,i);
}
config->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id,i);
config->has_ue_aggregated_max_bitrate_dl = 1;
if(flexran_get_tti_bundling(mod_id,i) != -1) {
config->has_tti_bundling = 1;
config->tti_bundling = flexran_get_tti_bundling(mod_id,i);
}
Protocol__FlexUeCapabilities *c_capabilities;
c_capabilities = malloc(sizeof(Protocol__FlexUeCapabilities));
protocol__flex_ue_capabilities__init(c_capabilities);
c_capabilities->has_half_duplex = 1;
c_capabilities->half_duplex = flexran_get_half_duplex(mod_id, i);
c_capabilities->has_intra_sf_hopping = 1;
c_capabilities->intra_sf_hopping = flexran_get_intra_sf_hopping(mod_id, i);
c_capabilities->has_type2_sb_1 = 1;
c_capabilities->type2_sb_1 = flexran_get_type2_sb_1(mod_id, i);
c_capabilities->has_ue_category = 1;
c_capabilities->ue_category = flexran_get_ue_category(mod_id, i);
c_capabilities->has_res_alloc_type1 = 1;
c_capabilities->res_alloc_type1 = flexran_get_res_alloc_type1(mod_id, i);
//Set the capabilites to the message
config->capabilities = c_capabilities;
if(flexran_get_maxHARQ_TX(mod_id,i) != -1){
config->has_max_harq_tx = 1;
config->max_harq_tx = flexran_get_maxHARQ_TX(mod_id,i);
}
if(flexran_get_ue_transmission_antenna(mod_id,i) != -1) {
config->has_ue_transmission_antenna = 1;
config->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id,i);
}
if(flexran_get_beta_offset_ack_index(mod_id,i) != -1) {
config->has_beta_offset_ack_index = 1;
config->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id,i);
}
if(flexran_get_tti_bundling(mod_id,i) != -1) {
config->has_tti_bundling = 1;
config->tti_bundling = flexran_get_tti_bundling(mod_id,i);
}
if(flexran_get_beta_offset_ri_index(mod_id,i) != -1) {
config->has_beta_offset_ri_index = 1;
config->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id,i);
}
if(flexran_get_maxHARQ_TX(mod_id,i) != -1){
config->has_max_harq_tx = 1;
config->max_harq_tx = flexran_get_maxHARQ_TX(mod_id,i);
}
if(flexran_get_beta_offset_cqi_index(mod_id,i) != -1) {
config->has_beta_offset_cqi_index = 1;
config->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id,i);
}
if(flexran_get_beta_offset_ack_index(mod_id,i) != -1) {
config->has_beta_offset_ack_index = 1;
config->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id,i);
}
/* assume primary carrier */
if(flexran_get_ack_nack_simultaneous_trans(mod_id,i,0) != -1) {
config->has_ack_nack_simultaneous_trans = 1;
config->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id,i,0);
}
if(flexran_get_beta_offset_ri_index(mod_id,i) != -1) {
config->has_beta_offset_ri_index = 1;
config->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id,i);
}
if(flexran_get_simultaneous_ack_nack_cqi(mod_id,i) != -1) {
config->has_simultaneous_ack_nack_cqi = 1;
config->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id,i);
}
if(flexran_get_beta_offset_cqi_index(mod_id,i) != -1) {
config->has_beta_offset_cqi_index = 1;
config->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id,i);
}
if(flexran_get_aperiodic_cqi_rep_mode(mod_id,i) != -1) {
config->has_aperiodic_cqi_rep_mode = 1;
int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id,i);
if (mode > 4) {
config->aperiodic_cqi_rep_mode = PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
} else {
config->aperiodic_cqi_rep_mode = mode;
}
}
/* assume primary carrier */
if(flexran_get_ack_nack_simultaneous_trans(mod_id,i,0) != -1) {
config->has_ack_nack_simultaneous_trans = 1;
config->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id,i,0);
}
if(flexran_get_tdd_ack_nack_feedback_mode(mod_id, i) != -1) {
config->has_tdd_ack_nack_feedback = 1;
config->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback_mode(mod_id,i);
}
if(flexran_get_simultaneous_ack_nack_cqi(mod_id,i) != -1) {
config->has_simultaneous_ack_nack_cqi = 1;
config->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id,i);
}
if(flexran_get_ack_nack_repetition_factor(mod_id, i) != -1) {
config->has_ack_nack_repetition_factor = 1;
config->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id,i);
}
if(flexran_get_aperiodic_cqi_rep_mode(mod_id,i) != -1) {
config->has_aperiodic_cqi_rep_mode = 1;
int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id,i);
if (mode > 4) {
config->aperiodic_cqi_rep_mode = PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
} else {
config->aperiodic_cqi_rep_mode = mode;
}
}
if(flexran_get_extended_bsr_size(mod_id, i) != -1) {
config->has_extended_bsr_size = 1;
config->extended_bsr_size = flexran_get_extended_bsr_size(mod_id,i);
}
if(flexran_get_tdd_ack_nack_feedback_mode(mod_id, i) != -1) {
config->has_tdd_ack_nack_feedback = 1;
config->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback_mode(mod_id,i);
}
config->has_pcell_carrier_index = 1;
config->pcell_carrier_index = UE_PCCID(mod_id, i);
//TODO: Set carrier aggregation support (boolean)
config->has_ca_support = 0;
config->ca_support = 0;
if(config->has_ca_support){
//TODO: Set cross carrier scheduling support (boolean)
config->has_cross_carrier_sched_support = 1;
config->cross_carrier_sched_support = 0;
//TODO: Set secondary cells configuration
// We do not set it for now. No carrier aggregation support
//TODO: Set deactivation timer for secondary cell
config->has_scell_deactivation_timer = 0;
config->scell_deactivation_timer = 0;
}
if(flexran_get_ack_nack_repetition_factor(mod_id, i) != -1) {
config->has_ack_nack_repetition_factor = 1;
config->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id,i);
}
if(flexran_get_extended_bsr_size(mod_id, i) != -1) {
config->has_extended_bsr_size = 1;
config->extended_bsr_size = flexran_get_extended_bsr_size(mod_id,i);
}
config->has_pcell_carrier_index = 1;
config->pcell_carrier_index = UE_PCCID(mod_id, i);
//TODO: Set carrier aggregation support (boolean)
config->has_ca_support = 0;
config->ca_support = 0;
if(config->has_ca_support){
//TODO: Set cross carrier scheduling support (boolean)
config->has_cross_carrier_sched_support = 1;
config->cross_carrier_sched_support = 0;
//TODO: Set secondary cells configuration
// We do not set it for now. No carrier aggregation support
//TODO: Set deactivation timer for secondary cell
config->has_scell_deactivation_timer = 0;
config->scell_deactivation_timer = 0;
}
} else if (state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_MOVED) {
// TODO: Not supported for now. Leave blank
}
@@ -264,27 +264,31 @@ int flexran_agent_destroy_ue_state_change(Protocol__FlexranMessage *msg) {
/* this is called by RRC as a part of rrc xface . The controller previously requested this*/
void flexran_trigger_rrc_measurements (mid_t mod_id, MeasResults_t* measResults) {
int i;
//int i;
// int priority = 0; // Warning Preventing
// void *data;
// int size;
// err_code_t err_code = -100;
triggered_rrc = true;
int num;
//int num;
/* TODO do we need this at the current state? meas_stats is never put into a
* protobuf message?!
num = flexran_get_num_ues (mod_id);
meas_stats = malloc(sizeof(rrc_meas_stats) * num);
for (i = 0; i < num; i++){
meas_stats[i].rnti = flexran_get_ue_crnti(mod_id, i);
meas_stats[i].meas_id = flexran_get_rrc_pcell_measid(mod_id,i);
meas_stats[i].rsrp = flexran_get_rrc_pcell_rsrp(mod_id,i) - 140;
UE_id = flexran_get_ue_id(mod_id, i);
meas_stats[i].rnti = flexran_get_ue_crnti(mod_id, UE_id);
meas_stats[i].meas_id = flexran_get_rrc_pcell_measid(mod_id, UE_id);
meas_stats[i].rsrp = flexran_get_rrc_pcell_rsrp(mod_id, UE_id) - 140;
// measResults->measResultPCell.rsrpResult - 140;
meas_stats[i].rsrq = flexran_get_rrc_pcell_rsrq(mod_id,i)/2 - 20;
meas_stats[i].rsrq = flexran_get_rrc_pcell_rsrq(mod_id, UE_id)/2 - 20;
// (measResults->measResultPCell.rsrqResult)/2 - 20;
}
*/
// repl->neigh_meas = NULL;
// if (meas->measResultNeighCells != NULL) {
@@ -495,11 +499,14 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
// Protocol__FlexHeader *header;
int i,j;
int UE_id;
/* Allocate memory for list of UE reports */
if (report_config->nr_ue > 0) {
for (i = 0; i < report_config->nr_ue; i++) {
UE_id = flexran_get_ue_id(mod_id, i);
/* Check flag for creation of buffer status report */
if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RRC_MEASUREMENTS) {
@@ -511,14 +518,14 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
goto error;
protocol__flex_rrc_measurements__init(rrc_measurements);
rrc_measurements->measid = flexran_get_rrc_pcell_measid(mod_id,i);
rrc_measurements->has_measid = 1;
rrc_measurements->pcell_rsrp = flexran_get_rrc_pcell_rsrp(mod_id,i);
rrc_measurements->has_pcell_rsrp = 1;
rrc_measurements->pcell_rsrq = flexran_get_rrc_pcell_rsrq(mod_id,i);
rrc_measurements->has_pcell_rsrq = 1 ;
rrc_measurements->measid = flexran_get_rrc_pcell_measid(mod_id, UE_id);
rrc_measurements->has_measid = 1;
rrc_measurements->pcell_rsrp = flexran_get_rrc_pcell_rsrp(mod_id, UE_id);
rrc_measurements->has_pcell_rsrp = 1;
rrc_measurements->pcell_rsrq = flexran_get_rrc_pcell_rsrq(mod_id, UE_id);
rrc_measurements->has_pcell_rsrq = 1 ;
/* Target Cell, Neghibouring*/
@@ -529,7 +536,7 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
protocol__flex_neigh_cells_measurements__init(neigh_meas);
neigh_meas->n_eutra_meas = flexran_get_rrc_num_ncell(mod_id, i);
neigh_meas->n_eutra_meas = flexran_get_rrc_num_ncell(mod_id, UE_id);
Protocol__FlexEutraMeasurements **eutra_meas = NULL;
@@ -547,7 +554,7 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
protocol__flex_eutra_measurements__init(eutra_meas[j]);
eutra_meas[j]->phys_cell_id = flexran_get_rrc_neigh_phy_cell_id(mod_id, i, j);
eutra_meas[j]->phys_cell_id = flexran_get_rrc_neigh_phy_cell_id(mod_id, UE_id, j);
eutra_meas[j]->has_phys_cell_id = 1;
@@ -558,10 +565,10 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
protocol__flex_eutra_ref_signal_meas__init(meas_result);
meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, i, eutra_meas[j]->phys_cell_id);
meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, UE_id, eutra_meas[j]->phys_cell_id);
meas_result->has_rsrp = 1;
meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, i, eutra_meas[j]->phys_cell_id);
meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, UE_id, eutra_meas[j]->phys_cell_id);
meas_result->has_rsrq = 1;
eutra_meas[j]->meas_result = meas_result;
@@ -625,8 +632,10 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
for (i = 0; i < report_config->nr_ue; i++){
UE_id = flexran_get_ue_id(mod_id, i);
if (ue_report[i]->rrc_measurements->neigh_meas != NULL){
for (j = 0; j < flexran_get_rrc_num_ncell(mod_id, i); j++){
for (j = 0; j < flexran_get_rrc_num_ncell(mod_id, UE_id); j++){
free(ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]);
}
@@ -58,6 +58,87 @@ enum flex_qam {
FLEQ_MOD_64QAM = 1;
}
//
// 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_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
}
enum flex_dl_accounting_policy {
POL_FAIR = 0;
POL_GREEDY = 1;
POL_NUM = 2;
}
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;
}
//
// UE config related structures and enums
//
@@ -177,4 +258,4 @@ enum flex_ue_state_change_type {
FLUESC_ACTIVATED = 1;
FLUESC_DEACTIVATED = 2;
FLUESC_MOVED = 3;
}
}
@@ -43,6 +43,19 @@ message flex_cell_config {
optional uint32 eutra_band= 37; // operating band
optional int32 dl_pdsch_power = 38; // operating downlink power
optional int32 ul_pusch_power = 39; // operating uplink power
optional flex_slice_config slice_config = 42;
}
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;
}
message flex_ue_config {
@@ -82,6 +95,8 @@ message flex_ue_config {
repeated flex_scell_config scell_config = 28; // Secondary cells configuration
optional uint32 scell_deactivation_timer = 29;// Deactivation timer for secondary cell
optional uint64 imsi = 30;
optional uint32 dl_slice_id = 31;
optional uint32 ul_slice_id = 32;
}
message flex_lc_ue_config {
+56
View File
@@ -64,6 +64,8 @@ extern RAN_CONTEXT_t RC;
# define ENB_REGISTER_RETRY_DELAY 10
# endif
#include "targets/RT/USER/lte-softmodem.h"
/*------------------------------------------------------------------------------*/
/*
@@ -244,6 +246,10 @@ void *eNB_app_task(void *args_p)
LOG_I(ENB_APP, "Received %s\n", ITTI_MSG_NAME(msg_p));
break;
case SOFT_RESTART_MESSAGE:
handle_reconfiguration(instance);
break;
case S1AP_REGISTER_ENB_CNF:
# if defined(ENABLE_USE_MME)
LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
@@ -321,3 +327,53 @@ void *eNB_app_task(void *args_p)
return NULL;
}
void handle_reconfiguration(module_id_t mod_id)
{
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
flexran_agent_info_t *flexran = RC.flexran[mod_id];
LOG_I(ENB_APP, "lte-softmodem soft-restart requested\n");
if (ENB_WAIT == flexran->node_ctrl_state) {
/* this is already waiting, just release */
pthread_mutex_lock(&flexran->mutex_node_ctrl);
flexran->node_ctrl_state = ENB_NORMAL_OPERATION;
pthread_mutex_unlock(&flexran->mutex_node_ctrl);
pthread_cond_signal(&flexran->cond_node_ctrl);
return;
}
if (stop_L1L2(mod_id) < 0) {
LOG_E(ENB_APP, "can not stop lte-softmodem, aborting restart\n");
return;
}
/* node_ctrl_state should have value ENB_MAKE_WAIT only if this method is not
* executed by the FlexRAN thread */
if (ENB_MAKE_WAIT == flexran->node_ctrl_state) {
LOG_I(ENB_APP, " * eNB %d: Waiting for FlexRAN RTController command *\n", mod_id);
pthread_mutex_lock(&flexran->mutex_node_ctrl);
flexran->node_ctrl_state = ENB_WAIT;
while (ENB_NORMAL_OPERATION != flexran->node_ctrl_state)
pthread_cond_wait(&flexran->cond_node_ctrl, &flexran->mutex_node_ctrl);
pthread_mutex_unlock(&flexran->mutex_node_ctrl);
}
if (restart_L1L2(mod_id) < 0) {
LOG_E(ENB_APP, "can not restart, killing lte-softmodem\n");
itti_terminate_tasks(TASK_PHY_ENB);
return;
}
clock_gettime(CLOCK_MONOTONIC, &end);
end.tv_sec -= start.tv_sec;
if (end.tv_nsec >= start.tv_nsec) {
end.tv_nsec -= start.tv_nsec;
} else {
end.tv_sec -= 1;
end.tv_nsec = end.tv_nsec - start.tv_nsec + 1000000000;
}
LOG_I(ENB_APP, "lte-softmodem restart succeeded in %ld.%ld s\n", end.tv_sec, end.tv_nsec / 1000000);
}
+2 -2
View File
@@ -31,11 +31,11 @@
#define ENB_APP_H_
#include <stdint.h>
#include "platform_types.h"
void *eNB_app_task(void *args_p);
/* needed for flexran: start PHY and RRC when restarting */
void enb_app_start_phy_rrc(uint32_t enb_id_start, uint32_t enb_id_end);
void handle_reconfiguration(module_id_t mod_id);
#endif /* ENB_APP_H_ */
+43 -46
View File
@@ -101,54 +101,51 @@ void RCconfig_flexran()
ue_TimersAndConstants_t300, ue_TimersAndConstants_t301,
ue_TimersAndConstants_t310, ue_TimersAndConstants_t311,
ue_TimersAndConstants_n310, ue_TimersAndConstants_n311,
ue_TransmissionMode;
ue_TransmissionMode, ue_multiple_max;
int32_t ue_multiple_max = 0;
e_SL_CP_Len_r12 rxPool_sc_CP_Len;
e_SL_PeriodComm_r12 rxPool_sc_Period;
e_SL_CP_Len_r12 rxPool_data_CP_Len;
long rxPool_ResourceConfig_prb_Num;
long rxPool_ResourceConfig_prb_Start;
long rxPool_ResourceConfig_prb_End;
SL_OffsetIndicator_r12_PR rxPool_ResourceConfig_offsetIndicator_present;
long rxPool_ResourceConfig_offsetIndicator_choice;
SubframeBitmapSL_r12_PR rxPool_ResourceConfig_subframeBitmap_present;
char* rxPool_ResourceConfig_subframeBitmap_choice_bs_buf;
long rxPool_ResourceConfig_subframeBitmap_choice_bs_size;
long rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
//SIB19
//for discRxPool
SL_CP_Len_r12_t discRxPool_cp_Len;
e_SL_DiscResourcePool_r12__discPeriod_r12 discRxPool_discPeriod;
long discRxPool_numRetx;
long discRxPool_numRepetition;
long discRxPool_ResourceConfig_prb_Num;
long discRxPool_ResourceConfig_prb_Start;
long discRxPool_ResourceConfig_prb_End;
SL_OffsetIndicator_r12_PR discRxPool_ResourceConfig_offsetIndicator_present;
long discRxPool_ResourceConfig_offsetIndicator_choice;
SubframeBitmapSL_r12_PR discRxPool_ResourceConfig_subframeBitmap_present;
char* discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf;
long discRxPool_ResourceConfig_subframeBitmap_choice_bs_size;
long discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
//for discRxPoolPS
SL_CP_Len_r12_t discRxPoolPS_cp_Len;
e_SL_DiscResourcePool_r12__discPeriod_r12 discRxPoolPS_discPeriod;
long discRxPoolPS_numRetx;
long discRxPoolPS_numRepetition;
long discRxPoolPS_ResourceConfig_prb_Num;
long discRxPoolPS_ResourceConfig_prb_Start;
long discRxPoolPS_ResourceConfig_prb_End;
SL_OffsetIndicator_r12_PR discRxPoolPS_ResourceConfig_offsetIndicator_present;
long discRxPoolPS_ResourceConfig_offsetIndicator_choice;
SubframeBitmapSL_r12_PR discRxPoolPS_ResourceConfig_subframeBitmap_present;
char* discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf;
long discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size;
long discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
const char* rxPool_sc_CP_Len;
const char* rxPool_sc_Period;
const char* rxPool_data_CP_Len;
libconfig_int rxPool_ResourceConfig_prb_Num;
libconfig_int rxPool_ResourceConfig_prb_Start;
libconfig_int rxPool_ResourceConfig_prb_End;
const char* rxPool_ResourceConfig_offsetIndicator_present;
libconfig_int rxPool_ResourceConfig_offsetIndicator_choice;
const char* rxPool_ResourceConfig_subframeBitmap_present;
char* rxPool_ResourceConfig_subframeBitmap_choice_bs_buf;
libconfig_int rxPool_ResourceConfig_subframeBitmap_choice_bs_size;
libconfig_int rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
//SIB19
//for discRxPool
const char* discRxPool_cp_Len;
const char* discRxPool_discPeriod;
libconfig_int discRxPool_numRetx;
libconfig_int discRxPool_numRepetition;
libconfig_int discRxPool_ResourceConfig_prb_Num;
libconfig_int discRxPool_ResourceConfig_prb_Start;
libconfig_int discRxPool_ResourceConfig_prb_End;
const char* discRxPool_ResourceConfig_offsetIndicator_present;
libconfig_int discRxPool_ResourceConfig_offsetIndicator_choice;
const char* discRxPool_ResourceConfig_subframeBitmap_present;
char* discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf;
libconfig_int discRxPool_ResourceConfig_subframeBitmap_choice_bs_size;
libconfig_int discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
//for discRxPoolPS
const char* discRxPoolPS_cp_Len;
const char* discRxPoolPS_discPeriod;
libconfig_int discRxPoolPS_numRetx;
libconfig_int discRxPoolPS_numRepetition;
libconfig_int discRxPoolPS_ResourceConfig_prb_Num;
libconfig_int discRxPoolPS_ResourceConfig_prb_Start;
libconfig_int discRxPoolPS_ResourceConfig_prb_End;
const char* discRxPoolPS_ResourceConfig_offsetIndicator_present;
libconfig_int discRxPoolPS_ResourceConfig_offsetIndicator_choice;
const char* discRxPoolPS_ResourceConfig_subframeBitmap_present;
char* discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf;
libconfig_int discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size;
libconfig_int discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
/* get number of eNBs */
paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
@@ -292,7 +289,7 @@ void RCconfig_L1(void) {
LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_CC[0]=%d for init_eNB_afterRU()\n", __FUNCTION__, RC.nb_CC[0]);
LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_macrlc_inst:%d because used by mac_top_init_eNB()\n", __FUNCTION__, RC.nb_macrlc_inst);
mac_top_init_eNB();
//mac_top_init_eNB();
configure_nfapi_pnf(RC.eNB[j][0]->eth_params_n.remote_addr, RC.eNB[j][0]->eth_params_n.remote_portc, RC.eNB[j][0]->eth_params_n.my_addr, RC.eNB[j][0]->eth_params_n.my_portd, RC.eNB[j][0]->eth_params_n .remote_portd);
}
+125 -54
View File
@@ -37,6 +37,7 @@
#include "flexran_agent_ran_api.h"
//#include "PHY/extern.h"
#include "common/utils/LOG/log.h"
#include "flexran_agent_mac_internal.h"
//#include "SCHED/defs.h"
#include "RRC/LTE/rrc_extern.h"
@@ -287,6 +288,23 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
free(reply->cell_config[i]->si_config->si_message);
free(reply->cell_config[i]->si_config);
}
if (reply->cell_config[i]->slice_config != NULL) {
for (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 (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);
}
free(reply->cell_config[i]);
}
free(reply->cell_config);
@@ -396,8 +414,14 @@ int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol_
FILE *f;
f = fopen(target, "wb");
fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f);
fclose(f);
if (f) {
fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f);
fclose(f);
}
else {
LOG_W(FLEXRAN_AGENT, "[%d] can not write control delegation data to %s\n",
mod_id, target);
}
// long time_elapsed_nanos = timer_end(vartime);
*msg = NULL;
@@ -435,6 +459,7 @@ int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__Fl
xid = (lc_config_request_msg->header)->xid;
int i, j;
int UE_id;
Protocol__FlexLcConfigReply *lc_config_reply_msg;
lc_config_reply_msg = malloc(sizeof(Protocol__FlexLcConfigReply));
@@ -460,13 +485,15 @@ int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__Fl
lc_ue_config[i] = malloc(sizeof(Protocol__FlexLcUeConfig));
protocol__flex_lc_ue_config__init(lc_ue_config[i]);
UE_id = flexran_get_ue_id(mod_id, i);
lc_ue_config[i]->has_rnti = 1;
lc_ue_config[i]->rnti = flexran_get_ue_crnti(mod_id,i);
lc_ue_config[i]->rnti = flexran_get_ue_crnti(mod_id, UE_id);
//TODO: Set the number of LC configurations that will be reported for this UE
//Set this according to the current state of the UE. This is only a temporary fix
int status = 0;
status = mac_eNB_get_rrc_status(mod_id, flexran_get_ue_crnti(mod_id, i));
status = mac_eNB_get_rrc_status(mod_id, flexran_get_ue_crnti(mod_id, UE_id));
/* TODO needs to be revised and appropriate API to be implemented */
if (status < RRC_CONNECTED) {
lc_ue_config[i]->n_lc_config = 0;
@@ -489,14 +516,14 @@ int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__Fl
lc_config[j]->has_lcid = 1;
lc_config[j]->lcid = j+1;
int lcg = flexran_get_lcg(mod_id, i, j+1);
int lcg = flexran_get_lcg(mod_id, UE_id, j+1);
if (lcg >= 0 && lcg <= 3) {
lc_config[j]->has_lcg = 1;
lc_config[j]->lcg = flexran_get_lcg(mod_id, i,j+1);
lc_config[j]->lcg = flexran_get_lcg(mod_id, UE_id, j+1);
}
lc_config[j]->has_direction = 1;
lc_config[j]->direction = flexran_get_direction(i,j+1);
lc_config[j]->direction = flexran_get_direction(UE_id, j+1);
//TODO: Bearer type. One of FLQBT_* values. Currently only default bearer supported
lc_config[j]->has_qos_bearer_type = 1;
lc_config[j]->qos_bearer_type = PROTOCOL__FLEX_QOS_BEARER_TYPE__FLQBT_NON_GBR;
@@ -563,6 +590,7 @@ int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__Fl
xid = (ue_config_request_msg->header)->xid;
int i;
int UE_id;
Protocol__FlexUeConfigReply *ue_config_reply_msg;
ue_config_reply_msg = malloc(sizeof(Protocol__FlexUeConfigReply));
@@ -587,26 +615,31 @@ int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__Fl
ue_config[i] = malloc(sizeof(Protocol__FlexUeConfig));
protocol__flex_ue_config__init(ue_config[i]);
ue_config[i]->rnti = flexran_get_ue_crnti(mod_id,i);
UE_id = flexran_get_ue_id(mod_id, i);
ue_config[i]->rnti = flexran_get_ue_crnti(mod_id, UE_id);
ue_config[i]->has_rnti = 1;
ue_config[i]->imsi = flexran_get_ue_imsi(mod_id, i);
ue_config[i]->imsi = flexran_get_ue_imsi(mod_id, UE_id);
ue_config[i]->has_imsi = 1;
ue_config[i]->dl_slice_id = flexran_get_ue_dl_slice_id(mod_id, UE_id);
ue_config[i]->has_dl_slice_id = 1;
ue_config[i]->ul_slice_id = flexran_get_ue_ul_slice_id(mod_id, UE_id);
ue_config[i]->has_ul_slice_id = 1;
//TODO: Set the DRX configuration (optional)
//Not supported for now, so we do not set it
if (flexran_get_time_alignment_timer(mod_id,i) != -1) {
ue_config[i]->time_alignment_timer = flexran_get_time_alignment_timer(mod_id,i);
ue_config[i]->has_time_alignment_timer = 1;
if (flexran_get_time_alignment_timer(mod_id, UE_id) != -1) {
ue_config[i]->time_alignment_timer = flexran_get_time_alignment_timer(mod_id, UE_id);
ue_config[i]->has_time_alignment_timer = 1;
}
if (flexran_get_meas_gap_config(mod_id,i) != -1) {
ue_config[i]->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id,i);
ue_config[i]->has_meas_gap_config_pattern = 1;
if (flexran_get_meas_gap_config(mod_id, UE_id) != -1) {
ue_config[i]->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id, UE_id);
ue_config[i]->has_meas_gap_config_pattern = 1;
}
if (ue_config[i]->has_meas_gap_config_pattern == 1 &&
ue_config[i]->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
ue_config[i]->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id,i);
ue_config[i]->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
ue_config[i]->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id, UE_id);
ue_config[i]->has_meas_gap_config_sf_offset = 1;
}
//TODO: Set the SPS configuration (Optional)
@@ -618,77 +651,77 @@ int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__Fl
//TODO: Set the CQI configuration (Optional)
//We do not set it for now
if (flexran_get_ue_transmission_mode(mod_id,i) != -1) {
ue_config[i]->transmission_mode = flexran_get_ue_transmission_mode(mod_id,i);
if (flexran_get_ue_transmission_mode(mod_id, UE_id) != -1) {
ue_config[i]->transmission_mode = flexran_get_ue_transmission_mode(mod_id, UE_id);
ue_config[i]->has_transmission_mode = 1;
}
ue_config[i]->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id,i);
ue_config[i]->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id, UE_id);
ue_config[i]->has_ue_aggregated_max_bitrate_ul = 1;
ue_config[i]->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id,i);
ue_config[i]->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id, UE_id);
ue_config[i]->has_ue_aggregated_max_bitrate_dl = 1;
Protocol__FlexUeCapabilities *capabilities;
capabilities = malloc(sizeof(Protocol__FlexUeCapabilities));
protocol__flex_ue_capabilities__init(capabilities);
capabilities->has_half_duplex = 1;
capabilities->half_duplex = flexran_get_half_duplex(mod_id, i);
capabilities->half_duplex = flexran_get_half_duplex(mod_id, UE_id);
capabilities->has_intra_sf_hopping = 1;
capabilities->intra_sf_hopping = flexran_get_intra_sf_hopping(mod_id, i);
capabilities->intra_sf_hopping = flexran_get_intra_sf_hopping(mod_id, UE_id);
capabilities->has_type2_sb_1 = 1;
capabilities->type2_sb_1 = flexran_get_type2_sb_1(mod_id, i);
capabilities->type2_sb_1 = flexran_get_type2_sb_1(mod_id, UE_id);
capabilities->has_ue_category = 1;
capabilities->ue_category = flexran_get_ue_category(mod_id, i);
capabilities->ue_category = flexran_get_ue_category(mod_id, UE_id);
capabilities->has_res_alloc_type1 = 1;
capabilities->res_alloc_type1 = flexran_get_res_alloc_type1(mod_id, i);
capabilities->res_alloc_type1 = flexran_get_res_alloc_type1(mod_id, UE_id);
//Set the capabilites to the message
ue_config[i]->capabilities = capabilities;
if (flexran_get_ue_transmission_antenna(mod_id,i) != -1) {
if (flexran_get_ue_transmission_antenna(mod_id, UE_id) != -1) {
ue_config[i]->has_ue_transmission_antenna = 1;
ue_config[i]->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id,i);
ue_config[i]->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id, UE_id);
}
if (flexran_get_tti_bundling(mod_id,i) != -1) {
if (flexran_get_tti_bundling(mod_id, UE_id) != -1) {
ue_config[i]->has_tti_bundling = 1;
ue_config[i]->tti_bundling = flexran_get_tti_bundling(mod_id,i);
ue_config[i]->tti_bundling = flexran_get_tti_bundling(mod_id, UE_id);
}
if (flexran_get_maxHARQ_TX(mod_id,i) != -1) {
if (flexran_get_maxHARQ_TX(mod_id, UE_id) != -1) {
ue_config[i]->has_max_harq_tx = 1;
ue_config[i]->max_harq_tx = flexran_get_maxHARQ_TX(mod_id,i);
ue_config[i]->max_harq_tx = flexran_get_maxHARQ_TX(mod_id, UE_id);
}
if (flexran_get_beta_offset_ack_index(mod_id,i) != -1) {
ue_config[i]->has_beta_offset_ack_index = 1;
ue_config[i]->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id,i);
if (flexran_get_beta_offset_ack_index(mod_id, UE_id) != -1) {
ue_config[i]->has_beta_offset_ack_index = 1;
ue_config[i]->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id, UE_id);
}
if (flexran_get_beta_offset_ri_index(mod_id,i) != -1) {
if (flexran_get_beta_offset_ri_index(mod_id, UE_id) != -1) {
ue_config[i]->has_beta_offset_ri_index = 1;
ue_config[i]->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id,i);
ue_config[i]->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id, UE_id);
}
if (flexran_get_beta_offset_cqi_index(mod_id,i) != -1) {
if (flexran_get_beta_offset_cqi_index(mod_id, UE_id) != -1) {
ue_config[i]->has_beta_offset_cqi_index = 1;
ue_config[i]->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id,i);
ue_config[i]->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id, UE_id);
}
/* assume primary carrier */
if (flexran_get_ack_nack_simultaneous_trans(mod_id, i, 0) != -1) {
if (flexran_get_ack_nack_simultaneous_trans(mod_id, UE_id, 0) != -1) {
ue_config[i]->has_ack_nack_simultaneous_trans = 1;
ue_config[i]->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id, i, 0);
ue_config[i]->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id, UE_id, 0);
}
if (flexran_get_simultaneous_ack_nack_cqi(mod_id,i) != -1) {
if (flexran_get_simultaneous_ack_nack_cqi(mod_id, UE_id) != -1) {
ue_config[i]->has_simultaneous_ack_nack_cqi = 1;
ue_config[i]->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id,i);
ue_config[i]->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id, UE_id);
}
if (flexran_get_aperiodic_cqi_rep_mode(mod_id,i) != -1) {
if (flexran_get_aperiodic_cqi_rep_mode(mod_id, UE_id) != -1) {
ue_config[i]->has_aperiodic_cqi_rep_mode = 1;
int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id,i);
int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id, UE_id);
if (mode > 4) {
ue_config[i]->aperiodic_cqi_rep_mode = PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
} else {
@@ -696,26 +729,26 @@ int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__Fl
}
}
if (flexran_get_tdd_ack_nack_feedback_mode(mod_id, i) != -1) {
if (flexran_get_tdd_ack_nack_feedback_mode(mod_id, UE_id) != -1) {
ue_config[i]->has_tdd_ack_nack_feedback = 1;
ue_config[i]->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback_mode(mod_id,i);
ue_config[i]->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback_mode(mod_id, UE_id);
}
if(flexran_get_ack_nack_repetition_factor(mod_id, i) != -1) {
if(flexran_get_ack_nack_repetition_factor(mod_id, UE_id) != -1) {
ue_config[i]->has_ack_nack_repetition_factor = 1;
ue_config[i]->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id,i);
ue_config[i]->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id, UE_id);
}
if (flexran_get_extended_bsr_size(mod_id, i) != -1) {
if (flexran_get_extended_bsr_size(mod_id, UE_id) != -1) {
ue_config[i]->has_extended_bsr_size = 1;
ue_config[i]->extended_bsr_size = flexran_get_extended_bsr_size(mod_id,i);
ue_config[i]->extended_bsr_size = flexran_get_extended_bsr_size(mod_id, UE_id);
}
//TODO: Set carrier aggregation support (boolean)
ue_config[i]->has_ca_support = 0;
ue_config[i]->ca_support = 0;
ue_config[i]->has_pcell_carrier_index = 1;
ue_config[i]->pcell_carrier_index = UE_PCCID(mod_id, i);
ue_config[i]->pcell_carrier_index = UE_PCCID(mod_id, UE_id);
if(ue_config[i]->has_ca_support){
//TODO: Set cross carrier scheduling support (boolean)
ue_config[i]->has_cross_carrier_sched_support = 0;
@@ -830,8 +863,8 @@ int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__F
cell_conf[i] = malloc(sizeof(Protocol__FlexCellConfig));
protocol__flex_cell_config__init(cell_conf[i]);
cell_conf[i]->phy_cell_id = 1;
cell_conf[i]->has_phy_cell_id = flexran_get_cell_id(mod_id,i);
cell_conf[i]->phy_cell_id = flexran_get_cell_id(mod_id,i);
cell_conf[i]->has_phy_cell_id = 1;
cell_conf[i]->cell_id = i;
cell_conf[i]->has_cell_id = 1;
@@ -1030,6 +1063,10 @@ int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__F
cell_conf[i]->carrier_index = i;
cell_conf[i]->has_carrier_index = 1;
/* get a pointer to the config which is maintained in the agent throughout
* its lifetime */
cell_conf[i]->slice_config = flexran_agent_get_slice_config(mod_id);
}
enb_config_reply_msg->cell_config=cell_conf;
}
@@ -1090,5 +1127,39 @@ int flexran_agent_destroy_rrc_measurement(Protocol__FlexranMessage *msg){
return 0;
}
int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg)
{
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 (enb_config->cell_config[0]->slice_config) {
prepare_update_slice_config(mod_id, enb_config->cell_config[0]->slice_config);
} else {
initiate_soft_restart(mod_id, enb_config->cell_config[0]);
}
*msg = NULL;
return 0;
}
int flexran_agent_handle_ue_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg)
{
int i;
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
Protocol__FlexUeConfigReply *ue_config_reply = input->ue_config_reply_msg;
for (i = 0; i < ue_config_reply->n_ue_config; i++)
prepare_ue_slice_assoc_update(mod_id, ue_config_reply->ue_config[i]);
*msg = NULL;
return 0;
}
+15
View File
@@ -166,4 +166,19 @@ void flexran_agent_send_update_stats(mid_t mod_id);
err_code_t flexran_agent_enable_cont_stats_update(mid_t mod_id, xid_t xid, stats_request_config_t *stats_req) ;
err_code_t flexran_agent_disable_cont_stats_update(mid_t mod_id);
/* Handle a received eNB config reply message as an "order" to reconfigure. It
* does not come as a reconfiguration message as this is a "structured"
* ProtoBuf message (as opposed to "unstructured" YAML). There is no destructor
* since we do not reply to this message (yet). Instead, the controller has to
* issue another eNB config request message. */
int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg);
/* Handle a received UE config reply message as an "order" to reconfigure the
* association of a UE to a slice. It does not come as a reconfiguration
* message as this is a "structured" ProtoBuf message (as opposed to
* "unstructured" YAML). There is no destructor since we do not reply to this
* message (yet). Instead, the controller has to issue another eNB config
* request message. */
int flexran_agent_handle_ue_config_reply(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg);
#endif
@@ -31,9 +31,9 @@
#include "flexran_agent_common_internal.h"
#include "flexran_agent_mac_internal.h"
/* needed to soft-restart the lte-softmodem */
#include "targets/RT/USER/lte-softmodem.h"
#include "enb_app.h"
void handle_reconfiguration(mid_t mod_id)
{
@@ -589,3 +589,32 @@ int apply_parameter_modification(void *parameter, yaml_parser_t *parser) {
return -1;
}
void initiate_soft_restart(module_id_t mod_id, Protocol__FlexCellConfig *c)
{
uint8_t cc_id = c->has_cell_id ? c->cell_id : 0;
if (c->has_eutra_band) {
flexran_agent_set_operating_eutra_band(mod_id, cc_id, c->eutra_band);
LOG_I(ENB_APP, "Setting eutra_band to %d\n", c->eutra_band);
}
if (c->has_dl_freq && c->has_ul_freq) {
flexran_agent_set_operating_dl_freq(mod_id, cc_id, c->dl_freq);
LOG_I(ENB_APP, "Setting dl_freq to %d\n", c->dl_freq);
int32_t ul_freq_offset = c->ul_freq - c->dl_freq;
flexran_agent_set_operating_ul_freq(mod_id, cc_id, ul_freq_offset);
LOG_I(ENB_APP, "Setting ul_freq to %d\n", c->ul_freq);
}
if (c->has_dl_bandwidth) {
flexran_agent_set_operating_bandwidth(mod_id, cc_id, c->dl_bandwidth);
LOG_I(ENB_APP, "Setting bandwidth to %d\n", c->dl_bandwidth);
if (c->has_ul_bandwidth && c->ul_bandwidth != c->dl_bandwidth)
LOG_W(ENB_APP, "UL/DL bandwidth mismatch, applied DL bandwidth\n");
} else if (c->has_ul_bandwidth) {
flexran_agent_set_operating_bandwidth(mod_id, cc_id, c->ul_bandwidth);
LOG_I(ENB_APP, "Setting bandwidth to %d\n", c->ul_bandwidth);
}
MessageDef *msg;
msg = itti_alloc_new_message(TASK_FLEXRAN_AGENT, SOFT_RESTART_MESSAGE);
itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}
@@ -32,6 +32,7 @@
#include <yaml.h>
#include "flexran_agent_defs.h"
#include "flexran.pb-c.h"
int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length);
@@ -57,4 +58,7 @@ int skip_subsystem_parameters_config(yaml_parser_t *parser);
//that is not yet implmeneted in order to skip its configuration, without affecting the rest
int skip_parameter_modification(yaml_parser_t *parser);
// applies reconfiguration parameters and notifies ENB APP
void initiate_soft_restart(mid_t mod_id, Protocol__FlexCellConfig *c);
#endif
+8 -5
View File
@@ -46,9 +46,9 @@ flexran_agent_message_decoded_callback agent_messages_callback[][3] = {
{0, 0, 0}, /*PROTOCOK__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG*/
{flexran_agent_enb_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REQUEST_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG*/
{flexran_agent_handle_enb_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG*/
{flexran_agent_ue_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REQUEST_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG*/
{flexran_agent_handle_ue_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG*/
{flexran_agent_lc_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REQUEST_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REPLY_MSG*/
{flexran_agent_mac_handle_dl_mac_config, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG*/
@@ -210,6 +210,7 @@ int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__Flexr
//TODO: We do not deal with multiple CCs at the moment and eNB id is 0
int enb_id = mod_id;
int UE_id;
//eNB_MAC_INST *eNB = &eNB_mac_inst[enb_id];
//UE_list_t *eNB_UE_list= &eNB->UE_list;
@@ -249,8 +250,9 @@ int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__Flexr
goto error;
}
for (i = 0; i < report_config.nr_ue; i++) {
report_config.ue_report_type[i].ue_rnti = flexran_get_ue_crnti(enb_id, i); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].crnti;
report_config.ue_report_type[i].ue_report_flags = ue_flags;
UE_id = flexran_get_ue_id(mod_id, i);
report_config.ue_report_type[i].ue_rnti = flexran_get_ue_crnti(enb_id, UE_id); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].crnti;
report_config.ue_report_type[i].ue_report_flags = ue_flags;
}
//Set the number of CCs and create a list with the cell stats configs
report_config.nr_cc = MAX_NUM_CCs;
@@ -359,7 +361,8 @@ int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__Flexr
goto error;
}
for (i = 0; i < report_config.nr_ue; i++) {
report_config.ue_report_type[i].ue_rnti = ue_req->rnti[i];
UE_id = flexran_get_ue_id(mod_id, i);
report_config.ue_report_type[i].ue_rnti = ue_req->rnti[UE_id];
report_config.ue_report_type[i].ue_report_flags = ue_req->flags;
}
break;
+523 -39
View File
@@ -26,6 +26,7 @@
* \version 0.1
*/
#include <dlfcn.h>
#include "flexran_agent_ran_api.h"
static inline int phy_is_present(mid_t mod_id, uint8_t cc_id)
@@ -112,6 +113,21 @@ int flexran_get_num_ues(mid_t mod_id)
return RC.mac[mod_id]->UE_list.num_UEs;
}
int flexran_get_ue_id(mid_t mod_id, int i)
{
int n;
if (!mac_is_present(mod_id)) return 0;
/* get the (i+1)'th active UE */
for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) {
if (RC.mac[mod_id]->UE_list.active[n] == TRUE) {
if (i == 0)
return n;
--i;
}
}
return 0;
}
rnti_t flexran_get_ue_crnti(mid_t mod_id, mid_t ue_id)
{
return UE_RNTI(mod_id, ue_id);
@@ -1193,106 +1209,158 @@ void flexran_agent_set_operating_frame_type(mid_t mod_id, uint8_t cc_id, lte_fra
/*********** PDCP *************/
/*PDCP super frame counter flexRAN*/
uint32_t flexran_get_pdcp_sfn(const mid_t mod_id){
/* TODO the following is a hack. all the functions below should instead already
* receive the PDCP's uid and operate on it and the caller has the obligation
* to get the ID for this layer.
*/
static inline uint16_t flexran_get_pdcp_uid(mid_t mod_id, mid_t ue_id)
{
rnti_t rnti = flexran_get_ue_crnti(mod_id, ue_id);
if (rnti == NOT_A_RNTI) return 0;
for (uint16_t pdcp_uid = 0; pdcp_uid < MAX_MOBILES_PER_ENB; ++pdcp_uid) {
if (pdcp_enb[mod_id].rnti[pdcp_uid] == rnti)
return pdcp_uid;
}
return 0;
}
uint32_t flexran_get_pdcp_sfn(mid_t mod_id)
{
return pdcp_enb[mod_id].sfn;
}
/*PDCP super frame counter flexRAN*/
void flexran_set_pdcp_tx_stat_window(const mid_t mod_id, const mid_t ue_id, uint16_t obs_window){
void flexran_set_pdcp_tx_stat_window(mid_t mod_id, mid_t ue_id, uint16_t obs_window)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
if (obs_window > 0 ){
Pdcp_stats_tx_window_ms[mod_id][ue_id]=obs_window;
Pdcp_stats_tx_window_ms[mod_id][uid]=obs_window;
}
else{
Pdcp_stats_tx_window_ms[mod_id][ue_id]=1000;
Pdcp_stats_tx_window_ms[mod_id][uid]=1000;
}
}
/*PDCP super frame counter flexRAN*/
void flexran_set_pdcp_rx_stat_window(const mid_t mod_id, const mid_t ue_id, uint16_t obs_window){
void flexran_set_pdcp_rx_stat_window(mid_t mod_id, mid_t ue_id, uint16_t obs_window)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
if (obs_window > 0 ){
Pdcp_stats_rx_window_ms[mod_id][ue_id]=obs_window;
Pdcp_stats_rx_window_ms[mod_id][uid]=obs_window;
}
else{
Pdcp_stats_rx_window_ms[mod_id][ue_id]=1000;
Pdcp_stats_rx_window_ms[mod_id][uid]=1000;
}
}
/*PDCP num tx pdu status flexRAN*/
uint32_t flexran_get_pdcp_tx(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
if (mod_id <0 || mod_id> MAX_NUM_CCs || ue_id<0 || ue_id> MAX_MOBILES_PER_ENB || lcid<0 || lcid>NB_RB_MAX)
uint32_t flexran_get_pdcp_tx(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
if (mod_id < 0 || mod_id > MAX_NUM_CCs || ue_id < 0 || ue_id > MAX_MOBILES_PER_ENB
|| lcid < 0 || lcid > NB_RB_MAX)
return -1;
return Pdcp_stats_tx[mod_id][ue_id][lcid];
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx[mod_id][uid][lcid];
}
/*PDCP num tx bytes status flexRAN*/
uint32_t flexran_get_pdcp_tx_bytes(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_bytes[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_bytes(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_bytes[mod_id][uid][lcid];
}
/*PDCP number of transmit packet / second status flexRAN*/
uint32_t flexran_get_pdcp_tx_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_w[mod_id][uid][lcid];
}
/*PDCP throughput (bit/s) status flexRAN*/
uint32_t flexran_get_pdcp_tx_bytes_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_bytes_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_bytes_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_bytes_w[mod_id][uid][lcid];
}
/*PDCP tx sequence number flexRAN*/
uint32_t flexran_get_pdcp_tx_sn(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_sn[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_sn(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_sn[mod_id][uid][lcid];
}
/*PDCP tx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_tx_aiat(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_aiat[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_aiat(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_aiat[mod_id][uid][lcid];
}
/*PDCP tx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_tx_aiat_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_aiat_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_aiat_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_aiat_w[mod_id][uid][lcid];
}
/*PDCP num rx pdu status flexRAN*/
uint32_t flexran_get_pdcp_rx(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx[mod_id][uid][lcid];
}
/*PDCP num rx bytes status flexRAN*/
uint32_t flexran_get_pdcp_rx_bytes(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_bytes[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_bytes(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_bytes[mod_id][uid][lcid];
}
/*PDCP number of received packet / second flexRAN*/
uint32_t flexran_get_pdcp_rx_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_w[mod_id][uid][lcid];
}
/*PDCP gootput (bit/s) status flexRAN*/
uint32_t flexran_get_pdcp_rx_bytes_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_bytes_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_bytes_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_bytes_w[mod_id][uid][lcid];
}
/*PDCP rx sequence number flexRAN*/
uint32_t flexran_get_pdcp_rx_sn(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_sn[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_sn(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_sn[mod_id][uid][lcid];
}
/*PDCP rx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_rx_aiat(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_aiat[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_aiat(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_aiat[mod_id][uid][lcid];
}
/*PDCP rx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_rx_aiat_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_aiat_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_aiat_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_aiat_w[mod_id][uid][lcid];
}
/*PDCP num of received outoforder pdu status flexRAN*/
uint32_t flexran_get_pdcp_rx_oo(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_outoforder[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_outoforder[mod_id][uid][lcid];
}
/******************** RRC *****************************/
@@ -1393,3 +1461,419 @@ float flexran_get_rrc_neigh_rsrq(mid_t mod_id, mid_t ue_id, int cell_id)
if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult) return 0;
return RSRQ_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult)];
}
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id)
{
if (!mac_is_present(mod_id)) return -1;
int slice_idx = RC.mac[mod_id]->UE_list.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;
}
void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return;
if (flexran_get_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_list.assoc_dl_slice_idx[ue_id] = slice_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 = RC.mac[mod_id]->UE_list.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;
}
void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return;
if (flexran_get_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_list.assoc_ul_slice_idx[ue_id] = slice_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, 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_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;
}
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_list.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 sli->n_dl;
}
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;
}
int flexran_create_ul_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_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_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;
}
return -1;
}
int flexran_remove_ul_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_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_list.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]->slice_info.ul[slice_idx].sched_name)
free(RC.mac[mod_id]->slice_info.ul[slice_idx].sched_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;
}
+174 -18
View File
@@ -73,6 +73,10 @@ uint16_t flexran_get_future_sfn_sf(mid_t mod_id, int ahead_of_time);
/* Return the number of attached UEs */
int flexran_get_num_ues(mid_t mod_id);
/* Return the UE id of attached UE as opposed to the index [0,NUM UEs] (i.e.,
* the i'th active UE). Returns 0 if the i'th active UE could not be found. */
int flexran_get_ue_id(mid_t mod_id, int i);
/* Get the rnti of a UE with id ue_id */
rnti_t flexran_get_ue_crnti(mid_t mod_id, mid_t ue_id);
@@ -421,59 +425,59 @@ uint8_t flexran_get_rrc_status(mid_t mod_id, mid_t ue_id);
/***************************** PDCP ***********************/
/*PDCP superframe numberflexRAN*/
uint32_t flexran_get_pdcp_sfn(const mid_t mod_id);
uint32_t flexran_get_pdcp_sfn(mid_t mod_id);
/*PDCP pdcp tx stats window*/
void flexran_set_pdcp_tx_stat_window(const mid_t mod_id, const mid_t ue_id, uint16_t obs_window);
void flexran_set_pdcp_tx_stat_window(mid_t mod_id, mid_t ue_id, uint16_t obs_window);
/*PDCP pdcp rx stats window*/
void flexran_set_pdcp_rx_stat_window(const mid_t mod_id, const mid_t ue_id, uint16_t obs_window);
void flexran_set_pdcp_rx_stat_window(mid_t mod_id, mid_t ue_id, uint16_t obs_window);
/*PDCP num tx pdu status flexRAN*/
uint32_t flexran_get_pdcp_tx(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP num tx bytes status flexRAN*/
uint32_t flexran_get_pdcp_tx_bytes(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_bytes(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP number of transmit packet / second status flexRAN*/
uint32_t flexran_get_pdcp_tx_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP pdcp tx bytes in a given window flexRAN*/
uint32_t flexran_get_pdcp_tx_bytes_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_bytes_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP tx sequence number flexRAN*/
uint32_t flexran_get_pdcp_tx_sn(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_sn(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP tx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_tx_aiat(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_aiat(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP tx aggregated packet arrival per second flexRAN*/
uint32_t flexran_get_pdcp_tx_aiat_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_aiat_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP num rx pdu status flexRAN*/
uint32_t flexran_get_pdcp_rx(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP num rx bytes status flexRAN*/
uint32_t flexran_get_pdcp_rx_bytes(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_bytes(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP number of received packet / second flexRAN*/
uint32_t flexran_get_pdcp_rx_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP gootput (bit/s) status flexRAN*/
uint32_t flexran_get_pdcp_rx_bytes_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_bytes_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP rx sequence number flexRAN*/
uint32_t flexran_get_pdcp_rx_sn(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_sn(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP rx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_rx_aiat(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_aiat(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP rx aggregated packet arrival per second flexRAN*/
uint32_t flexran_get_pdcp_rx_aiat_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_aiat_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP num of received outoforder pdu status flexRAN*/
uint32_t flexran_get_pdcp_rx_oo(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*********************RRC**********************/
/*Get primary cell measuremeant id flexRAN*/
@@ -504,3 +508,155 @@ int flexran_get_rrc_neigh_plmn_mcc(mid_t mod_id, mid_t ue_id, int cell_id); */
/*Get MNC PLMN identity neighbouring Cell*/
/* currently not implemented
int flexran_get_rrc_neigh_plmn_mnc(mid_t mod_id, mid_t ue_id, int cell_id); */
/************************** Slice configuration **************************/
/* 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);
/* 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 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);
/* 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 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);
/* 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);
/* 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);
+12 -7
View File
@@ -733,7 +733,7 @@ rrc_mac_config_req_eNB(module_id_t Mod_idP,
if (RC.mac == NULL)
l2_init_eNB();
mac_top_init_eNB();
//mac_top_init_eNB();
RC.mac[Mod_idP]->common_channels[CC_idP].mib = mib;
RC.mac[Mod_idP]->common_channels[CC_idP].physCellId = physCellId;
@@ -852,16 +852,21 @@ rrc_mac_config_req_eNB(module_id_t Mod_idP,
LOG_E(MAC, "%s:%d:%s: ERROR, UE_id == -1\n", __FILE__,
__LINE__, __FUNCTION__);
} else {
if (logicalChannelConfig)
if (logicalChannelConfig) {
UE_list->
UE_template[CC_idP][UE_id].lcgidmap
[logicalChannelIdentity] =
*logicalChannelConfig->
ul_SpecificParameters->logicalChannelGroup;
else
UE_list->
UE_template[CC_idP][UE_id].lcgidmap
[logicalChannelIdentity] = 0;
ul_SpecificParameters->logicalChannelGroup;
UE_list->
UE_template[CC_idP][UE_id].lcgidpriority
[logicalChannelIdentity]=
logicalChannelConfig->ul_SpecificParameters->priority;
} else
UE_list->
UE_template[CC_idP][UE_id].lcgidmap
[logicalChannelIdentity] = 0;
}
}
+4
View File
@@ -703,6 +703,10 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP,
allocate_CCEs(module_idP, CC_id, frameP, subframeP, 2);
}
if (mac_agent_registered[module_idP] && subframeP == 9) {
flexran_agent_slice_update(module_idP);
}
stop_meas(&RC.mac[module_idP]->eNB_scheduler);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
File diff suppressed because it is too large Load Diff
+12 -11
View File
@@ -542,8 +542,9 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
uint16_t temp_total_rbs_count;
unsigned char temp_total_ue_count;
unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX];
uint8_t slice_allocation[MAX_NUM_CCs][N_RBG_MAX];
int UE_id, i;
uint16_t j;
uint16_t j,c;
uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
// uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
@@ -554,8 +555,6 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
uint8_t CC_id;
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
int N_RB_DL;
int transmission_mode = 0;
UE_sched_ctrl *ue_sched_ctl;
// int rrc_status = RRC_IDLE;
COMMON_channels_t *cc;
@@ -590,14 +589,14 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
dlsch_scheduler_pre_processor_reset(Mod_id,
UE_id,
CC_id,
0,
frameP,
subframeP,
N_RBG[CC_id],
min_rb_unit,
(uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required,
rballoc_sub,
MIMO_mode_indicator);
MIMO_mode_indicator,
mbsfn_flag);
}
}
@@ -621,7 +620,6 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
average_rbs_per_user[CC_id] = 0;
cc = &RC.mac[Mod_id]->common_channels[CC_id];
// Get total available RBS count and total UE count
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
temp_total_rbs_count = RC.mac[Mod_id]->eNB_stats[CC_id].available_prbs;
temp_total_ue_count = dlsch_ue_select[CC_id].ue_num;
@@ -658,19 +656,22 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
nb_rbs_required_remaining[CC_id][UE_id] = cmin(average_rbs_per_user[CC_id], dlsch_ue_select[CC_id].list[i].nb_rb);
}
transmission_mode = get_tmode(Mod_id,CC_id,UE_id);
/* slicing support has been introduced into the scheduler. Provide dummy
* data so that the preprocessor "simply works" */
for (c = 0; c < MAX_NUM_CCs; ++c)
for (j = 0; j < N_RBG_MAX; ++j)
slice_allocation[c][j] = 1;
LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n ");
dlsch_scheduler_pre_processor_allocate (Mod_id,
UE_id,
CC_id,
N_RBG[CC_id],
transmission_mode,
min_rb_unit[CC_id],
N_RB_DL,
(uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required,
(uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required_remaining,
rballoc_sub,
slice_allocation,
MIMO_mode_indicator);
temp_total_rbs_count -= ue_sched_ctl->pre_nb_available_rbs[CC_id];
temp_total_ue_count--;
+25 -12
View File
@@ -62,8 +62,6 @@ extern uint16_t frame_cnt;
extern RAN_CONTEXT_t RC;
extern int n_active_slices;
int choose(int n, int k)
{
int res = 1;
@@ -1853,7 +1851,7 @@ rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP)
return (rnti);
}
LOG_D(MAC, "[eNB %d] Couldn't find RNTI for UE %d\n", mod_idP, ue_idP);
//LOG_D(MAC, "[eNB %d] Couldn't find RNTI for UE %d\n", mod_idP, ue_idP);
//display_backtrace();
return (NOT_A_RNTI);
}
@@ -1963,6 +1961,9 @@ int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP, int harq_pidP
sizeof(eNB_UE_STATS));
UE_list->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0;
/* default slice in case there was something different */
UE_list->assoc_dl_slice_idx[UE_id] = 0;
UE_list->assoc_ul_slice_idx[UE_id] = 0;
UE_list->UE_sched_ctrl[UE_id].ta_update = 31;
@@ -4536,19 +4537,31 @@ harq_indication(module_id_t mod_idP, int CC_idP, frame_t frameP,
// Flexran Slicing functions
uint16_t flexran_nb_rbs_allowed_slice(float rb_percentage, int total_rbs)
uint16_t nb_rbs_allowed_slice(float rb_percentage, int total_rbs)
{
return (uint16_t) floor(rb_percentage * total_rbs);
}
int ue_slice_membership(int UE_id, int slice_id)
int ue_dl_slice_membership(module_id_t mod_id, int UE_id, int slice_idx)
{
if ((slice_id < 0) || (slice_id > n_active_slices))
LOG_W(MAC, "out of range slice id %d\n", slice_id);
if ((UE_id % n_active_slices) == slice_id) {
return 1; // this ue is a member of this slice
if ((slice_idx < 0)
|| (slice_idx >= RC.mac[mod_id]->slice_info.n_dl)) {
LOG_W(MAC, "out of range slice index %d (slice ID %d)\n",
slice_idx, RC.mac[mod_id]->slice_info.dl[slice_idx].id);
return 0;
}
return 0;
return RC.mac[mod_id]->UE_list.active[UE_id] == TRUE
&& RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[UE_id] == slice_idx;
}
int ue_ul_slice_membership(module_id_t mod_id, int UE_id, int slice_idx)
{
if ((slice_idx < 0)
|| (slice_idx >= RC.mac[mod_id]->slice_info.n_ul)) {
LOG_W(MAC, "out of range slice index %d (slice ID %d)\n",
slice_idx, RC.mac[mod_id]->slice_info.dl[slice_idx].id);
return 0;
}
return RC.mac[mod_id]->UE_list.active[UE_id] == TRUE
&& RC.mac[mod_id]->UE_list.assoc_ul_slice_idx[UE_id] == slice_idx;
}
+46 -158
View File
@@ -63,6 +63,9 @@
#include "T.h"
#include "common/ran_context.h"
extern RAN_CONTEXT_t RC;
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
@@ -72,46 +75,14 @@ extern uint16_t sfnsf_add_subframe(uint16_t frameP, uint16_t subframeP, int offs
extern int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req);
extern uint8_t nfapi_mode;
extern uint8_t nfapi_mode;
// This table holds the allowable PRB sizes for ULSCH transmissions
uint8_t rb_table[34] =
{ 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32,
36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80, 81, 90, 96, 100
};
/* number of active slices for past and current time*/
int n_active_slices_uplink = 1;
int n_active_slices_current_uplink = 1;
/* RB share for each slice for past and current time*/
float avg_slice_percentage_uplink=0.25;
float slice_percentage_uplink[MAX_NUM_SLICES] = {1.0, 0.0, 0.0, 0.0};
float slice_percentage_current_uplink[MAX_NUM_SLICES] = {1.0, 0.0, 0.0, 0.0};
float total_slice_percentage_uplink = 0;
float total_slice_percentage_current_uplink = 0;
// MAX MCS for each slice for past and current time
int slice_maxmcs_uplink[MAX_NUM_SLICES] = {20, 20, 20, 20};
int slice_maxmcs_current_uplink[MAX_NUM_SLICES] = {20,20,20,20};
/*resource blocks allowed*/
uint16_t nb_rbs_allowed_slice_uplink[MAX_NUM_CCs][MAX_NUM_SLICES];
/*Slice Update */
int update_ul_scheduler[MAX_NUM_SLICES] = {1, 1, 1, 1};
int update_ul_scheduler_current[MAX_NUM_SLICES] = {1, 1, 1, 1};
/* name of available scheduler*/
char *ul_scheduler_type[MAX_NUM_SLICES] = {"schedule_ulsch_rnti",
"schedule_ulsch_rnti",
"schedule_ulsch_rnti",
"schedule_ulsch_rnti"
};
extern mui_t rrc_eNB_mui;
/* Slice Function Pointer */
slice_scheduler_ul slice_sched_ul[MAX_NUM_SLICES] = {0};
void
rx_sdu(const module_id_t enb_mod_idP,
const int CC_idP,
@@ -432,10 +403,10 @@ rx_sdu(const module_id_t enb_mod_idP,
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid] = BSR_TABLE[bsr];
UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer =
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[0] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[1] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[2] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[3];
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3];
//UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer += UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer / 4;
RC.eNB[enb_mod_idP][CC_idP]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP] = (payload_ptr[0] & 0x3f);
@@ -466,10 +437,10 @@ rx_sdu(const module_id_t enb_mod_idP,
int bsr2 = ((payload_ptr[1] & 0x0F) << 2) | ((payload_ptr[2] & 0xC0) >> 6);
int bsr3 = payload_ptr[2] & 0x3F;
lcgid_updated[0] = 1;
lcgid_updated[1] = 1;
lcgid_updated[2] = 1;
lcgid_updated[3] = 1;
lcgid_updated[LCGID0] = 1;
lcgid_updated[LCGID1] = 1;
lcgid_updated[LCGID2] = 1;
lcgid_updated[LCGID3] = 1;
// update buffer info
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0] = BSR_TABLE[bsr0];
@@ -478,10 +449,10 @@ rx_sdu(const module_id_t enb_mod_idP,
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3] = BSR_TABLE[bsr3];
UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer =
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[0] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[1] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[2] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[3];
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3];
//UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer += UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer / 4;
LOG_D(MAC,
@@ -951,9 +922,10 @@ void
schedule_ulsch(module_id_t module_idP, frame_t frameP,
sub_frame_t subframeP)
{
uint16_t first_rb[MAX_NUM_CCs], i;
uint16_t first_rb[NFAPI_CC_MAX], i;
int CC_id;
eNB_MAC_INST *mac = RC.mac[module_idP];
slice_info_t *sli = &RC.mac[module_idP]->slice_info;
COMMON_channels_t *cc;
start_meas(&mac->schedule_ulsch);
@@ -1034,12 +1006,10 @@ schedule_ulsch(module_id_t module_idP, frame_t frameP,
break;
}
}
if (sched_subframe < subframeP) sched_frame++;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) {
//leave out first RB for PUCCH
first_rb[CC_id] = 1;
@@ -1066,102 +1036,9 @@ schedule_ulsch(module_id_t module_idP, frame_t frameP,
}
}
// perform slice-specifc operations
total_slice_percentage_uplink=0;
avg_slice_percentage_uplink=1.0/n_active_slices_uplink;
// reset the slice percentage for inactive slices
for (i = n_active_slices_uplink; i< MAX_NUM_SLICES; i++) {
slice_percentage_uplink[i]=0;
}
for (i = 0; i < n_active_slices_uplink; i++) {
if (slice_percentage_uplink[i] < 0 ){
LOG_W(MAC, "[eNB %d] frame %d subframe %d:invalid slice %d percentage %f. resetting to zero",
module_idP, frameP, subframeP, i, slice_percentage_uplink[i]);
slice_percentage_uplink[i]=0;
}
total_slice_percentage_uplink+=slice_percentage_uplink[i];
}
for (i = 0; i < n_active_slices_uplink; i++) {
// Load any updated functions
if (update_ul_scheduler[i] > 0 ) {
slice_sched_ul[i] = dlsym(NULL, ul_scheduler_type[i]);
update_ul_scheduler[i] = 0;
update_ul_scheduler_current[i] = 0;
//slice_percentage_current_uplink[i]= slice_percentage_uplink[i];
//total_slice_percentage_current_uplink+=slice_percentage_uplink[i];
//if (total_slice_percentage_current_uplink> 1)
//total_slice_percentage_current_uplink=1;
LOG_I(MAC,"update ul scheduler slice %d\n", i);
}
// the new total RB share is within the range
if (total_slice_percentage_uplink <= 1.0){
// check if the number of slices has changed, and log
if (n_active_slices_current_uplink != n_active_slices_uplink ){
if ((n_active_slices_uplink > 0) && (n_active_slices_uplink <= MAX_NUM_SLICES)) {
LOG_I(MAC,"[eNB %d]frame %d subframe %d: number of active UL slices has changed: %d-->%d\n",
module_idP, frameP, subframeP, n_active_slices_current_uplink, n_active_slices_uplink);
n_active_slices_current_uplink = n_active_slices_uplink;
} else {
LOG_W(MAC,"invalid number of UL slices %d, revert to the previous value %d\n",
n_active_slices_uplink, n_active_slices_current_uplink);
n_active_slices_uplink = n_active_slices_current_uplink;
}
}
// check if the slice rb share has changed, and log the console
if (slice_percentage_current_uplink[i] != slice_percentage_uplink[i]){
LOG_I(MAC,"[eNB %d][SLICE %d][UL] frame %d subframe %d: total percentage %f-->%f, slice RB percentage has changed: %f-->%f\n",
module_idP, i, frameP, subframeP, total_slice_percentage_current_uplink,
total_slice_percentage_uplink, slice_percentage_current_uplink[i], slice_percentage_uplink[i]);
total_slice_percentage_current_uplink = total_slice_percentage_uplink;
slice_percentage_current_uplink[i] = slice_percentage_uplink[i];
}
// check if the slice max MCS, and log the console
if (slice_maxmcs_current_uplink[i] != slice_maxmcs_uplink[i]){
if ((slice_maxmcs_uplink[i] >= 0) && (slice_maxmcs_uplink[i] <= 16)){
LOG_I(MAC,"[eNB %d][SLICE %d][UL] frame %d subframe %d: slice MAX MCS has changed: %d-->%d\n",
module_idP, i, frameP, subframeP, slice_maxmcs_current_uplink[i], slice_maxmcs_uplink[i]);
slice_maxmcs_current_uplink[i] = slice_maxmcs_uplink[i];
} else {
LOG_W(MAC,"[eNB %d][SLICE %d][UL] invalid slice max mcs %d, revert the previous value %d\n",
module_idP, i, slice_maxmcs_uplink[i],slice_maxmcs_current_uplink[i]);
slice_maxmcs_uplink[i] = slice_maxmcs_current_uplink[i];
}
}
// check if a new scheduler, and log the console
if (update_ul_scheduler_current[i] != update_ul_scheduler[i]){
LOG_I(MAC,"[eNB %d][SLICE %d][UL] frame %d subframe %d: UL scheduler for this slice is updated: %s \n",
module_idP, i, frameP, subframeP, ul_scheduler_type[i]);
update_ul_scheduler_current[i] = update_ul_scheduler[i];
}
} else {
if (n_active_slices_uplink == n_active_slices_current_uplink) {
LOG_W(MAC,"[eNB %d][SLICE %d][UL] invalid total RB share (%f->%f), reduce proportionally the RB share by 0.1\n",
module_idP, i, total_slice_percentage_current_uplink, total_slice_percentage_uplink);
if (slice_percentage_uplink[i] > avg_slice_percentage_uplink) {
slice_percentage_uplink[i] -= 0.1;
total_slice_percentage_uplink -= 0.1;
}
} else {
// here we can correct the values, e.g. reduce proportionally
LOG_W(MAC,"[eNB %d][SLICE %d][UL] invalid total RB share (%f->%f), revert the number of slice to its previous value (%d->%d)\n",
module_idP, i, total_slice_percentage_current_uplink,
total_slice_percentage_uplink, n_active_slices_uplink,
n_active_slices_current_uplink);
n_active_slices_uplink = n_active_slices_current_uplink;
slice_percentage_uplink[i] = slice_percentage_current_uplink[i];
}
}
for (i = 0; i < sli->n_ul; i++) {
// Run each enabled slice-specific schedulers one by one
slice_sched_ul[i](module_idP, i, frameP, subframeP, sched_subframe, first_rb);
sli->ul[i].sched_cb(module_idP, i, frameP, subframeP, sched_subframe, first_rb);
}
stop_meas(&mac->schedule_ulsch);
@@ -1169,7 +1046,7 @@ schedule_ulsch(module_id_t module_idP, frame_t frameP,
void
schedule_ulsch_rnti(module_id_t module_idP,
slice_id_t slice_id,
int slice_idx,
frame_t frameP,
sub_frame_t subframeP,
unsigned char sched_subframeP, uint16_t * first_rb)
@@ -1191,12 +1068,14 @@ schedule_ulsch_rnti(module_id_t module_idP,
eNB_MAC_INST *mac = RC.mac[module_idP];
COMMON_channels_t *cc = mac->common_channels;
UE_list_t *UE_list = &mac->UE_list;
slice_info_t *sli = &RC.mac[module_idP]->slice_info;
UE_TEMPLATE *UE_template;
UE_sched_ctrl *UE_sched_ctrl;
int sched_frame = frameP;
int rvidx_tab[4] = { 0, 2, 3, 1 };
uint16_t ul_req_index;
uint8_t dlsch_flag;
int first_rb_slice[NFAPI_CC_MAX];
if (sched_subframeP < subframeP)
sched_frame++;
@@ -1208,9 +1087,18 @@ schedule_ulsch_rnti(module_id_t module_idP,
nfapi_ul_config_request_t *ul_req_tmp = &mac->UL_req_tmp[CC_id][sched_subframeP];
nfapi_ul_config_request_body_t *ul_req_tmp_body = &ul_req_tmp->ul_config_request_body;
nfapi_ul_config_ulsch_harq_information *ulsch_harq_information;
//LOG_D(MAC, "entering ulsch preprocesor\n");
ulsch_scheduler_pre_processor(module_idP, slice_id, frameP, subframeP, sched_subframeP, first_rb);
for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; ++CC_id) {
N_RB_UL = to_prb(cc[CC_id].ul_Bandwidth);
UE_list->first_rb_offset[CC_id][slice_idx] = cmin(N_RB_UL, sli->ul[slice_idx].first_rb);
}
//LOG_D(MAC, "entering ulsch preprocesor\n");
ulsch_scheduler_pre_processor(module_idP, slice_idx, frameP, subframeP, sched_subframeP, first_rb);
for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; ++CC_id) {
first_rb_slice[CC_id] = first_rb[CC_id] + UE_list->first_rb_offset[CC_id][slice_idx];
}
//LOG_D(MAC, "exiting ulsch preprocesor\n");
hi_dci0_req->sfn_sf = (frameP << 4) + subframeP;
@@ -1219,7 +1107,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
for (UE_id = UE_list->head_ul; UE_id >= 0;
UE_id = UE_list->next_ul[UE_id]) {
if (!ue_slice_membership(UE_id, slice_id))
if (!ue_ul_slice_membership(module_idP, UE_id, slice_idx))
continue;
// don't schedule if Msg4 is not received yet
@@ -1296,7 +1184,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
}
/* be sure that there are some free RBs */
if (first_rb[CC_id] >= N_RB_UL - 1) {
if (first_rb_slice[CC_id] >= N_RB_UL - 1) {
LOG_W(MAC,
"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n",
module_idP, frameP, subframeP, UE_id, rnti, CC_id);
@@ -1407,7 +1295,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
UE_template->oldNDI_UL[harq_pid] = ndi;
UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power = normalized_rx_power;
UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power = target_rx_power;
UE_template->mcs_UL[harq_pid] = cmin(UE_template->pre_assigned_mcs_ul, slice_maxmcs_uplink[slice_id]);
UE_template->mcs_UL[harq_pid] = cmin(UE_template->pre_assigned_mcs_ul, sli->ul[slice_idx].maxmcs);
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1= UE_template->mcs_UL[harq_pid];
//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS
if (UE_template->pre_allocated_rb_table_index_ul >= 0) {
@@ -1421,7 +1309,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
// buffer_occupancy = UE_template->ul_total_buffer;
while (((rb_table[rb_table_index] > (N_RB_UL - 1 - first_rb[CC_id]))
while (((rb_table[rb_table_index] > (N_RB_UL - first_rb_slice[CC_id]))
|| (rb_table[rb_table_index] > 45))
&& (rb_table_index > 0)) {
rb_table_index--;
@@ -1438,7 +1326,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
T_INT(CC_id), T_INT(rnti), T_INT(frameP),
T_INT(subframeP), T_INT(harq_pid),
T_INT(UE_template->mcs_UL[harq_pid]),
T_INT(first_rb[CC_id]),
T_INT(first_rb_slice[CC_id]),
T_INT(rb_table[rb_table_index]),
T_INT(UE_template->TBS_UL[harq_pid]), T_INT(ndi));
@@ -1448,14 +1336,14 @@ schedule_ulsch_rnti(module_id_t module_idP,
module_idP, harq_pid, rnti, CC_id, frameP,
subframeP, UE_id,
UE_template->mcs_UL[harq_pid],
first_rb[CC_id], rb_table[rb_table_index],
first_rb_slice[CC_id], rb_table[rb_table_index],
rb_table_index,
UE_template->TBS_UL[harq_pid], harq_pid);
// bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
//store for possible retransmission
UE_template->nb_rb_ul[harq_pid] = rb_table[rb_table_index];
UE_template->first_rb_ul[harq_pid] = first_rb[CC_id];
UE_template->first_rb_ul[harq_pid] = first_rb_slice[CC_id];
UE_sched_ctrl->ul_scheduled |= (1 << harq_pid);
if (UE_id == UE_list->head)
@@ -1487,7 +1375,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb[CC_id];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb_slice[CC_id];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = rb_table[rb_table_index];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = UE_template->mcs_UL[harq_pid];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift;
@@ -1523,7 +1411,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
}
// Add UL_config PDUs
fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], cqi_req, cc, UE_template->physicalConfigDedicated, get_tmode(module_idP, CC_id, UE_id), mac->ul_handle, rnti, first_rb[CC_id], // resource_block_start
fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], cqi_req, cc, UE_template->physicalConfigDedicated, get_tmode(module_idP, CC_id, UE_id), mac->ul_handle, rnti, first_rb_slice[CC_id], // resource_block_start
rb_table[rb_table_index], // number_of_resource_blocks
UE_template->mcs_UL[harq_pid], cshift, // cyclic_shift_2_for_drms
0, // frequency_hopping_enabled_flag
@@ -1586,13 +1474,13 @@ schedule_ulsch_rnti(module_id_t module_idP,
LOG_D(MAC,"[PUSCH %d] SFN/SF:%04d%d UL_CFG:SFN/SF:%04d%d CQI:%d for UE %d/%x\n", harq_pid,frameP,subframeP,ul_sched_frame,ul_sched_subframeP,cqi_req,UE_id,rnti);
// increment first rb for next UE allocation
first_rb[CC_id] += rb_table[rb_table_index];
first_rb_slice[CC_id] += rb_table[rb_table_index];
} else { // round > 0 => retransmission
T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION,
T_INT(module_idP), T_INT(CC_id), T_INT(rnti),
T_INT(frameP), T_INT(subframeP), T_INT(harq_pid),
T_INT(UE_template->mcs_UL[harq_pid]),
T_INT(first_rb[CC_id]),
T_INT(first_rb_slice[CC_id]),
T_INT(rb_table[rb_table_index]), T_INT(round));
// Add UL_config PDUs
+123 -2
View File
@@ -159,7 +159,7 @@
#define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE)
/*!\brief maximum number of slices / groups */
#define MAX_NUM_SLICES 4
#define MAX_NUM_SLICES 10
#define U_PLANE_INACTIVITY_VALUE 6000
@@ -849,6 +849,9 @@ typedef struct {
/// LCGID mapping
long lcgidmap[11];
///UE logical channel priority
long lcgidpriority[11];
/// phr information
int8_t phr_info;
@@ -1099,6 +1102,10 @@ typedef struct {
/// Sorting criteria for the UE list in the MAC preprocessor
uint16_t sorting_criteria[MAX_NUM_SLICES][CR_NUM];
uint16_t first_rb_offset[NFAPI_CC_MAX][MAX_NUM_SLICES];
int assoc_dl_slice_idx[MAX_MOBILES_PER_ENB];
int assoc_ul_slice_idx[MAX_MOBILES_PER_ENB];
} UE_list_t;
@@ -1118,6 +1125,117 @@ typedef struct {
int tail_freelist; ///the tail position of the delete list
} UE_free_list_t;
/// Structure for saving the output of each pre_processor instance
typedef struct {
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX];
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX];
uint32_t bytes_lcid[MAX_MOBILES_PER_ENB][MAX_NUM_LCID];
uint32_t wb_pmi[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
uint8_t mcs[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
} pre_processor_results_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];
pre_processor_results_t pre_processor_results[MAX_NUM_SLICES];
/// common rb allocation list between slices
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX];
} slice_info_t;
/*! \brief eNB common channels */
typedef struct {
int physCellId;
@@ -1238,7 +1356,10 @@ typedef struct eNB_MAC_INST_s {
/// UL handle
uint32_t ul_handle;
UE_list_t UE_list;
/// slice-related configuration
slice_info_t slice_info;
///subband bitmap configuration
SBMAP_CONF sbmap_conf;
/// CCE table used to build DCI scheduling information
+80 -56
View File
@@ -36,22 +36,6 @@
* @{
*/
/**
* slice specific scheduler
*/
typedef void (*slice_scheduler_dl)(module_id_t mod_id,
slice_id_t slice_id,
frame_t frame,
sub_frame_t subframe,
int *mbsfn_flag);
typedef void (*slice_scheduler_ul)(module_id_t mod_id,
slice_id_t slice_id,
frame_t frame,
sub_frame_t subframe,
unsigned char sched_subframe,
uint16_t *first_rb);
/** \fn void schedule_mib(module_id_t module_idP,frame_t frameP,sub_frame_t subframe);
\brief MIB scheduling for PBCH. This function requests the MIB from RRC and provides it to L1.
@param Mod_id Instance ID of eNB
@@ -119,12 +103,12 @@ void schedule_ulsch(module_id_t module_idP, frame_t frameP,
/** \brief ULSCH Scheduling per RNTI
@param Mod_id Instance ID of eNB
@param slice_id Instance slice for this eNB
@param slice_idx Slice instance index for this eNB
@param frame Frame index
@param subframe Subframe number on which to act
@param sched_subframe Subframe number where PUSCH is transmitted (for DAI lookup)
*/
void schedule_ulsch_rnti(module_id_t module_idP, slice_id_t slice_idP, frame_t frameP,
void schedule_ulsch_rnti(module_id_t module_idP, int slice_idx, frame_t frameP,
sub_frame_t subframe,
unsigned char sched_subframe,
uint16_t * first_rb);
@@ -147,7 +131,7 @@ void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,i
void schedule_dlsch(module_id_t module_idP, frame_t frameP,
sub_frame_t subframe, int *mbsfn_flag);
void schedule_ue_spec(module_id_t module_idP, slice_id_t slice_idP,
void schedule_ue_spec(module_id_t module_idP, int slice_idxP,
frame_t frameP,sub_frame_t subframe, int *mbsfn_flag);
void schedule_ue_spec_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag);
@@ -181,6 +165,10 @@ void add_msg3(module_id_t module_idP, int CC_id, RA_t * ra, frame_t frameP,
//main.c
void init_UE_list(UE_list_t *UE_list);
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);
@@ -204,24 +192,11 @@ void mac_UE_out_of_sync_ind(module_id_t module_idP, frame_t frameP,
void clear_nfapi_information(eNB_MAC_INST * eNB, int CC_idP,
frame_t frameP, sub_frame_t subframeP);
void dlsch_scheduler_pre_processor_reset(int module_idP, int UE_id,
uint8_t CC_id,
int frameP,
int subframeP,
int N_RBG,
uint16_t
nb_rbs_required[NFAPI_CC_MAX]
[MAX_MOBILES_PER_ENB],
unsigned char
rballoc_sub[NFAPI_CC_MAX]
[N_RBG_MAX],
unsigned char
MIMO_mode_indicator[NFAPI_CC_MAX]
[N_RBG_MAX]);
// eNB functions
/* \brief This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
@param Mod_id Instance ID of eNB
@param slice_idxP Slice instance index for the slice in which scheduling happens
@param frame Index of frame
@param subframe Index of current subframe
@param N_RBS Number of resource block groups
@@ -229,24 +204,73 @@ void dlsch_scheduler_pre_processor_reset(int module_idP, int UE_id,
void dlsch_scheduler_pre_processor(module_id_t module_idP,
slice_id_t slice_idP,
frame_t frameP,
sub_frame_t subframe,
int N_RBG[NFAPI_CC_MAX],
int *mbsfn_flag);
int slice_idxP,
frame_t frameP,
sub_frame_t subframe,
int *mbsfn_flag,
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]);
void dlsch_scheduler_pre_processor_reset(module_id_t module_idP,
int slice_idx,
frame_t frameP,
sub_frame_t subframeP,
int min_rb_unit[NFAPI_CC_MAX],
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX],
int *mbsfn_flag);
void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id,
int slice_idx,
const uint8_t rbs_retx[NFAPI_CC_MAX]);
void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id,
int slice_idx,
frame_t frameP,
sub_frame_t subframeP,
int min_rb_unit[NFAPI_CC_MAX],
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]);
void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id,
int slice_idx,
int min_rb_unit[NFAPI_CC_MAX],
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]);
void dlsch_scheduler_pre_processor_intraslice_sharing(module_id_t Mod_id,
int slice_idx,
int min_rb_unit[NFAPI_CC_MAX],
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]);
void slice_priority_sort(module_id_t Mod_id, int slice_list[MAX_NUM_SLICES]);
void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id,
int frameP,
sub_frame_t subframeP,
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]);
void dlsch_scheduler_qos_multiplexing(module_id_t Mod_id,
int frameP,
sub_frame_t subframeP);
void dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id,
int UE_id,
uint8_t CC_id,
int N_RBG,
int transmission_mode,
int min_rb_unit,
uint8_t N_RB_DL,
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_required_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
unsigned char rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
unsigned char MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]);
int UE_id,
uint8_t CC_id,
int N_RBG,
int min_rb_unit,
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX],
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]);
/* \brief Function to trigger the eNB scheduling procedure. It is called by PHY at the beginning of each subframe, \f$n$\f
and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f.
@@ -676,8 +700,8 @@ int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti, int harq_pid
);
int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP);
void store_dlsch_buffer(module_id_t Mod_id, slice_id_t slice_id, frame_t frameP, sub_frame_t subframeP);
void assign_rbs_required(module_id_t Mod_id, slice_id_t slice_id, frame_t frameP, sub_frame_t subframe, uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], int min_rb_unit[NFAPI_CC_MAX]);
void store_dlsch_buffer(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframeP);
void assign_rbs_required(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframe, uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], int min_rb_unit[NFAPI_CC_MAX]);
int maxround(module_id_t Mod_id, uint16_t rnti, int frame,
sub_frame_t subframe, uint8_t ul_flag);
@@ -696,20 +720,20 @@ void set_ul_DAI(int module_idP,
int frameP,
int subframeP);
void ulsch_scheduler_pre_processor(module_id_t module_idP, slice_id_t slice_id, int frameP,
void ulsch_scheduler_pre_processor(module_id_t module_idP, int slice_idx, int frameP,
sub_frame_t subframeP,
unsigned char sched_subframeP,
uint16_t * first_rb);
void store_ulsch_buffer(module_id_t module_idP, int frameP,
sub_frame_t subframeP);
void sort_ue_ul(module_id_t module_idP, int frameP, sub_frame_t subframeP);
void assign_max_mcs_min_rb(module_id_t module_idP, int slice_id, int frameP,
void assign_max_mcs_min_rb(module_id_t module_idP, int slice_idx, int frameP,
sub_frame_t subframeP, uint16_t * first_rb);
void adjust_bsr_info(int buffer_occupancy, uint16_t TBS,
UE_TEMPLATE * UE_template);
int phy_stats_exist(module_id_t Mod_id, int rnti);
void sort_UEs(module_id_t Mod_idP, slice_id_t slice_id, int frameP, sub_frame_t subframeP);
void sort_UEs(module_id_t Mod_idP, int slice_idx, int frameP, sub_frame_t subframeP);
/*! \fn UE_L2_state_t ue_scheduler(const module_id_t module_idP,const frame_t frameP, const sub_frame_t subframe, const lte_subframe_t direction,const uint8_t eNB_index)
\brief UE scheduler where all the ue background tasks are done. This function performs the following: 1) Trigger PDCP every 5ms 2) Call RRC for link status return to PHY3) Perform SR/BSR procedures for scheduling feedback 4) Perform PHR procedures.
@@ -1244,9 +1268,9 @@ void pre_scd_nb_rbs_required( module_id_t module_idP,
#endif
/*Slice related functions */
uint16_t flexran_nb_rbs_allowed_slice(float rb_percentage, int total_rbs);
int ue_slice_membership(int UE_id, int slice_id);
uint16_t nb_rbs_allowed_slice(float rb_percentage, int total_rbs);
int ue_dl_slice_membership(module_id_t mod_id, int UE_id, int slice_idx);
int ue_ul_slice_membership(module_id_t mod_id, int UE_id, int slice_idx);
/* from here: prototypes to get rid of compilation warnings: doc to be written by function author */
uint8_t ul_subframe2_k_phich(COMMON_channels_t * cc, sub_frame_t ul_subframe);
+95 -77
View File
@@ -29,6 +29,7 @@
*/
#include <dlfcn.h>
#include "mac.h"
#include "mac_proto.h"
#include "mac_extern.h"
@@ -45,96 +46,113 @@
extern RAN_CONTEXT_t RC;
void init_UE_list(UE_list_t *UE_list)
{
int list_el;
UE_list->num_UEs = 0;
UE_list->head = -1;
UE_list->head_ul = -1;
UE_list->avail = 0;
for (list_el = 0; list_el < MAX_MOBILES_PER_ENB - 1; list_el++) {
UE_list->next[list_el] = list_el + 1;
UE_list->next_ul[list_el] = list_el + 1;
}
UE_list->next[list_el] = -1;
UE_list->next_ul[list_el] = -1;
memset(UE_list->DLSCH_pdu, 0, sizeof(UE_list->DLSCH_pdu));
memset(UE_list->UE_template, 0, sizeof(UE_list->UE_template));
memset(UE_list->eNB_UE_stats, 0, sizeof(UE_list->eNB_UE_stats));
memset(UE_list->UE_sched_ctrl, 0, sizeof(UE_list->UE_sched_ctrl));
memset(UE_list->active, 0, sizeof(UE_list->active));
memset(UE_list->assoc_dl_slice_idx, 0, sizeof(UE_list->assoc_dl_slice_idx));
memset(UE_list->assoc_ul_slice_idx, 0, sizeof(UE_list->assoc_ul_slice_idx));
}
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;
eNB_MAC_INST **mac;
module_id_t i, j;
int list_el;
UE_list_t *UE_list;
eNB_MAC_INST *mac;
LOG_I(MAC, "[MAIN] Init function start:nb_macrlc_inst=%d\n",
RC.nb_macrlc_inst);
LOG_I(MAC, "[MAIN] Init function start:nb_macrlc_inst=%d\n",
RC.nb_macrlc_inst);
if (RC.nb_macrlc_inst <= 0) {
RC.mac = NULL;
return;
}
if (RC.nb_macrlc_inst > 0) {
if (RC.mac == NULL){
RC.mac =
(eNB_MAC_INST **) malloc16(RC.nb_macrlc_inst *
sizeof(eNB_MAC_INST *));
bzero(RC.mac, RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *));
}
AssertFatal(RC.mac != NULL,
"can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n",
RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *),
RC.nb_macrlc_inst, sizeof(eNB_MAC_INST));
for (i = 0; i < RC.nb_macrlc_inst; i++) {
if (RC.mac[i] == NULL) {
RC.mac[i] = (eNB_MAC_INST *) malloc16(sizeof(eNB_MAC_INST));
AssertFatal(RC.mac[i] != NULL,
"can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n",
RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *),
RC.nb_macrlc_inst, sizeof(eNB_MAC_INST));
LOG_D(MAC,
"[MAIN] ALLOCATE %zu Bytes for %d eNB_MAC_INST @ %p\n",
sizeof(eNB_MAC_INST), RC.nb_macrlc_inst, RC.mac);
bzero(RC.mac[i], sizeof(eNB_MAC_INST));
}
RC.mac[i]->Mod_id = i;
for (j = 0; j < MAX_NUM_CCs; j++) {
RC.mac[i]->DL_req[j].dl_config_request_body.
dl_config_pdu_list = RC.mac[i]->dl_config_pdu_list[j];
RC.mac[i]->UL_req[j].ul_config_request_body.
ul_config_pdu_list = RC.mac[i]->ul_config_pdu_list[j];
for (int k = 0; k < 10; k++)
RC.mac[i]->UL_req_tmp[j][k].
ul_config_request_body.ul_config_pdu_list =
RC.mac[i]->ul_config_pdu_list_tmp[j][k];
for(int sf=0;sf<10;sf++){
RC.mac[i]->HI_DCI0_req[j][sf].hi_dci0_request_body.hi_dci0_pdu_list =RC.mac[i]->hi_dci0_pdu_list[j][sf];
}
RC.mac[i]->TX_req[j].tx_request_body.tx_pdu_list =
RC.mac[i]->tx_request_pdu[j];
RC.mac[i]->ul_handle = 0;
}
}
AssertFatal(rlc_module_init() == 0,
"Could not initialize RLC layer\n");
// These should be out of here later
pdcp_layer_init();
rrc_init_global_param();
} else {
RC.mac = NULL;
mac = malloc16(RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *));
AssertFatal(mac != NULL,
"can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n",
RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *),
RC.nb_macrlc_inst, sizeof(eNB_MAC_INST));
for (i = 0; i < RC.nb_macrlc_inst; i++) {
mac[i] = malloc16(sizeof(eNB_MAC_INST));
AssertFatal(mac[i] != NULL,
"can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n",
RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *),
RC.nb_macrlc_inst, sizeof(eNB_MAC_INST));
LOG_D(MAC,
"[MAIN] ALLOCATE %zu Bytes for %d eNB_MAC_INST @ %p\n",
sizeof(eNB_MAC_INST), RC.nb_macrlc_inst, mac);
bzero(mac[i], sizeof(eNB_MAC_INST));
mac[i]->Mod_id = i;
for (j = 0; j < MAX_NUM_CCs; j++) {
mac[i]->DL_req[j].dl_config_request_body.dl_config_pdu_list =
mac[i]->dl_config_pdu_list[j];
mac[i]->UL_req[j].ul_config_request_body.ul_config_pdu_list =
mac[i]->ul_config_pdu_list[j];
for (int k = 0; k < 10; k++)
mac[i]->UL_req_tmp[j][k].ul_config_request_body.ul_config_pdu_list =
mac[i]->ul_config_pdu_list_tmp[j][k];
for(int sf=0;sf<10;sf++)
mac[i]->HI_DCI0_req[j][sf].hi_dci0_request_body.hi_dci0_pdu_list =
mac[i]->hi_dci0_pdu_list[j][sf];
mac[i]->TX_req[j].tx_request_body.tx_pdu_list = mac[i]->tx_request_pdu[j];
mac[i]->ul_handle = 0;
}
// Initialize Linked-List for Active UEs
for (i = 0; i < RC.nb_macrlc_inst; i++) {
mac = RC.mac[i];
mac[i]->if_inst = IF_Module_init(i);
init_UE_list(&mac[i]->UE_list);
init_slice_info(&mac[i]->slice_info);
}
mac->if_inst = IF_Module_init(i);
RC.mac = mac;
UE_list = &mac->UE_list;
AssertFatal(rlc_module_init() == 0,
"Could not initialize RLC layer\n");
UE_list->num_UEs = 0;
UE_list->head = -1;
UE_list->head_ul = -1;
UE_list->avail = 0;
for (list_el = 0; list_el < MAX_MOBILES_PER_ENB - 1; list_el++) {
UE_list->next[list_el] = list_el + 1;
UE_list->next_ul[list_el] = list_el + 1;
}
UE_list->next[list_el] = -1;
UE_list->next_ul[list_el] = -1;
}
// These should be out of here later
pdcp_layer_init();
rrc_init_global_param();
}
void mac_init_cell_params(int Mod_idP, int CC_idP)
File diff suppressed because it is too large Load Diff
+34 -21
View File
@@ -169,6 +169,11 @@ boolean_t pdcp_data_req(
start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
}
for (pdcp_uid = 0; pdcp_uid < MAX_MOBILES_PER_ENB; ++pdcp_uid) {
if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti)
break;
}
// PDCP transparent mode for MBMS traffic
if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
@@ -366,13 +371,24 @@ boolean_t pdcp_data_req(
LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)pdcp_pdu_p->data,pdcp_pdu_size,
"[MSG] PDCP DL %s PDU on rb_id %d\n",(srb_flagP)? "CONTROL" : "DATA", rb_idP);
rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p
/* if RLC buffer for this UE has been full, we want to skip all subsequent
* traffic for TM_SKIP_FULL_BUF_MS ms. Afterwards, it will be checkd again */
if (pdcp_enb[ctxt_pP->module_id].time_buf_full[pdcp_uid] == 0
|| pdcp_enb[ctxt_pP->module_id].sfn - pdcp_enb[ctxt_pP->module_id].time_buf_full[pdcp_uid] >= TM_SKIP_FULL_BUF_MS) {
pdcp_enb[ctxt_pP->module_id].time_buf_full[pdcp_uid] = 0;
rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP,
confirmP, pdcp_pdu_size, pdcp_pdu_p
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
,sourceL2Id
,destinationL2Id
,sourceL2Id
,destinationL2Id
#endif
);
);
} else {
/* RLC would free pdcp_pdu_p, but since we skip it, have to do it
* ourselves and fake normal operation */
free_mem_block(pdcp_pdu_p, __func__);
rlc_status = RLC_OP_SKIPPED_FUL_BUF;
}
}
switch (rlc_status) {
@@ -383,18 +399,24 @@ boolean_t pdcp_data_req(
case RLC_OP_STATUS_BAD_PARAMETER:
LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
ret= FALSE;
break;
return FALSE;
case RLC_OP_STATUS_INTERNAL_ERROR:
LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
ret= FALSE;
break;
return FALSE;
case RLC_OP_STATUS_OUT_OF_RESSOURCES:
pdcp_enb[ctxt_pP->module_id].time_buf_full[pdcp_uid] = pdcp_enb[ctxt_pP->module_id].sfn;
LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
ret= FALSE;
break;
int h = TM_SKIP_FULL_BUF_MS;
LOG_W(PDCP, "Blocking incoming traffic for %d ms\n", h);
return FALSE;
case RLC_OP_SKIPPED_FUL_BUF:
LOG_D(PDCP, "Skipping RLC request due to full buffer\n");
/* fake good return so that GTP doesn't spam us and return immediately so
* that dropped traffic is not counted in PDCP traffic stats */
return TRUE;
default:
LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
@@ -408,16 +430,6 @@ boolean_t pdcp_data_req(
stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
}
/*
* Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
* so we return TRUE afterwards
*/
for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB;pdcp_uid++){
if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti )
break;
}
//LOG_I(PDCP,"ueid %d lcid %d tx seq num %d\n", pdcp_uid, rb_idP+rb_offset, current_sn);
Pdcp_stats_tx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
@@ -1066,6 +1078,7 @@ void pdcp_add_UE(const protocol_ctxt_t* const ctxt_pP){
if (pdcp_enb[ctxt_pP->module_id].rnti[i] == 0 ){
pdcp_enb[ctxt_pP->module_id].rnti[i]=ctxt_pP->rnti;
pdcp_enb[ctxt_pP->module_id].uid[i]=i;
pdcp_enb[ctxt_pP->module_id].time_buf_full[i] = 0;
pdcp_enb[ctxt_pP->module_id].num_ues++;
printf("add new uid is %d %x\n\n", i, ctxt_pP->rnti);
// ret=1;
+2
View File
@@ -106,6 +106,8 @@ typedef struct pdcp_enb_s {
uint16_t uid[MAX_MOBILES_PER_ENB];
rnti_t rnti[MAX_MOBILES_PER_ENB];
uint16_t num_ues;
#define TM_SKIP_FULL_BUF_MS (500)
uint64_t time_buf_full[MAX_MOBILES_PER_ENB];
uint64_t sfn;
frame_t frame;
+1
View File
@@ -67,6 +67,7 @@ typedef uint64_t hash_key_t;
#define RLC_OP_STATUS_BAD_PARAMETER 22
#define RLC_OP_STATUS_INTERNAL_ERROR 2
#define RLC_OP_STATUS_OUT_OF_RESSOURCES 3
#define RLC_OP_SKIPPED_FUL_BUF 4
#define RLC_MUI_UNDEFINED (mui_t)0
+3 -3
View File
@@ -6658,7 +6658,7 @@ rrc_eNB_decode_dcch(
//WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
if (rrc_agent_registered[ctxt_pP->module_id]) {
agent_rrc_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
agent_rrc_xface[ctxt_pP->module_id]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
ue_context_p->ue_id_rnti,
PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED);
}
@@ -6804,7 +6804,7 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
//WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
if (mac_agent_registered[ctxt_pP->module_id]) {
agent_rrc_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
agent_rrc_xface[ctxt_pP->module_id]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
ue_context_p->ue_id_rnti,
PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED);
}
@@ -6857,7 +6857,7 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
//WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
if (rrc_agent_registered[ctxt_pP->module_id]) {
agent_rrc_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
agent_rrc_xface[ctxt_pP->module_id]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
ue_context_p->ue_id_rnti,
PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED);
}
+1 -1
View File
@@ -75,7 +75,7 @@ extern uint32_t timeToTrigger_ms[16];
extern float RSRP_meas_mapping[98];
extern float RSRQ_meas_mapping[35];
extern UE_PF_PO_t UE_PF_PO[MAX_NUM_CCs][MAX_MOBILES_PER_ENB];
extern UE_PF_PO_t UE_PF_PO[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
extern pthread_mutex_t ue_pf_po_mutex;
extern uint16_t reestablish_rnti_map[MAX_MOBILES_PER_ENB][2];
+1 -1
View File
@@ -36,7 +36,7 @@
#include "COMMON/mac_rrc_primitives.h"
#include "LAYER2/MAC/mac.h"
UE_PF_PO_t UE_PF_PO[MAX_NUM_CCs][MAX_MOBILES_PER_ENB];
UE_PF_PO_t UE_PF_PO[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
pthread_mutex_t ue_pf_po_mutex;
UE_RRC_INST *UE_rrc_inst;
#include "LAYER2/MAC/mac_extern.h"
+20 -6
View File
@@ -781,10 +781,10 @@ static void* eNB_thread_prach( void* param ) {
while (!oai_exit) {
if (oai_exit) break;
if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
if (oai_exit) break;
LOG_D(PHY,"Running eNB prach procedures\n");
prach_procedures(eNB
@@ -822,10 +822,10 @@ static void* eNB_thread_prach_br( void* param ) {
while (!oai_exit) {
if (oai_exit) break;
if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"eNB_prach_thread_br") < 0) break;
if (oai_exit) break;
LOG_D(PHY,"Running eNB prach procedures for BL/CE UEs\n");
prach_procedures(eNB,1);
@@ -1029,8 +1029,10 @@ void kill_eNB_proc(int inst) {
proc = &eNB->proc;
proc_rxtx = &proc->proc_rxtx[0];
kill_td_thread(eNB);
kill_te_thread(eNB);
if(get_nprocs() > 2 && codingw) {
kill_td_thread(eNB);
kill_te_thread(eNB);
}
LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst );
for (i=0; i<2; i++) {
pthread_mutex_lock(&proc_rxtx[i].mutex_rxtx);
@@ -1039,8 +1041,10 @@ void kill_eNB_proc(int inst) {
pthread_cond_signal(&proc_rxtx[i].cond_rxtx);
pthread_mutex_unlock(&proc_rxtx[i].mutex_rxtx);
}
pthread_mutex_lock(&proc->mutex_prach);
proc->instance_cnt_prach = 0;
pthread_cond_signal( &proc->cond_prach );
pthread_mutex_unlock(&proc->mutex_prach);
pthread_cond_signal( &proc->cond_asynch_rxtx );
pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
@@ -1067,6 +1071,16 @@ void kill_eNB_proc(int inst) {
pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx );
pthread_cond_destroy( &proc_rxtx[i].cond_rxtx );
}
pthread_attr_destroy(&proc->attr_prach);
pthread_attr_destroy(&proc->attr_asynch_rxtx);
pthread_attr_destroy(&proc_rxtx[0].attr_rxtx);
pthread_attr_destroy(&proc_rxtx[1].attr_rxtx);
#ifdef Rel14
pthread_mutex_destroy(&proc->mutex_RU_PRACH_br);
pthread_attr_destroy(&proc->attr_prach_br);
#endif
}
}
@@ -1104,10 +1118,10 @@ void free_transport(PHY_VARS_eNB *eNB)
int j;
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
LOG_I(PHY, "Freeing Transport Channel Buffers for DLSCH, UE %d\n",i);
LOG_D(PHY, "Freeing Transport Channel Buffers for DLSCH, UE %d\n",i);
for (j=0; j<2; j++) free_eNB_dlsch(eNB->dlsch[i][j]);
LOG_I(PHY, "Freeing Transport Channel Buffer for ULSCH, UE %d\n",i);
LOG_D(PHY, "Freeing Transport Channel Buffer for ULSCH, UE %d\n",i);
free_eNB_ulsch(eNB->ulsch[1+i]);
}
free_eNB_ulsch(eNB->ulsch[0]);
+39 -44
View File
@@ -1080,8 +1080,8 @@ static void* ru_thread_prach( void* param ) {
while (!oai_exit) {
if (oai_exit) break;
if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
if (oai_exit) break;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 );
if (ru->eNB_list[0]){
prach_procedures(
@@ -1130,8 +1130,8 @@ static void* ru_thread_prach_br( void* param ) {
while (!oai_exit) {
if (oai_exit) break;
if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"ru_prach_thread_br") < 0) break;
if (oai_exit) break;
rx_prach(NULL,
ru,
NULL,
@@ -2230,11 +2230,36 @@ void init_RU_proc(RU_t *ru) {
}
void kill_RU_proc(int inst)
void kill_RU_proc(RU_t *ru)
{
RU_t *ru = RC.ru[inst];
RU_proc_t *proc = &ru->proc;
#if defined(PRE_SCD_THREAD)
pthread_mutex_lock(&proc->mutex_pre_scd);
ru->proc.instance_pre_scd = 0;
pthread_cond_signal(&proc->cond_pre_scd);
pthread_mutex_unlock(&proc->mutex_pre_scd);
pthread_join(proc->pthread_pre_scd, NULL);
pthread_mutex_destroy(&proc->mutex_pre_scd);
pthread_cond_destroy(&proc->cond_pre_scd);
#endif
#ifdef PHY_TX_THREAD
pthread_mutex_lock(&proc->mutex_phy_tx);
proc->instance_cnt_phy_tx = 0;
pthread_cond_signal(&proc->cond_phy_tx);
pthread_mutex_unlock(&proc->mutex_phy_tx);
pthread_join(ru->proc.pthread_phy_tx, NULL);
pthread_mutex_destroy( &proc->mutex_phy_tx);
pthread_cond_destroy( &proc->cond_phy_tx);
pthread_mutex_lock(&proc->mutex_rf_tx);
proc->instance_cnt_rf_tx = 0;
pthread_cond_signal(&proc->cond_rf_tx);
pthread_mutex_unlock(&proc->mutex_rf_tx);
pthread_join(proc->pthread_rf_tx, NULL);
pthread_mutex_destroy( &proc->mutex_rf_tx);
pthread_cond_destroy( &proc->cond_rf_tx);
#endif
if (get_nprocs() > 2 && fepw) {
LOG_D(PHY, "killing FEP thread\n");
kill_fep_thread(ru);
@@ -2271,8 +2296,10 @@ void kill_RU_proc(int inst)
pthread_mutex_lock(&proc->mutex_eNBs);
proc->ru_tx_ready = 0;
proc->instance_cnt_eNBs = 0;
pthread_cond_signal(&proc->cond_eNBs);
proc->instance_cnt_eNBs = 1;
// cond_eNBs is used by both ru_thread and ru_thread_tx, so we need to send
// a broadcast to wake up both threads
pthread_cond_broadcast(&proc->cond_eNBs);
pthread_mutex_unlock(&proc->mutex_eNBs);
pthread_mutex_lock(&proc->mutex_asynch_rxtx);
@@ -2280,10 +2307,12 @@ void kill_RU_proc(int inst)
pthread_cond_signal(&proc->cond_asynch_rxtx);
pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
/*LOG_D(PHY, "Joining pthread_FH\n");
LOG_D(PHY, "Joining pthread_FH\n");
pthread_join(proc->pthread_FH, NULL);
LOG_D(PHY, "Joining pthread_FHTX\n");
pthread_join(proc->pthread_FH1, NULL);*/
if (!single_thread_flag && get_nprocs() > 4) {
LOG_D(PHY, "Joining pthread_FHTX\n");
pthread_join(proc->pthread_FH1, NULL);
}
if (ru->function == NGFI_RRU_IF4p5) {
LOG_D(PHY, "Joining pthread_prach\n");
pthread_join(proc->pthread_prach, NULL);
@@ -2755,45 +2784,11 @@ void init_RU(char *rf_config_file) {
}
void stop_ru(RU_t *ru) {
#if defined(PRE_SCD_THREAD) || defined(PHY_TX_THREAD)
int *status;
#endif
printf("Stopping RU %p processing threads\n",(void*)ru);
#if defined(PRE_SCD_THREAD)
if(ru){
ru->proc.instance_pre_scd = 0;
pthread_cond_signal( &ru->proc.cond_pre_scd );
pthread_join(ru->proc.pthread_pre_scd, (void**)&status );
pthread_mutex_destroy(&ru->proc.mutex_pre_scd );
pthread_cond_destroy(&ru->proc.cond_pre_scd );
}
#endif
#ifdef PHY_TX_THREAD
if(ru){
ru->proc.instance_cnt_phy_tx = 0;
pthread_cond_signal(&ru->proc.cond_phy_tx);
pthread_join( ru->proc.pthread_phy_tx, (void**)&status );
pthread_mutex_destroy( &ru->proc.mutex_phy_tx );
pthread_cond_destroy( &ru->proc.cond_phy_tx );
ru->proc.instance_cnt_rf_tx = 0;
pthread_cond_signal(&ru->proc.cond_rf_tx);
pthread_join( ru->proc.pthread_rf_tx, (void**)&status );
pthread_mutex_destroy( &ru->proc.mutex_rf_tx );
pthread_cond_destroy( &ru->proc.cond_rf_tx );
}
#endif
}
void stop_RU(int nb_ru)
{
for (int inst = 0; inst < nb_ru; inst++) {
LOG_I(PHY, "Stopping RU %d processing threads\n", inst);
kill_RU_proc(inst);
kill_RU_proc(RC.ru[inst]);
}
}
+42 -83
View File
@@ -448,46 +448,22 @@ void *l2l1_task(void *arg) {
itti_set_task_real_time(TASK_L2L1);
itti_mark_task_ready(TASK_L2L1);
/* Wait for the initialize message */
printf("Wait for the ITTI initialize message\n");
do {
if (message_p != NULL) {
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
itti_receive_msg (TASK_L2L1, &message_p);
switch (ITTI_MSG_ID(message_p)) {
case INITIALIZE_MESSAGE:
/* Start eNB thread */
printf("L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
start_eNB = 1;
break;
case TERMINATE_MESSAGE:
printf("received terminate message\n");
oai_exit=1;
start_eNB = 0;
itti_exit_task ();
break;
default:
printf("Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
break;
}
} while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
/* ???? no else but seems to be UE only ???
do {
// Wait for a message
/* Wait for the initialize message */
printf("Wait for the ITTI initialize message\n");
while (1) {
itti_receive_msg (TASK_L2L1, &message_p);
switch (ITTI_MSG_ID(message_p)) {
case INITIALIZE_MESSAGE:
/* Start eNB thread */
LOG_D(PHY, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
start_eNB = 1;
break;
case TERMINATE_MESSAGE:
LOG_W(PHY, " *** Exiting L2L1 thread\n");
oai_exit=1;
start_eNB = 0;
itti_exit_task ();
break;
@@ -510,8 +486,9 @@ void *l2l1_task(void *arg) {
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
} while(!oai_exit);
*/
message_p = NULL;
};
return NULL;
}
#endif
@@ -772,12 +749,13 @@ void wait_eNBs(void) {
/*
* helper function to terminate a certain ITTI task
*/
void terminate_task(task_id_t task_id, module_id_t mod_id)
void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to)
{
LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id);
LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n",
itti_get_task_name(from), from, itti_get_task_name(to), to);
MessageDef *msg;
msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE);
itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
msg = itti_alloc_new_message (from, TERMINATE_MESSAGE);
itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}
extern void free_transport(PHY_VARS_eNB *);
@@ -786,39 +764,20 @@ extern void phy_free_RU(RU_t*);
int stop_L1L2(module_id_t enb_id)
{
LOG_W(ENB_APP, "stopping lte-softmodem\n");
oai_exit = 1;
if (!RC.ru) {
LOG_UI(ENB_APP, "no RU configured\n");
return -1;
}
/* stop trx devices, multiple carrier currently not supported by RU */
if (RC.ru[enb_id]) {
if (RC.ru[enb_id]->rfdevice.trx_stop_func) {
RC.ru[enb_id]->rfdevice.trx_stop_func(&RC.ru[enb_id]->rfdevice);
LOG_I(ENB_APP, "turned off RU rfdevice\n");
} else {
LOG_W(ENB_APP, "can not turn off rfdevice due to missing trx_stop_func callback, proceding anyway!\n");
}
if (RC.ru[enb_id]->ifdevice.trx_stop_func) {
RC.ru[enb_id]->ifdevice.trx_stop_func(&RC.ru[enb_id]->ifdevice);
LOG_I(ENB_APP, "turned off RU ifdevice\n");
} else {
LOG_W(ENB_APP, "can not turn off ifdevice due to missing trx_stop_func callback, proceding anyway!\n");
}
} else {
LOG_W(ENB_APP, "no RU found for index %d\n", enb_id);
return -1;
}
/* these tasks need to pick up new configuration */
terminate_task(TASK_RRC_ENB, enb_id);
terminate_task(TASK_L2L1, enb_id);
terminate_task(enb_id, TASK_ENB_APP, TASK_RRC_ENB);
terminate_task(enb_id, TASK_ENB_APP, TASK_L2L1);
oai_exit = 1;
LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
kill_RU_proc(RC.ru[enb_id]);
LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
kill_eNB_proc(enb_id);
LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
kill_RU_proc(enb_id);
oai_exit = 0;
for (int cc_id = 0; cc_id < RC.nb_CC[enb_id]; cc_id++) {
free_transport(RC.eNB[enb_id][cc_id]);
@@ -841,7 +800,9 @@ int restart_L1L2(module_id_t enb_id)
LOG_W(ENB_APP, "restarting lte-softmodem\n");
/* block threads */
pthread_mutex_lock(&sync_mutex);
sync_var = -1;
pthread_mutex_unlock(&sync_mutex);
for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) {
RC.eNB[enb_id][cc_id]->configured = 0;
@@ -852,6 +813,9 @@ int restart_L1L2(module_id_t enb_id)
/* TODO this should be done for all RUs associated to this eNB */
memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS));
set_function_spec_param(RC.ru[enb_id]);
/* reset the list of connected UEs in the MAC, since in this process with
* loose all UEs (have to reconnect) */
init_UE_list(&RC.mac[enb_id]->UE_list);
LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) {
@@ -1263,25 +1227,20 @@ int main( int argc, char **argv )
printf("stopping MODEM threads\n");
// cleanup
for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
stop_ru(RC.ru[ru_id]);
stop_eNB(NB_eNB_INST);
stop_RU(RC.nb_RU);
/* release memory used by the RU/eNB threads (incomplete), after all
* threads have been stopped (they partially use the same memory) */
for (int inst = 0; inst < NB_eNB_INST; inst++) {
for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) {
free_transport(RC.eNB[inst][cc_id]);
phy_free_lte_eNB(RC.eNB[inst][cc_id]);
}
}
stop_eNB(NB_eNB_INST);
stop_RU(RC.nb_RU);
/* release memory used by the RU/eNB threads (incomplete), after all
* threads have been stopped (they partially use the same memory) */
for (int inst = 0; inst < NB_eNB_INST; inst++) {
for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) {
free_transport(RC.eNB[inst][cc_id]);
phy_free_lte_eNB(RC.eNB[inst][cc_id]);
}
}
for (int inst = 0; inst < RC.nb_RU; inst++) {
phy_free_RU(RC.ru[inst]);
}
free_lte_top();
for (int inst = 0; inst < RC.nb_RU; inst++) {
phy_free_RU(RC.ru[inst]);
}
free_lte_top();
printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
end_configmodule();
+1 -1
View File
@@ -252,7 +252,7 @@ extern void init_RU(const char*);
extern void stop_ru(RU_t *ru);
extern void init_RU_proc(RU_t *ru);
extern void stop_RU(int nb_ru);
extern void kill_RU_proc(int inst);
extern void kill_RU_proc(RU_t *ru);
extern void set_function_spec_param(RU_t *ru);
// In lte-ue.c