Commit 2cb87ddd authored by Cedric Roux's avatar Cedric Roux
Browse files

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
parents 2c9be8c1 c1359a10
......@@ -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)
......
......@@ -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;
if (loader_data.shlibpath == NULL) {
loader_init();
}
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 (!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");
}
}
sprintf(afname,"%s_autoinit",modname);
fpi = dlsym(lib_handle,afname);
goto load_module_shlib_exit;
}
loader_data.shlibs[lib_idx].name = strdup(modname);
loader_data.shlibs[lib_idx].thisshlib_path = strdup(shlib_path);
}
if (fpi != NULL ) {
fpi(autoinit_arg);
}
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 (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;
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;
}
}
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 */
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)
......
......@@ -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);
}
......
/*
* 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)
......@@ -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"
......@@ -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
//-----------------------------------------------------------------------------
......
......@@ -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
......@@ -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_*/
/*
* 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;