Merge remote-tracking branch 'origin/develop_integration_2018_w36' into develop
Summary of changes: - work on flexran - work on X2 - new implementation of ITTI - code cleanup - bug fixes
This commit is contained in:
@@ -170,11 +170,12 @@ set(CMAKE_C_FLAGS
|
||||
"${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -std=gnu99 -Wall -Wstrict-prototypes -fno-strict-aliasing -rdynamic -funroll-loops -Wno-packed-bitfield-compat -fPIC ")
|
||||
# add autotools definitions that were maybe used!
|
||||
set(CMAKE_C_FLAGS
|
||||
"${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -DASN_DISABLE_OER_SUPPORT -D'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'"
|
||||
"${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -D'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'"
|
||||
)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 "
|
||||
"${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 -D'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'"
|
||||
)
|
||||
add_definitions("-DASN_DISABLE_OER_SUPPORT")
|
||||
|
||||
|
||||
#########################
|
||||
@@ -256,16 +257,13 @@ add_boolean_option(BASIC_SIMULATOR False "Has to be True when building the b
|
||||
add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering")
|
||||
|
||||
add_boolean_option(ENABLE_ITTI True "ITTI is internal messaging, should remain enabled for most targets")
|
||||
set (ITTI_DIR ${OPENAIR_DIR}/common/utils/itti)
|
||||
set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti)
|
||||
if (${ENABLE_ITTI})
|
||||
add_library(ITTI
|
||||
# add .h files if depend on (this one is generated)
|
||||
${ITTI_DIR}/intertask_interface.h
|
||||
${ITTI_DIR}/intertask_interface.c
|
||||
${ITTI_DIR}/backtrace.c
|
||||
${ITTI_DIR}/memory_pools.c
|
||||
${ITTI_DIR}/signals.c
|
||||
${ITTI_DIR}/timer.c
|
||||
${OCP_ITTI}/intertask_interface.cpp
|
||||
${OPENAIR_DIR}/common/utils/backtrace.c
|
||||
${OPENAIR_DIR}/common/utils/memory_pools.c
|
||||
)
|
||||
set(ITTI_LIB ITTI)
|
||||
set(GTPU_need_ITTI ${OPENAIR3_DIR}/GTPV1-U/gtpv1u_eNB.c)
|
||||
@@ -474,15 +472,15 @@ add_library(X2AP_LIB
|
||||
include_directories ("${X2AP_C_DIR}")
|
||||
include_directories ("${X2AP_DIR}")
|
||||
|
||||
#add_library(X2AP_ENB
|
||||
# ${X2AP_DIR}/x2ap_eNB.c
|
||||
add_library(X2AP_ENB
|
||||
${X2AP_DIR}/x2ap_eNB.c
|
||||
# ${X2AP_DIR}/x2ap_eNB_decoder.c
|
||||
# ${X2AP_DIR}/x2ap_eNB_encoder.c
|
||||
# ${X2AP_DIR}/x2ap_eNB_handler.c
|
||||
${X2AP_DIR}/x2ap_eNB_handler.c
|
||||
# ${X2AP_DIR}/x2ap_eNB_itti_messaging.c
|
||||
# ${X2AP_DIR}/x2ap_eNB_management_procedures.c
|
||||
${X2AP_DIR}/x2ap_eNB_management_procedures.c
|
||||
# ${X2AP_DIR}/x2ap_eNB_generate_messages.c
|
||||
# )
|
||||
)
|
||||
|
||||
# Hardware dependant options
|
||||
###################################
|
||||
@@ -754,11 +752,14 @@ include_directories("${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0")
|
||||
include_directories("${OPENAIR2_DIR}/RRC/LTE/MESSAGES")
|
||||
include_directories("${OPENAIR2_DIR}/RRC/LTE")
|
||||
include_directories("${OPENAIR_DIR}/common/utils")
|
||||
include_directories("${OPENAIR_DIR}/common/utils/itti")
|
||||
include_directories("${OPENAIR_DIR}/common/utils/ocp_itti")
|
||||
include_directories("${OPENAIR3_DIR}/NAS/COMMON")
|
||||
include_directories("${OPENAIR3_DIR}/NAS/COMMON/API/NETWORK")
|
||||
include_directories("${OPENAIR3_DIR}/NAS/COMMON/EMM/MSG")
|
||||
include_directories("${OPENAIR3_DIR}/NAS/COMMON/ESM/MSG")
|
||||
include_directories("${OPENAIR3_DIR}/NAS/UE/ESM")
|
||||
include_directories("${OPENAIR3_DIR}/NAS/UE/EMM")
|
||||
include_directories("${OPENAIR3_DIR}/NAS/UE/API/USER")
|
||||
include_directories("${OPENAIR3_DIR}/NAS/COMMON/IES")
|
||||
include_directories("${OPENAIR3_DIR}/NAS/COMMON/UTIL")
|
||||
include_directories("${OPENAIR3_DIR}/SECU")
|
||||
@@ -870,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)
|
||||
@@ -1115,6 +1117,7 @@ set(PHY_SRC
|
||||
# actual source
|
||||
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pss.c
|
||||
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss.c
|
||||
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss_gen.c
|
||||
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pilots.c
|
||||
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pilots_mbsfn.c
|
||||
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_coding.c
|
||||
@@ -1144,6 +1147,7 @@ set(PHY_SRC_RU
|
||||
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if5_tools.c
|
||||
${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_ul.c
|
||||
${OPENAIR1_DIR}/PHY/MODULATION/ul_7_5_kHz.c
|
||||
${OPENAIR1_DIR}/PHY/MODULATION/gen_75KHz.cpp
|
||||
${OPENAIR1_DIR}/PHY/MODULATION/beamforming.c
|
||||
${OPENAIR1_DIR}/PHY/MODULATION/compute_bf_weights.c
|
||||
${OPENAIR1_DIR}/PHY/INIT/lte_init_ru.c
|
||||
@@ -1154,6 +1158,7 @@ set(PHY_SRC_RU
|
||||
set(PHY_SRC_UE
|
||||
# actual source
|
||||
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/sss_ue.c
|
||||
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss_gen.c
|
||||
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c
|
||||
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c
|
||||
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c
|
||||
@@ -1942,7 +1947,7 @@ add_executable(lte-softmodem
|
||||
|
||||
target_link_libraries (lte-softmodem
|
||||
-Wl,--start-group
|
||||
RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2
|
||||
RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2
|
||||
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
|
||||
NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
|
||||
-Wl,--end-group z dl)
|
||||
@@ -2018,7 +2023,7 @@ add_executable(lte-uesoftmodem
|
||||
|
||||
target_link_libraries (lte-uesoftmodem
|
||||
-Wl,--start-group
|
||||
RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE SIMU
|
||||
RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE SIMU
|
||||
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES}
|
||||
NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
|
||||
-Wl,--end-group z dl)
|
||||
@@ -2135,7 +2140,7 @@ add_executable(test_epc_generate_scenario
|
||||
${OPENAIR3_DIR}/S1AP/s1ap_eNB_defs.h
|
||||
)
|
||||
target_link_libraries (test_epc_generate_scenario
|
||||
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
|
||||
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
|
||||
)
|
||||
|
||||
add_executable(test_epc_play_scenario
|
||||
@@ -2155,7 +2160,7 @@ add_executable(test_epc_play_scenario
|
||||
)
|
||||
target_include_directories(test_epc_play_scenario PUBLIC /usr/local/share/asn1c)
|
||||
target_link_libraries (test_epc_play_scenario
|
||||
-Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY_COMMON PHY PHY_UE LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
|
||||
-Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB X2AP_ENB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY_COMMON PHY PHY_UE LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
@@ -2191,7 +2196,7 @@ if (${T_TRACER})
|
||||
dlsim_tm4 dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim
|
||||
pdcchsim pucchsim prachsim syncsim ulsim
|
||||
#all "add_library" definitions
|
||||
ITTI RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB
|
||||
ITTI RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB
|
||||
oai_exmimodevif oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif
|
||||
oai_eth_transpro
|
||||
FLPT_MSG ASYNC_IF FLEXRAN_AGENT HASHTABLE MSC UTIL OMG_SUMO SECU_OSA
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <platform_types.h>
|
||||
#include "config_userapi.h"
|
||||
|
||||
|
||||
@@ -141,25 +142,16 @@ char defbool[2]="1";
|
||||
|
||||
int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix)
|
||||
{
|
||||
|
||||
|
||||
int c = config_get_if()->argc;
|
||||
int i,j;
|
||||
char *pp;
|
||||
char *cfgpath;
|
||||
int c = config_get_if()->argc;
|
||||
int i,j;
|
||||
char *pp;
|
||||
char cfgpath[512]; /* 512 should be enough for the sprintf below */
|
||||
|
||||
j = (prefix ==NULL) ? 0 : strlen(prefix);
|
||||
cfgpath = malloc( j + MAX_OPTNAME_SIZE +1);
|
||||
if (cfgpath == NULL) {
|
||||
fprintf(stderr,"[CONFIG] %s %i malloc error, %s\n", __FILE__, __LINE__,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
i = 0;
|
||||
while (c > 0 ) {
|
||||
char *oneargv = strdup(config_get_if()->argv[i]); /* we use strtok_r which modifies its string paramater, and we don't want argv to be modified */
|
||||
/* first check help options, either --help, -h or --help_<section> */
|
||||
/* first check help options, either --help, -h or --help_<section> */
|
||||
if (strncmp(oneargv, "-h",2) == 0 || strncmp(oneargv, "--help",6) == 0 ) {
|
||||
char *tokctx;
|
||||
pp=strtok_r(oneargv, "_",&tokctx);
|
||||
@@ -182,7 +174,7 @@ char *cfgpath;
|
||||
}
|
||||
}
|
||||
|
||||
/* now, check for non help options */
|
||||
/* now, check for non help options */
|
||||
if (oneargv[0] == '-') {
|
||||
for(int n=0;n<numoptions;n++) {
|
||||
if ( ( cfgoptions[n].paramflags & PARAMFLAG_DISABLECMDLINE) != 0) {
|
||||
@@ -223,9 +215,5 @@ char *cfgpath;
|
||||
c--;
|
||||
} /* fin du while */
|
||||
printf_cmdl("[CONFIG] %s %i options set from command line\n",((prefix == NULL) ? "(root)":prefix),j);
|
||||
free(cfgpath);
|
||||
return j;
|
||||
} /* parse_cmdline*/
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
#include <dlfcn.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <platform_types.h>
|
||||
#include "config_userapi.h"
|
||||
extern void exit_fun(const char* s); // lte-softmodem clean exit function
|
||||
|
||||
|
||||
configmodule_interface_t *config_get_if(void)
|
||||
|
||||
@@ -38,8 +38,6 @@
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
/* get rid of "exit_fun undeclared" warning */
|
||||
extern void exit_fun(const char* s);
|
||||
|
||||
#define CONFIG_GETSOURCE ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgmode )
|
||||
#define CONFIG_GETNUMP ( (config_get_if()==NULL) ? 0 : config_get_if()->num_cfgP )
|
||||
|
||||
@@ -91,8 +91,6 @@ int read_intarray(paramdef_t *cfgoptions,config_setting_t *setting, char *cfgpat
|
||||
|
||||
int config_libconfig_get(paramdef_t *cfgoptions,int numoptions, char *prefix )
|
||||
{
|
||||
|
||||
|
||||
config_setting_t *setting;
|
||||
char *str;
|
||||
int i,u;
|
||||
@@ -103,15 +101,9 @@ int config_libconfig_get(paramdef_t *cfgoptions,int numoptions, char *prefix )
|
||||
int notfound;
|
||||
int defval;
|
||||
int fatalerror=0;
|
||||
char *cfgpath; /* listname.[listindex].paramname */
|
||||
int numdefvals=0;
|
||||
|
||||
i = (prefix ==NULL) ? 0 : strlen(prefix);
|
||||
cfgpath = malloc( i+ MAX_OPTNAME_SIZE +1);
|
||||
if (cfgpath == NULL) {
|
||||
fprintf(stderr,"[LIBCONFIG] %s %i malloc error, %s\n", __FILE__, __LINE__,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
char cfgpath[512]; /* 512 should be enough for the sprintf below */
|
||||
|
||||
for(i=0;i<numoptions;i++) {
|
||||
|
||||
if (prefix != NULL) {
|
||||
@@ -253,7 +245,6 @@ int config_libconfig_get(paramdef_t *cfgoptions,int numoptions, char *prefix )
|
||||
config_libconfig_end();
|
||||
end_configmodule();
|
||||
}
|
||||
free(cfgpath);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -410,6 +410,7 @@ int logInit (void)
|
||||
|
||||
|
||||
register_log_component("S1AP","",S1AP);
|
||||
register_log_component("X2AP","",X2AP);
|
||||
|
||||
|
||||
register_log_component("SCTP","",SCTP);
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "assertions.h"
|
||||
#include "signals.h"
|
||||
|
||||
#include "vcd_signal_dumper.h"
|
||||
|
||||
|
||||
@@ -19,9 +19,72 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef UTILS_ASSERTIONS_H_
|
||||
#define UTILS_ASSERTIONS_H_
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#ifdef CMAKER
|
||||
#include <platform_types.h>
|
||||
#endif
|
||||
|
||||
#include "./itti/assertions.h"
|
||||
#if defined(ENB_MODE)
|
||||
# define display_backtrace()
|
||||
#else
|
||||
# include "backtrace.h"
|
||||
#endif
|
||||
|
||||
#endif /* UTILS_ASSERTIONS_H_ */
|
||||
#ifndef ASSERTIONS_H_
|
||||
#define ASSERTIONS_H_
|
||||
|
||||
void output_log_mem(void);
|
||||
#define _Assert_Exit_ \
|
||||
{ \
|
||||
fprintf(stderr, "\nExiting execution\n"); \
|
||||
display_backtrace(); \
|
||||
fflush(stdout); \
|
||||
fflush(stderr); \
|
||||
exit(EXIT_FAILURE); \
|
||||
}
|
||||
|
||||
#define _Assert_(cOND, aCTION, fORMAT, aRGS...) \
|
||||
do { \
|
||||
if (!(cOND)) { \
|
||||
fprintf(stderr, "\nAssertion ("#cOND") failed!\n" \
|
||||
"In %s() %s:%d\n" fORMAT, \
|
||||
__FUNCTION__, __FILE__, __LINE__, ##aRGS); \
|
||||
aCTION; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define AssertFatal(cOND, fORMAT, aRGS...) _Assert_(cOND, _Assert_Exit_, fORMAT, ##aRGS)
|
||||
|
||||
#define AssertError(cOND, aCTION, fORMAT, aRGS...) _Assert_(cOND, aCTION, fORMAT, ##aRGS)
|
||||
|
||||
|
||||
|
||||
#define DevCheck(cOND, vALUE1, vALUE2, vALUE3) \
|
||||
_Assert_(cOND, _Assert_Exit_, #vALUE1 ": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX "\n" #vALUE3 ": %" PRIdMAX "\n\n", \
|
||||
(intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3)
|
||||
|
||||
#define DevCheck4(cOND, vALUE1, vALUE2, vALUE3, vALUE4) \
|
||||
_Assert_(cOND, _Assert_Exit_, #vALUE1": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX "\n" #vALUE3 ": %" PRIdMAX "\n" #vALUE4 ": %" PRIdMAX "\n\n", \
|
||||
(intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3, (intmax_t)vALUE4)
|
||||
|
||||
#define DevParam(vALUE1, vALUE2, vALUE3) DevCheck(0, vALUE1, vALUE2, vALUE3)
|
||||
|
||||
#define DevAssert(cOND) _Assert_(cOND, _Assert_Exit_, "")
|
||||
|
||||
#define DevMessage(mESSAGE) _Assert_(0, _Assert_Exit_, #mESSAGE)
|
||||
|
||||
#define CHECK_INIT_RETURN(fCT) \
|
||||
do { \
|
||||
int fct_ret; \
|
||||
if ((fct_ret = (fCT)) != 0) { \
|
||||
fprintf(stderr, "Function "#fCT" has failed\n" \
|
||||
"returning %d\n", fct_ret); \
|
||||
fflush(stdout); \
|
||||
fflush(stderr); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* ASSERTIONS_H_ */
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
AM_CFLAGS = @ADD_CFLAGS@ \
|
||||
-I$(top_srcdir)/UTILS \
|
||||
-I$(top_srcdir)/COMMON \
|
||||
-I$(OPENAIR2_DIR)/UTIL/LFDS/liblfds6.1.1/liblfds611/inc \
|
||||
-DENABLE_EVENT_FD
|
||||
|
||||
noinst_LTLIBRARIES = libitti.la
|
||||
|
||||
BUILT_SOURCES = $(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/bin/liblfds611.a
|
||||
|
||||
$(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/bin/liblfds611.a:
|
||||
@if [ ! -d $(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/bin ]; then mkdir -p $(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/bin; fi;
|
||||
@if [ ! -d $(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/obj ]; then mkdir -p $(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/obj; fi;
|
||||
@$(MAKE) -C $(OPENAIR2_DIR)/UTIL/LFDS/liblfds6.1.1/liblfds611/ -f makefile.linux OUTDIR=$(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611
|
||||
|
||||
libitti_la_LDFLAGS = -all-static
|
||||
libitti_la_SOURCES = \
|
||||
gtpv1_u_messages_def.h gtpv1_u_messages_types.h \
|
||||
nas_messages_def.h nas_messages_types.h \
|
||||
timer_messages_def.h timer_messages_types.h \
|
||||
s11_messages_def.h s11_messages_types.h \
|
||||
s1ap_messages_def.h s1ap_messages_types.h \
|
||||
s6a_messages_def.h s6a_messages_types.h \
|
||||
sgw_lite_def.h sgw_lite_messages_types.h \
|
||||
sctp_messages_def.h sctp_messages_types.h \
|
||||
udp_message_def.h udp_messages_types.h \
|
||||
intertask_interface.c intertask_interface.h \
|
||||
intertask_interface_dump.c intertask_interface_dump.h \
|
||||
assertions.h \
|
||||
backtrace.c backtrace.h \
|
||||
signals.c signals.h \
|
||||
timer.c timer.h
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#ifdef CMAKER
|
||||
#include <platform_types.h>
|
||||
#endif
|
||||
|
||||
#if defined(ENB_MODE)
|
||||
# define display_backtrace()
|
||||
#else
|
||||
# include "backtrace.h"
|
||||
#endif
|
||||
|
||||
#ifndef ASSERTIONS_H_
|
||||
#define ASSERTIONS_H_
|
||||
|
||||
void output_log_mem(void);
|
||||
#define _Assert_Exit_ \
|
||||
{ \
|
||||
fprintf(stderr, "\nExiting execution\n"); \
|
||||
display_backtrace(); \
|
||||
fflush(stdout); \
|
||||
fflush(stderr); \
|
||||
exit(EXIT_FAILURE); \
|
||||
}
|
||||
|
||||
#define _Assert_(cOND, aCTION, fORMAT, aRGS...) \
|
||||
do { \
|
||||
if (!(cOND)) { \
|
||||
fprintf(stderr, "\nAssertion ("#cOND") failed!\n" \
|
||||
"In %s() %s:%d\n" fORMAT, \
|
||||
__FUNCTION__, __FILE__, __LINE__, ##aRGS); \
|
||||
aCTION; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define AssertFatal(cOND, fORMAT, aRGS...) _Assert_(cOND, _Assert_Exit_, fORMAT, ##aRGS)
|
||||
|
||||
#define AssertError(cOND, aCTION, fORMAT, aRGS...) _Assert_(cOND, aCTION, fORMAT, ##aRGS)
|
||||
|
||||
|
||||
|
||||
#define DevCheck(cOND, vALUE1, vALUE2, vALUE3) \
|
||||
_Assert_(cOND, _Assert_Exit_, #vALUE1 ": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX "\n" #vALUE3 ": %" PRIdMAX "\n\n", \
|
||||
(intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3)
|
||||
|
||||
#define DevCheck4(cOND, vALUE1, vALUE2, vALUE3, vALUE4) \
|
||||
_Assert_(cOND, _Assert_Exit_, #vALUE1": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX "\n" #vALUE3 ": %" PRIdMAX "\n" #vALUE4 ": %" PRIdMAX "\n\n", \
|
||||
(intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3, (intmax_t)vALUE4)
|
||||
|
||||
#define DevParam(vALUE1, vALUE2, vALUE3) DevCheck(0, vALUE1, vALUE2, vALUE3)
|
||||
|
||||
#define DevAssert(cOND) _Assert_(cOND, _Assert_Exit_, "")
|
||||
|
||||
#define DevMessage(mESSAGE) _Assert_(0, _Assert_Exit_, #mESSAGE)
|
||||
|
||||
#define CHECK_INIT_RETURN(fCT) \
|
||||
do { \
|
||||
int fct_ret; \
|
||||
if ((fct_ret = (fCT)) != 0) { \
|
||||
fprintf(stderr, "Function "#fCT" has failed\n" \
|
||||
"returning %d\n", fct_ret); \
|
||||
fflush(stdout); \
|
||||
fflush(stderr); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* ASSERTIONS_H_ */
|
||||
@@ -1,930 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
#if !defined(TRUE)
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#include "liblfds611.h"
|
||||
|
||||
#include "assertions.h"
|
||||
#include "intertask_interface.h"
|
||||
|
||||
#if T_TRACER
|
||||
#include "T.h"
|
||||
#endif
|
||||
|
||||
/* Includes "intertask_interface_init.h" to check prototype coherence, but
|
||||
* disable threads and messages information generation.
|
||||
*/
|
||||
#define CHECK_PROTOTYPE_ONLY
|
||||
#include "intertask_interface_init.h"
|
||||
#undef CHECK_PROTOTYPE_ONLY
|
||||
|
||||
#include "signals.h"
|
||||
#include "timer.h"
|
||||
|
||||
/* ITTI DEBUG groups */
|
||||
#define ITTI_DEBUG_POLL (1<<0)
|
||||
#define ITTI_DEBUG_SEND (1<<1)
|
||||
#define ITTI_DEBUG_EVEN_FD (1<<2)
|
||||
#define ITTI_DEBUG_INIT (1<<3)
|
||||
#define ITTI_DEBUG_EXIT (1<<4)
|
||||
#define ITTI_DEBUG_ISSUES (1<<5)
|
||||
#define ITTI_DEBUG_MP_STATISTICS (1<<6)
|
||||
|
||||
const int itti_debug = (ITTI_DEBUG_ISSUES | ITTI_DEBUG_MP_STATISTICS);
|
||||
|
||||
# define ITTI_DEBUG(m, x, args...) do { if ((m) & itti_debug) {fprintf(stdout, "[ITTI][D]"x, ##args); fflush (stdout);} } while(0);
|
||||
#define ITTI_ERROR(x, args...) do { fprintf(stdout, "[ITTI][E]"x, ##args); fflush (stdout); } while(0);
|
||||
|
||||
/* Global message size */
|
||||
#define MESSAGE_SIZE(mESSAGEiD) (sizeof(MessageHeader) + itti_desc.messages_info[mESSAGEiD].size)
|
||||
|
||||
|
||||
extern int emulate_rf;
|
||||
|
||||
typedef enum task_state_s {
|
||||
TASK_STATE_NOT_CONFIGURED, TASK_STATE_STARTING, TASK_STATE_READY, TASK_STATE_ENDED, TASK_STATE_MAX,
|
||||
} task_state_t;
|
||||
|
||||
/* This list acts as a FIFO of messages received by tasks (RRC, NAS, ...) */
|
||||
typedef struct message_list_s {
|
||||
MessageDef *msg; ///< Pointer to the message
|
||||
|
||||
message_number_t message_number; ///< Unique message number
|
||||
uint32_t message_priority; ///< Message priority
|
||||
} message_list_t;
|
||||
|
||||
typedef struct thread_desc_s {
|
||||
/* pthread associated with the thread */
|
||||
pthread_t task_thread;
|
||||
|
||||
/* State of the thread */
|
||||
volatile task_state_t task_state;
|
||||
|
||||
/* This fd is used internally by ITTI. */
|
||||
int epoll_fd;
|
||||
|
||||
/* The thread fd */
|
||||
int task_event_fd;
|
||||
|
||||
/* Number of events to monitor */
|
||||
uint16_t nb_events;
|
||||
|
||||
|
||||
/* Array of events monitored by the task.
|
||||
* By default only one fd is monitored (the one used to received messages
|
||||
* from other tasks).
|
||||
* More events can be suscribed later by the task itself.
|
||||
*/
|
||||
struct epoll_event *events;
|
||||
|
||||
int epoll_nb_events;
|
||||
|
||||
/* Flag to mark real time thread */
|
||||
unsigned real_time;
|
||||
|
||||
/* Counter to indicate that messages are pending for the thread */
|
||||
unsigned messages_pending;
|
||||
} thread_desc_t;
|
||||
|
||||
typedef struct task_desc_s {
|
||||
/* Queue of messages belonging to the task */
|
||||
struct lfds611_queue_state *message_queue;
|
||||
} task_desc_t;
|
||||
|
||||
typedef struct itti_desc_s {
|
||||
thread_desc_t *threads;
|
||||
task_desc_t *tasks;
|
||||
|
||||
/* Current message number. Incremented every call to send_msg_to_task */
|
||||
message_number_t message_number __attribute__((aligned(8)));
|
||||
|
||||
thread_id_t thread_max;
|
||||
task_id_t task_max;
|
||||
MessagesIds messages_id_max;
|
||||
|
||||
boolean_t thread_handling_signals;
|
||||
pthread_t thread_ref;
|
||||
|
||||
const task_info_t *tasks_info;
|
||||
const message_info_t *messages_info;
|
||||
|
||||
itti_lte_time_t lte_time;
|
||||
|
||||
int running;
|
||||
|
||||
volatile uint32_t created_tasks;
|
||||
volatile uint32_t ready_tasks;
|
||||
volatile int wait_tasks;
|
||||
} itti_desc_t;
|
||||
|
||||
static itti_desc_t itti_desc;
|
||||
|
||||
void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
|
||||
ptr = malloc (size);
|
||||
if (ptr) memset(ptr,0,size);
|
||||
|
||||
AssertFatal (ptr != NULL, "Memory allocation of %d bytes failed (%d -> %d)!\n", (int) size, origin_task_id, destination_task_id);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int itti_free(task_id_t task_id, void *ptr)
|
||||
{
|
||||
int result = EXIT_SUCCESS;
|
||||
AssertFatal (ptr != NULL, "Trying to free a NULL pointer (%d)!\n", task_id);
|
||||
|
||||
free (ptr);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static inline message_number_t itti_increment_message_number(void)
|
||||
{
|
||||
/* Atomic operation supported by GCC: returns the current message number
|
||||
* and then increment it by 1.
|
||||
* This can be done without mutex.
|
||||
*/
|
||||
return __sync_fetch_and_add (&itti_desc.message_number, 1);
|
||||
}
|
||||
|
||||
static inline uint32_t itti_get_message_priority(MessagesIds message_id)
|
||||
{
|
||||
AssertFatal (message_id < itti_desc.messages_id_max, "Message id (%d) is out of range (%d)!\n", message_id, itti_desc.messages_id_max);
|
||||
|
||||
return (itti_desc.messages_info[message_id].priority);
|
||||
}
|
||||
|
||||
const char *itti_get_message_name(MessagesIds message_id)
|
||||
{
|
||||
AssertFatal (message_id < itti_desc.messages_id_max, "Message id (%d) is out of range (%d)!\n", message_id, itti_desc.messages_id_max);
|
||||
|
||||
return (itti_desc.messages_info[message_id].name);
|
||||
}
|
||||
|
||||
const char *itti_get_task_name(task_id_t task_id)
|
||||
{
|
||||
if (itti_desc.task_max > 0) {
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)!\n", task_id, itti_desc.task_max);
|
||||
} else {
|
||||
return ("ITTI NOT INITIALIZED !!!");
|
||||
}
|
||||
|
||||
return (itti_desc.tasks_info[task_id].name);
|
||||
}
|
||||
|
||||
static task_id_t itti_get_current_task_id(void)
|
||||
{
|
||||
task_id_t task_id;
|
||||
thread_id_t thread_id;
|
||||
pthread_t thread = pthread_self ();
|
||||
|
||||
for (task_id = TASK_FIRST; task_id < itti_desc.task_max; task_id++) {
|
||||
thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
|
||||
if (itti_desc.threads[thread_id].task_thread == thread) {
|
||||
return task_id;
|
||||
}
|
||||
}
|
||||
|
||||
return TASK_UNKNOWN;
|
||||
}
|
||||
|
||||
void itti_update_lte_time(uint32_t frame, uint8_t slot)
|
||||
{
|
||||
itti_desc.lte_time.frame = frame;
|
||||
itti_desc.lte_time.slot = slot;
|
||||
}
|
||||
|
||||
int itti_send_broadcast_message(MessageDef *message_p)
|
||||
{
|
||||
task_id_t destination_task_id;
|
||||
task_id_t origin_task_id;
|
||||
thread_id_t origin_thread_id;
|
||||
uint32_t thread_id;
|
||||
int ret = 0;
|
||||
int result;
|
||||
|
||||
AssertFatal (message_p != NULL, "Trying to broadcast a NULL message!\n");
|
||||
|
||||
origin_task_id = message_p->ittiMsgHeader.originTaskId;
|
||||
origin_thread_id = TASK_GET_THREAD_ID(origin_task_id);
|
||||
|
||||
destination_task_id = TASK_FIRST;
|
||||
|
||||
for (thread_id = THREAD_FIRST; thread_id < itti_desc.thread_max; thread_id++) {
|
||||
MessageDef *new_message_p;
|
||||
|
||||
while (thread_id != TASK_GET_THREAD_ID(destination_task_id)) {
|
||||
destination_task_id++;
|
||||
}
|
||||
|
||||
/* Skip task that broadcast the message */
|
||||
if (thread_id != origin_thread_id) {
|
||||
/* Skip tasks which are not running */
|
||||
if (itti_desc.threads[thread_id].task_state == TASK_STATE_READY) {
|
||||
size_t size = sizeof(MessageHeader) + message_p->ittiMsgHeader.ittiMsgSize;
|
||||
new_message_p = itti_malloc( origin_task_id, destination_task_id, size );
|
||||
AssertFatal (new_message_p != NULL, "New message allocation failed!\n");
|
||||
|
||||
memcpy( new_message_p, message_p, size );
|
||||
result = itti_send_msg_to_task (destination_task_id, INSTANCE_DEFAULT, new_message_p);
|
||||
AssertFatal (result >= 0, "Failed to send message %d to thread %d (task %d)!\n", message_p->ittiMsgHeader.messageId, thread_id, destination_task_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
MessageDef *itti_alloc_new_message_sized(task_id_t origin_task_id, MessagesIds message_id, MessageHeaderSize size)
|
||||
{
|
||||
MessageDef *temp = NULL;
|
||||
|
||||
AssertFatal (message_id < itti_desc.messages_id_max, "Message id (%d) is out of range (%d)!\n", message_id, itti_desc.messages_id_max);
|
||||
|
||||
if (origin_task_id == TASK_UNKNOWN) {
|
||||
/* Try to identify real origin task ID */
|
||||
origin_task_id = itti_get_current_task_id();
|
||||
}
|
||||
|
||||
temp = itti_malloc (origin_task_id, TASK_UNKNOWN, sizeof(MessageHeader) + size);
|
||||
|
||||
temp->ittiMsgHeader.messageId = message_id;
|
||||
temp->ittiMsgHeader.originTaskId = origin_task_id;
|
||||
temp->ittiMsgHeader.ittiMsgSize = size;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
MessageDef *itti_alloc_new_message(task_id_t origin_task_id, MessagesIds message_id)
|
||||
{
|
||||
return itti_alloc_new_message_sized(origin_task_id, message_id, itti_desc.messages_info[message_id].size);
|
||||
}
|
||||
|
||||
int itti_send_msg_to_task(task_id_t destination_task_id, instance_t instance, MessageDef *message)
|
||||
{
|
||||
thread_id_t destination_thread_id;
|
||||
task_id_t origin_task_id;
|
||||
message_list_t *new;
|
||||
uint32_t priority;
|
||||
message_number_t message_number;
|
||||
uint32_t message_id;
|
||||
|
||||
AssertFatal (message != NULL, "Message is NULL!\n");
|
||||
AssertFatal (destination_task_id < itti_desc.task_max, "Destination task id (%d) is out of range (%d)\n", destination_task_id, itti_desc.task_max);
|
||||
|
||||
destination_thread_id = TASK_GET_THREAD_ID(destination_task_id);
|
||||
message->ittiMsgHeader.destinationTaskId = destination_task_id;
|
||||
message->ittiMsgHeader.instance = instance;
|
||||
message->ittiMsgHeader.lte_time.frame = itti_desc.lte_time.frame;
|
||||
message->ittiMsgHeader.lte_time.slot = itti_desc.lte_time.slot;
|
||||
message_id = message->ittiMsgHeader.messageId;
|
||||
AssertFatal (message_id < itti_desc.messages_id_max, "Message id (%d) is out of range (%d)!\n", message_id, itti_desc.messages_id_max);
|
||||
|
||||
origin_task_id = ITTI_MSG_ORIGIN_ID(message);
|
||||
|
||||
priority = itti_get_message_priority (message_id);
|
||||
|
||||
/* Increment the global message number */
|
||||
message_number = itti_increment_message_number ();
|
||||
|
||||
if (destination_task_id != TASK_UNKNOWN) {
|
||||
|
||||
if (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_ENDED ||
|
||||
itti_desc.threads[destination_thread_id].task_state == TASK_STATE_NOT_CONFIGURED) {
|
||||
ITTI_DEBUG(ITTI_DEBUG_ISSUES, " Message %s, number %lu with priority %d can not be sent from %s to queue (%u:%s), unconfigured or ended destination task!\n",
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_number,
|
||||
priority,
|
||||
itti_get_task_name(origin_task_id),
|
||||
destination_task_id,
|
||||
itti_get_task_name(destination_task_id));
|
||||
} else {
|
||||
if(!emulate_rf){
|
||||
/* We cannot send a message if the task is not running */
|
||||
AssertFatal (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_READY,
|
||||
"Task %s Cannot send message %s (%d) to thread %d, it is not in ready state (%d)!\n",
|
||||
itti_get_task_name(origin_task_id),
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_id,
|
||||
destination_thread_id,
|
||||
itti_desc.threads[destination_thread_id].task_state);
|
||||
}
|
||||
|
||||
/* Allocate new list element */
|
||||
new = (message_list_t *) itti_malloc (origin_task_id, destination_task_id, sizeof(struct message_list_s));
|
||||
|
||||
/* Fill in members */
|
||||
new->msg = message;
|
||||
new->message_number = message_number;
|
||||
new->message_priority = priority;
|
||||
|
||||
/* Enqueue message in destination task queue */
|
||||
if (lfds611_queue_enqueue(itti_desc.tasks[destination_task_id].message_queue, new) == 0) {
|
||||
AssertFatal(0, "Error: lfds611_queue_enqueue returns 0, queue is full, exiting\n");
|
||||
}
|
||||
|
||||
{
|
||||
/* Only use event fd for tasks, subtasks will pool the queue */
|
||||
if (TASK_GET_PARENT_TASK_ID(destination_task_id) == TASK_UNKNOWN) {
|
||||
ssize_t write_ret;
|
||||
eventfd_t sem_counter = 1;
|
||||
|
||||
/* Call to write for an event fd must be of 8 bytes */
|
||||
write_ret = write (itti_desc.threads[destination_thread_id].task_event_fd, &sem_counter, sizeof(sem_counter));
|
||||
AssertFatal (write_ret == sizeof(sem_counter), "Write to task message FD (%d) failed (%d/%d)\n",
|
||||
destination_thread_id, (int) write_ret, (int) sizeof(sem_counter));
|
||||
}
|
||||
}
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_SEND, " Message %s, number %lu with priority %d successfully sent from %s to queue (%u:%s)\n",
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_number,
|
||||
priority,
|
||||
itti_get_task_name(origin_task_id),
|
||||
destination_task_id,
|
||||
itti_get_task_name(destination_task_id));
|
||||
}
|
||||
} else {
|
||||
/* This is a debug message to TASK_UNKNOWN, we can release safely release it */
|
||||
int result = itti_free(origin_task_id, message);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* same as itti_send_msg_to_task but returns -1 in case of failure instead of crashing */
|
||||
/* TODO: this is a hack - the whole logic needs a proper rework. */
|
||||
/* look for HACK_RLC_UM_LIMIT for others places related to the hack. Please do not remove this comment. */
|
||||
int itti_try_send_msg_to_task(task_id_t destination_task_id, instance_t instance, MessageDef *message)
|
||||
{
|
||||
thread_id_t destination_thread_id;
|
||||
task_id_t origin_task_id;
|
||||
message_list_t *new;
|
||||
uint32_t priority;
|
||||
message_number_t message_number;
|
||||
uint32_t message_id;
|
||||
|
||||
AssertFatal (message != NULL, "Message is NULL!\n");
|
||||
AssertFatal (destination_task_id < itti_desc.task_max, "Destination task id (%d) is out of range (%d)\n", destination_task_id, itti_desc.task_max);
|
||||
|
||||
destination_thread_id = TASK_GET_THREAD_ID(destination_task_id);
|
||||
message->ittiMsgHeader.destinationTaskId = destination_task_id;
|
||||
message->ittiMsgHeader.instance = instance;
|
||||
message->ittiMsgHeader.lte_time.frame = itti_desc.lte_time.frame;
|
||||
message->ittiMsgHeader.lte_time.slot = itti_desc.lte_time.slot;
|
||||
message_id = message->ittiMsgHeader.messageId;
|
||||
AssertFatal (message_id < itti_desc.messages_id_max, "Message id (%d) is out of range (%d)!\n", message_id, itti_desc.messages_id_max);
|
||||
|
||||
origin_task_id = ITTI_MSG_ORIGIN_ID(message);
|
||||
|
||||
priority = itti_get_message_priority (message_id);
|
||||
|
||||
/* Increment the global message number */
|
||||
message_number = itti_increment_message_number ();
|
||||
|
||||
if (destination_task_id != TASK_UNKNOWN) {
|
||||
|
||||
if (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_ENDED ||
|
||||
itti_desc.threads[destination_thread_id].task_state == TASK_STATE_NOT_CONFIGURED) {
|
||||
ITTI_DEBUG(ITTI_DEBUG_ISSUES, " Message %s, number %lu with priority %d can not be sent from %s to queue (%u:%s), unconfigured or ended destination task!\n",
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_number,
|
||||
priority,
|
||||
itti_get_task_name(origin_task_id),
|
||||
destination_task_id,
|
||||
itti_get_task_name(destination_task_id));
|
||||
} else {
|
||||
/* We cannot send a message if the task is not running */
|
||||
AssertFatal (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_READY,
|
||||
"Task %s Cannot send message %s (%d) to thread %d, it is not in ready state (%d)!\n",
|
||||
itti_get_task_name(origin_task_id),
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_id,
|
||||
destination_thread_id,
|
||||
itti_desc.threads[destination_thread_id].task_state);
|
||||
|
||||
/* Allocate new list element */
|
||||
new = (message_list_t *) itti_malloc (origin_task_id, destination_task_id, sizeof(struct message_list_s));
|
||||
|
||||
/* Fill in members */
|
||||
new->msg = message;
|
||||
new->message_number = message_number;
|
||||
new->message_priority = priority;
|
||||
|
||||
/* Enqueue message in destination task queue */
|
||||
if (lfds611_queue_enqueue(itti_desc.tasks[destination_task_id].message_queue, new) == 0) {
|
||||
itti_free(origin_task_id, new);
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
/* Only use event fd for tasks, subtasks will pool the queue */
|
||||
if (TASK_GET_PARENT_TASK_ID(destination_task_id) == TASK_UNKNOWN) {
|
||||
ssize_t write_ret;
|
||||
eventfd_t sem_counter = 1;
|
||||
|
||||
/* Call to write for an event fd must be of 8 bytes */
|
||||
write_ret = write (itti_desc.threads[destination_thread_id].task_event_fd, &sem_counter, sizeof(sem_counter));
|
||||
AssertFatal (write_ret == sizeof(sem_counter), "Write to task message FD (%d) failed (%d/%d)\n",
|
||||
destination_thread_id, (int) write_ret, (int) sizeof(sem_counter));
|
||||
}
|
||||
}
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_SEND, " Message %s, number %lu with priority %d successfully sent from %s to queue (%u:%s)\n",
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_number,
|
||||
priority,
|
||||
itti_get_task_name(origin_task_id),
|
||||
destination_task_id,
|
||||
itti_get_task_name(destination_task_id));
|
||||
}
|
||||
} else {
|
||||
/* This is a debug message to TASK_UNKNOWN, we can release safely release it */
|
||||
int result = itti_free(origin_task_id, message);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void itti_subscribe_event_fd(task_id_t task_id, int fd)
|
||||
{
|
||||
thread_id_t thread_id;
|
||||
struct epoll_event event;
|
||||
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)!\n", task_id, itti_desc.task_max);
|
||||
|
||||
thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
itti_desc.threads[thread_id].nb_events++;
|
||||
|
||||
/* Reallocate the events */
|
||||
itti_desc.threads[thread_id].events = realloc(
|
||||
itti_desc.threads[thread_id].events,
|
||||
itti_desc.threads[thread_id].nb_events * sizeof(struct epoll_event));
|
||||
|
||||
event.events = EPOLLIN | EPOLLERR;
|
||||
event.data.u64 = 0;
|
||||
event.data.fd = fd;
|
||||
|
||||
/* Add the event fd to the list of monitored events */
|
||||
if (epoll_ctl(itti_desc.threads[thread_id].epoll_fd, EPOLL_CTL_ADD, fd,
|
||||
&event) != 0) {
|
||||
/* Always assert on this condition */
|
||||
AssertFatal (0, "epoll_ctl (EPOLL_CTL_ADD) failed for task %s, fd %d: %s!\n",
|
||||
itti_get_task_name(task_id), fd, strerror(errno));
|
||||
}
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_EVEN_FD, " Successfully subscribed fd %d for task %s\n", fd, itti_get_task_name(task_id));
|
||||
}
|
||||
|
||||
void itti_unsubscribe_event_fd(task_id_t task_id, int fd)
|
||||
{
|
||||
thread_id_t thread_id;
|
||||
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)!\n", task_id, itti_desc.task_max);
|
||||
AssertFatal (fd >= 0, "File descriptor (%d) is invalid!\n", fd);
|
||||
|
||||
thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
|
||||
/* Add the event fd to the list of monitored events */
|
||||
if (epoll_ctl(itti_desc.threads[thread_id].epoll_fd, EPOLL_CTL_DEL, fd, NULL) != 0) {
|
||||
/* Always assert on this condition */
|
||||
AssertFatal (0, "epoll_ctl (EPOLL_CTL_DEL) failed for task %s, fd %d: %s!\n",
|
||||
itti_get_task_name(task_id), fd, strerror(errno));
|
||||
}
|
||||
|
||||
itti_desc.threads[thread_id].nb_events--;
|
||||
itti_desc.threads[thread_id].events = realloc(
|
||||
itti_desc.threads[thread_id].events,
|
||||
itti_desc.threads[thread_id].nb_events * sizeof(struct epoll_event));
|
||||
}
|
||||
|
||||
int itti_get_events(task_id_t task_id, struct epoll_event **events)
|
||||
{
|
||||
thread_id_t thread_id;
|
||||
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)\n", task_id, itti_desc.task_max);
|
||||
|
||||
thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
*events = itti_desc.threads[thread_id].events;
|
||||
|
||||
return itti_desc.threads[thread_id].epoll_nb_events;
|
||||
}
|
||||
|
||||
static inline void itti_receive_msg_internal_event_fd(task_id_t task_id, uint8_t polling, MessageDef **received_msg)
|
||||
{
|
||||
thread_id_t thread_id;
|
||||
int epoll_ret = 0;
|
||||
int epoll_timeout = 0;
|
||||
int i;
|
||||
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)!\n", task_id, itti_desc.task_max);
|
||||
AssertFatal (received_msg != NULL, "Received message is NULL!\n");
|
||||
|
||||
thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
*received_msg = NULL;
|
||||
|
||||
if (polling) {
|
||||
/* In polling mode we set the timeout to 0 causing epoll_wait to return
|
||||
* immediately.
|
||||
*/
|
||||
epoll_timeout = 0;
|
||||
} else {
|
||||
/* timeout = -1 causes the epoll_wait to wait indefinitely.
|
||||
*/
|
||||
epoll_timeout = -1;
|
||||
}
|
||||
|
||||
do {
|
||||
epoll_ret = epoll_wait(itti_desc.threads[thread_id].epoll_fd,
|
||||
itti_desc.threads[thread_id].events,
|
||||
itti_desc.threads[thread_id].nb_events,
|
||||
epoll_timeout);
|
||||
} while (epoll_ret < 0 && errno == EINTR);
|
||||
|
||||
if (epoll_ret < 0) {
|
||||
AssertFatal (0, "epoll_wait failed for task %s: %s!\n", itti_get_task_name(task_id), strerror(errno));
|
||||
}
|
||||
|
||||
if (epoll_ret == 0 && polling) {
|
||||
/* No data to read -> return */
|
||||
return;
|
||||
}
|
||||
|
||||
itti_desc.threads[thread_id].epoll_nb_events = epoll_ret;
|
||||
|
||||
for (i = 0; i < epoll_ret; i++) {
|
||||
/* Check if there is an event for ITTI for the event fd */
|
||||
if ((itti_desc.threads[thread_id].events[i].events & EPOLLIN) &&
|
||||
(itti_desc.threads[thread_id].events[i].data.fd == itti_desc.threads[thread_id].task_event_fd)) {
|
||||
struct message_list_s *message = NULL;
|
||||
eventfd_t sem_counter;
|
||||
ssize_t read_ret;
|
||||
int result;
|
||||
|
||||
/* Read will always return 1 */
|
||||
read_ret = read (itti_desc.threads[thread_id].task_event_fd, &sem_counter, sizeof(sem_counter));
|
||||
AssertFatal (read_ret == sizeof(sem_counter), "Read from task message FD (%d) failed (%d/%d)!\n", thread_id, (int) read_ret, (int) sizeof(sem_counter));
|
||||
|
||||
if (lfds611_queue_dequeue (itti_desc.tasks[task_id].message_queue, (void **) &message) == 0) {
|
||||
/* No element in list -> this should not happen */
|
||||
AssertFatal (0, "No message in queue for task %d while there are %d events and some for the messages queue!\n", task_id, epoll_ret);
|
||||
}
|
||||
|
||||
AssertFatal(message != NULL, "Message from message queue is NULL!\n");
|
||||
*received_msg = message->msg;
|
||||
|
||||
|
||||
result = itti_free (ITTI_MSG_ORIGIN_ID(*received_msg), message);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
|
||||
|
||||
/* Mark that the event has been processed */
|
||||
itti_desc.threads[thread_id].events[i].events &= ~EPOLLIN;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void itti_receive_msg(task_id_t task_id, MessageDef **received_msg)
|
||||
{
|
||||
|
||||
itti_receive_msg_internal_event_fd(task_id, 0, received_msg);
|
||||
|
||||
}
|
||||
|
||||
void itti_poll_msg(task_id_t task_id, MessageDef **received_msg)
|
||||
{
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)!\n", task_id, itti_desc.task_max);
|
||||
|
||||
*received_msg = NULL;
|
||||
|
||||
{
|
||||
struct message_list_s *message;
|
||||
|
||||
if (lfds611_queue_dequeue (itti_desc.tasks[task_id].message_queue, (void **) &message) == 1) {
|
||||
int result;
|
||||
|
||||
*received_msg = message->msg;
|
||||
result = itti_free (ITTI_MSG_ORIGIN_ID(*received_msg), message);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
}
|
||||
}
|
||||
|
||||
if (*received_msg == NULL) {
|
||||
ITTI_DEBUG(ITTI_DEBUG_POLL, " No message in queue[(%u:%s)]\n", task_id, itti_get_task_name(task_id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int itti_create_task(task_id_t task_id, void *(*start_routine)(void *), void *args_p)
|
||||
{
|
||||
thread_id_t thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
int result;
|
||||
|
||||
AssertFatal (start_routine != NULL, "Start routine is NULL!\n");
|
||||
AssertFatal (thread_id < itti_desc.thread_max, "Thread id (%d) is out of range (%d)!\n", thread_id, itti_desc.thread_max);
|
||||
AssertFatal (itti_desc.threads[thread_id].task_state == TASK_STATE_NOT_CONFIGURED, "Task %d, thread %d state is not correct (%d)!\n",
|
||||
task_id, thread_id, itti_desc.threads[thread_id].task_state);
|
||||
|
||||
itti_desc.threads[thread_id].task_state = TASK_STATE_STARTING;
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT, " Creating thread for task %s ...\n", itti_get_task_name(task_id));
|
||||
|
||||
result = pthread_create (&itti_desc.threads[thread_id].task_thread, NULL, start_routine, args_p);
|
||||
AssertFatal (result >= 0, "Thread creation for task %d, thread %d failed (%d)!\n", task_id, thread_id, result);
|
||||
char name[16];
|
||||
snprintf( name, sizeof(name), "ITTI %d", thread_id );
|
||||
pthread_setname_np( itti_desc.threads[thread_id].task_thread, name );
|
||||
|
||||
itti_desc.created_tasks ++;
|
||||
|
||||
/* Wait till the thread is completely ready */
|
||||
while (itti_desc.threads[thread_id].task_state != TASK_STATE_READY)
|
||||
usleep (1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void itti_set_task_real_time(task_id_t task_id)
|
||||
{
|
||||
thread_id_t thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
|
||||
DevCheck(thread_id < itti_desc.thread_max, thread_id, itti_desc.thread_max, 0);
|
||||
|
||||
itti_desc.threads[thread_id].real_time = TRUE;
|
||||
}
|
||||
|
||||
void itti_wait_ready(int wait_tasks)
|
||||
{
|
||||
itti_desc.wait_tasks = wait_tasks;
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT,
|
||||
" wait for tasks: %s, created tasks %d, ready tasks %d\n",
|
||||
itti_desc.wait_tasks ? "yes" : "no",
|
||||
itti_desc.created_tasks,
|
||||
itti_desc.ready_tasks);
|
||||
|
||||
AssertFatal (itti_desc.created_tasks == itti_desc.ready_tasks, "Number of created tasks (%d) does not match ready tasks (%d), wait task %d!\n",
|
||||
itti_desc.created_tasks, itti_desc.ready_tasks, itti_desc.wait_tasks);
|
||||
}
|
||||
|
||||
void itti_mark_task_ready(task_id_t task_id)
|
||||
{
|
||||
thread_id_t thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
|
||||
AssertFatal (thread_id < itti_desc.thread_max, "Thread id (%d) is out of range (%d)!\n", thread_id, itti_desc.thread_max);
|
||||
|
||||
/* Mark the thread as using LFDS queue */
|
||||
lfds611_queue_use(itti_desc.tasks[task_id].message_queue);
|
||||
|
||||
#if defined(UE_EXPANSION) || defined(RTAI)
|
||||
/* Assign low priority to created threads */
|
||||
{
|
||||
struct sched_param sched_param;
|
||||
sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO) + 1;
|
||||
sched_setscheduler(0, SCHED_FIFO, &sched_param);
|
||||
}
|
||||
#endif
|
||||
|
||||
itti_desc.threads[thread_id].task_state = TASK_STATE_READY;
|
||||
itti_desc.ready_tasks ++;
|
||||
|
||||
while (itti_desc.wait_tasks != 0) {
|
||||
usleep (10000);
|
||||
}
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT, " task %s started\n", itti_get_task_name(task_id));
|
||||
}
|
||||
|
||||
void itti_exit_task(void)
|
||||
{
|
||||
task_id_t task_id = itti_get_current_task_id();
|
||||
thread_id_t thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
|
||||
#if defined(OAI_EMU) || defined(RTAI)
|
||||
if (task_id > TASK_UNKNOWN) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_ITTI_RECV_MSG,
|
||||
__sync_and_and_fetch (&itti_desc.vcd_receive_msg, ~(1L << task_id)));
|
||||
}
|
||||
#endif
|
||||
|
||||
itti_desc.threads[thread_id].task_state = TASK_STATE_NOT_CONFIGURED;
|
||||
itti_desc.created_tasks--;
|
||||
ITTI_DEBUG(ITTI_DEBUG_EXIT, "Thread for task %s (%d) exits\n", itti_get_task_name(task_id), task_id);
|
||||
pthread_exit (NULL);
|
||||
}
|
||||
|
||||
void itti_terminate_tasks(task_id_t task_id)
|
||||
{
|
||||
// Sends Terminate signals to all tasks.
|
||||
itti_send_terminate_message (task_id);
|
||||
|
||||
if (itti_desc.thread_handling_signals) {
|
||||
pthread_kill (itti_desc.thread_ref, SIGUSR1);
|
||||
}
|
||||
|
||||
pthread_exit (NULL);
|
||||
}
|
||||
|
||||
int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
|
||||
const message_info_t *messages_info)
|
||||
{
|
||||
task_id_t task_id;
|
||||
thread_id_t thread_id;
|
||||
int ret;
|
||||
|
||||
itti_desc.message_number = 1;
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT, " Init: %d tasks, %d threads, %d messages\n", task_max, thread_max, messages_id_max);
|
||||
|
||||
CHECK_INIT_RETURN(signal_mask());
|
||||
|
||||
/* Saves threads and messages max values */
|
||||
itti_desc.task_max = task_max;
|
||||
itti_desc.thread_max = thread_max;
|
||||
itti_desc.messages_id_max = messages_id_max;
|
||||
itti_desc.thread_handling_signals = FALSE;
|
||||
itti_desc.tasks_info = tasks_info;
|
||||
itti_desc.messages_info = messages_info;
|
||||
|
||||
/* Allocates memory for tasks info */
|
||||
itti_desc.tasks = calloc (itti_desc.task_max, sizeof(task_desc_t));
|
||||
|
||||
/* Allocates memory for threads info */
|
||||
itti_desc.threads = calloc (itti_desc.thread_max, sizeof(thread_desc_t));
|
||||
|
||||
/* Initializing each queue and related stuff */
|
||||
for (task_id = TASK_FIRST; task_id < itti_desc.task_max; task_id++) {
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT, " Initializing %stask %s%s%s\n",
|
||||
itti_desc.tasks_info[task_id].parent_task != TASK_UNKNOWN ? "sub-" : "",
|
||||
itti_desc.tasks_info[task_id].name,
|
||||
itti_desc.tasks_info[task_id].parent_task != TASK_UNKNOWN ? " with parent " : "",
|
||||
itti_desc.tasks_info[task_id].parent_task != TASK_UNKNOWN ?
|
||||
itti_get_task_name(itti_desc.tasks_info[task_id].parent_task) : "");
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT, " Creating queue of message of size %u\n", itti_desc.tasks_info[task_id].queue_size);
|
||||
|
||||
ret = lfds611_queue_new(&itti_desc.tasks[task_id].message_queue, itti_desc.tasks_info[task_id].queue_size);
|
||||
|
||||
if (0 == ret) {
|
||||
AssertFatal (0, "lfds611_queue_new failed for task %s!\n", itti_get_task_name(task_id));
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializing each thread */
|
||||
for (thread_id = THREAD_FIRST; thread_id < itti_desc.thread_max; thread_id++) {
|
||||
itti_desc.threads[thread_id].task_state = TASK_STATE_NOT_CONFIGURED;
|
||||
|
||||
itti_desc.threads[thread_id].epoll_fd = epoll_create1(0);
|
||||
|
||||
if (itti_desc.threads[thread_id].epoll_fd == -1) {
|
||||
/* Always assert on this condition */
|
||||
AssertFatal (0, "Failed to create new epoll fd: %s!\n", strerror(errno));
|
||||
}
|
||||
|
||||
itti_desc.threads[thread_id].task_event_fd = eventfd(0, EFD_SEMAPHORE);
|
||||
|
||||
if (itti_desc.threads[thread_id].task_event_fd == -1) {
|
||||
/* Always assert on this condition */
|
||||
AssertFatal (0, " eventfd failed: %s!\n", strerror(errno));
|
||||
}
|
||||
|
||||
itti_desc.threads[thread_id].nb_events = 1;
|
||||
|
||||
itti_desc.threads[thread_id].events = calloc(1, sizeof(struct epoll_event));
|
||||
|
||||
itti_desc.threads[thread_id].events->events = EPOLLIN | EPOLLERR;
|
||||
itti_desc.threads[thread_id].events->data.fd = itti_desc.threads[thread_id].task_event_fd;
|
||||
|
||||
/* Add the event fd to the list of monitored events */
|
||||
if (epoll_ctl(itti_desc.threads[thread_id].epoll_fd, EPOLL_CTL_ADD,
|
||||
itti_desc.threads[thread_id].task_event_fd, itti_desc.threads[thread_id].events) != 0) {
|
||||
/* Always assert on this condition */
|
||||
AssertFatal (0, " epoll_ctl (EPOLL_CTL_ADD) failed: %s!\n", strerror(errno));
|
||||
}
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_EVEN_FD, " Successfully subscribed fd %d for thread %d\n",
|
||||
itti_desc.threads[thread_id].task_event_fd, thread_id);
|
||||
|
||||
}
|
||||
|
||||
itti_desc.running = 1;
|
||||
itti_desc.wait_tasks = 0;
|
||||
itti_desc.created_tasks = 0;
|
||||
itti_desc.ready_tasks = 0;
|
||||
CHECK_INIT_RETURN(timer_init ());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void itti_wait_tasks_end(void)
|
||||
{
|
||||
int end = 0;
|
||||
int thread_id;
|
||||
task_id_t task_id;
|
||||
int ready_tasks;
|
||||
int result;
|
||||
int retries = 10;
|
||||
|
||||
itti_desc.thread_handling_signals = TRUE;
|
||||
itti_desc.thread_ref=pthread_self ();
|
||||
|
||||
/* Handle signals here */
|
||||
while (end == 0) {
|
||||
signal_handle (&end);
|
||||
}
|
||||
|
||||
printf("closing all tasks\n");
|
||||
sleep(1);
|
||||
|
||||
do {
|
||||
ready_tasks = 0;
|
||||
|
||||
task_id = TASK_FIRST;
|
||||
|
||||
for (thread_id = THREAD_FIRST; thread_id < itti_desc.thread_max; thread_id++) {
|
||||
/* Skip tasks which are not running */
|
||||
if (itti_desc.threads[thread_id].task_state == TASK_STATE_READY) {
|
||||
while (thread_id != TASK_GET_THREAD_ID(task_id)) {
|
||||
task_id++;
|
||||
}
|
||||
|
||||
result = pthread_tryjoin_np (itti_desc.threads[thread_id].task_thread, NULL);
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_EXIT, " Thread %s join status %d\n", itti_get_task_name(task_id), result);
|
||||
|
||||
if (result == 0) {
|
||||
/* Thread has terminated */
|
||||
itti_desc.threads[thread_id].task_state = TASK_STATE_ENDED;
|
||||
} else {
|
||||
/* Thread is still running, count it */
|
||||
ready_tasks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ready_tasks > 0) {
|
||||
usleep (100 * 1000);
|
||||
}
|
||||
} while ((ready_tasks > 0) && (retries--)&& (!end) );
|
||||
|
||||
printf("ready_tasks %d\n",ready_tasks);
|
||||
|
||||
itti_desc.running = 0;
|
||||
|
||||
if (ready_tasks > 0) {
|
||||
ITTI_DEBUG(ITTI_DEBUG_ISSUES, " Some threads are still running, force exit\n");
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
|
||||
void itti_send_terminate_message(task_id_t task_id)
|
||||
{
|
||||
MessageDef *terminate_message_p;
|
||||
|
||||
terminate_message_p = itti_alloc_new_message (task_id, TERMINATE_MESSAGE);
|
||||
|
||||
itti_send_broadcast_message (terminate_message_p);
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/** @defgroup _intertask_interface_impl_ Intertask Interface Mechanisms
|
||||
* Implementation
|
||||
* @ingroup _ref_implementation_
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#ifndef INTERTASK_INTERFACE_H_
|
||||
#define INTERTASK_INTERFACE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "intertask_interface_conf.h"
|
||||
#include "intertask_interface_types.h"
|
||||
|
||||
#define ITTI_MSG_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.messageId)
|
||||
#define ITTI_MSG_ORIGIN_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.originTaskId)
|
||||
#define ITTI_MSG_DESTINATION_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.destinationTaskId)
|
||||
#define ITTI_MSG_INSTANCE(mSGpTR) ((mSGpTR)->ittiMsgHeader.instance)
|
||||
#define ITTI_MSG_NAME(mSGpTR) itti_get_message_name(ITTI_MSG_ID(mSGpTR))
|
||||
#define ITTI_MSG_ORIGIN_NAME(mSGpTR) itti_get_task_name(ITTI_MSG_ORIGIN_ID(mSGpTR))
|
||||
#define ITTI_MSG_DESTINATION_NAME(mSGpTR) itti_get_task_name(ITTI_MSG_DESTINATION_ID(mSGpTR))
|
||||
|
||||
/* Make the message number platform specific */
|
||||
typedef unsigned long message_number_t;
|
||||
#define MESSAGE_NUMBER_SIZE (sizeof(unsigned long))
|
||||
|
||||
typedef enum message_priorities_e {
|
||||
MESSAGE_PRIORITY_MAX = 100,
|
||||
MESSAGE_PRIORITY_MAX_LEAST = 85,
|
||||
MESSAGE_PRIORITY_MED_PLUS = 70,
|
||||
MESSAGE_PRIORITY_MED = 55,
|
||||
MESSAGE_PRIORITY_MED_LEAST = 40,
|
||||
MESSAGE_PRIORITY_MIN_PLUS = 25,
|
||||
MESSAGE_PRIORITY_MIN = 10,
|
||||
} message_priorities_t;
|
||||
|
||||
typedef struct message_info_s {
|
||||
task_id_t id;
|
||||
message_priorities_t priority;
|
||||
/* Message payload size */
|
||||
MessageHeaderSize size;
|
||||
/* Printable name */
|
||||
const char * const name;
|
||||
} message_info_t;
|
||||
|
||||
typedef enum task_priorities_e {
|
||||
TASK_PRIORITY_MAX = 100,
|
||||
TASK_PRIORITY_MAX_LEAST = 85,
|
||||
TASK_PRIORITY_MED_PLUS = 70,
|
||||
TASK_PRIORITY_MED = 55,
|
||||
TASK_PRIORITY_MED_LEAST = 40,
|
||||
TASK_PRIORITY_MIN_PLUS = 25,
|
||||
TASK_PRIORITY_MIN = 10,
|
||||
} task_priorities_t;
|
||||
|
||||
typedef struct task_info_s {
|
||||
thread_id_t thread;
|
||||
task_id_t parent_task;
|
||||
task_priorities_t priority;
|
||||
unsigned int queue_size;
|
||||
/* Printable name */
|
||||
const char * const name;
|
||||
} task_info_t;
|
||||
|
||||
/** \brief Update the itti LTE time reference for messages
|
||||
\param current reference frame
|
||||
\param current reference slot
|
||||
@returns < 0 on failure, 0 otherwise
|
||||
**/
|
||||
void itti_update_lte_time(uint32_t frame, uint8_t slot);
|
||||
|
||||
/** \brief Send a broadcast message to every task
|
||||
\param message_p Pointer to the message to send
|
||||
@returns < 0 on failure, 0 otherwise
|
||||
**/
|
||||
int itti_send_broadcast_message(MessageDef *message_p);
|
||||
|
||||
/** \brief Send a message to a task (could be itself)
|
||||
\param task_id Task ID
|
||||
\param instance Instance of the task used for virtualization
|
||||
\param message Pointer to the message to send
|
||||
@returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int itti_send_msg_to_task(task_id_t task_id, instance_t instance, MessageDef *message);
|
||||
|
||||
/* TODO: this is a hack. Almost no caller of itti_send_msg_to_task checks
|
||||
* the return value so it has been changed to crash the program in case
|
||||
* of failure instead of returning -1 as the documentation above says.
|
||||
* The RLC UM code may receive too much data when doing UDP at a higher
|
||||
* throughput than the link allows and so for this specific case we need
|
||||
* a version that actually returns -1 on failure.
|
||||
*
|
||||
* This needs to be cleaned at some point.
|
||||
*/
|
||||
/* look for HACK_RLC_UM_LIMIT for others places related to the hack. Please do not remove this comment. */
|
||||
int itti_try_send_msg_to_task(task_id_t task_id, instance_t instance, MessageDef *message);
|
||||
|
||||
/** \brief Add a new fd to monitor.
|
||||
* NOTE: it is up to the user to read data associated with the fd
|
||||
* \param task_id Task ID of the receiving task
|
||||
* \param fd The file descriptor to monitor
|
||||
**/
|
||||
void itti_subscribe_event_fd(task_id_t task_id, int fd);
|
||||
|
||||
/** \brief Remove a fd from the list of fd to monitor
|
||||
* \param task_id Task ID of the task
|
||||
* \param fd The file descriptor to remove
|
||||
**/
|
||||
void itti_unsubscribe_event_fd(task_id_t task_id, int fd);
|
||||
|
||||
/** \brief Return the list of events excluding the fd associated with itti
|
||||
* \param task_id Task ID of the task
|
||||
* \param events events list
|
||||
* @returns number of events to handle
|
||||
**/
|
||||
int itti_get_events(task_id_t task_id, struct epoll_event **events);
|
||||
|
||||
/** \brief Retrieves a message in the queue associated to task_id.
|
||||
* If the queue is empty, the thread is blocked till a new message arrives.
|
||||
\param task_id Task ID of the receiving task
|
||||
\param received_msg Pointer to the allocated message
|
||||
**/
|
||||
void itti_receive_msg(task_id_t task_id, MessageDef **received_msg);
|
||||
|
||||
/** \brief Try to retrieves a message in the queue associated to task_id.
|
||||
\param task_id Task ID of the receiving task
|
||||
\param received_msg Pointer to the allocated message
|
||||
**/
|
||||
void itti_poll_msg(task_id_t task_id, MessageDef **received_msg);
|
||||
|
||||
/** \brief Start thread associated to the task
|
||||
* \param task_id task to start
|
||||
* \param start_routine entry point for the task
|
||||
* \param args_p Optional argument to pass to the start routine
|
||||
* @returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int itti_create_task(task_id_t task_id,
|
||||
void *(*start_routine) (void *),
|
||||
void *args_p);
|
||||
|
||||
/** \brief Mark the task as a real time task
|
||||
* \param task_id task to mark as real time
|
||||
**/
|
||||
void itti_set_task_real_time(task_id_t task_id);
|
||||
|
||||
/** \brief Indicates to ITTI if newly created tasks should wait for all tasks to be ready
|
||||
* \param wait_tasks non 0 to make new created tasks to wait, 0 to let created tasks to run
|
||||
**/
|
||||
void itti_wait_ready(int wait_tasks);
|
||||
|
||||
/** \brief Mark the task as in ready state
|
||||
* \param task_id task to mark as ready
|
||||
**/
|
||||
void itti_mark_task_ready(task_id_t task_id);
|
||||
|
||||
/** \brief Exit the current task.
|
||||
**/
|
||||
void itti_exit_task(void);
|
||||
|
||||
/** \brief Indicate that the task is completed and initiate termination of all tasks.
|
||||
* \param task_id task that is completed
|
||||
**/
|
||||
void itti_terminate_tasks(task_id_t task_id);
|
||||
|
||||
/** \brief Return the printable string associated with the message
|
||||
* \param message_id Id of the message
|
||||
**/
|
||||
const char *itti_get_message_name(MessagesIds message_id);
|
||||
|
||||
/** \brief Return the printable string associated with a task id
|
||||
* \param thread_id Id of the task
|
||||
**/
|
||||
const char *itti_get_task_name(task_id_t task_id);
|
||||
|
||||
/** \brief Alloc and memset(0) a new itti message.
|
||||
* \param origin_task_id Task ID of the sending task
|
||||
* \param message_id Message ID
|
||||
* @returns NULL in case of failure or newly allocated mesage ref
|
||||
**/
|
||||
MessageDef *itti_alloc_new_message(
|
||||
task_id_t origin_task_id,
|
||||
MessagesIds message_id);
|
||||
|
||||
/** \brief Alloc and memset(0) a new itti message.
|
||||
* \param origin_task_id Task ID of the sending task
|
||||
* \param message_id Message ID
|
||||
* \param size size of the payload to send
|
||||
* @returns NULL in case of failure or newly allocated mesage ref
|
||||
**/
|
||||
MessageDef *itti_alloc_new_message_sized(
|
||||
task_id_t origin_task_id,
|
||||
MessagesIds message_id,
|
||||
MessageHeaderSize size);
|
||||
|
||||
/** \brief handle signals and wait for all threads to join when the process complete.
|
||||
* This function should be called from the main thread after having created all ITTI tasks.
|
||||
**/
|
||||
void itti_wait_tasks_end(void);
|
||||
|
||||
/** \brief Send a termination message to all tasks.
|
||||
* \param task_id task that is broadcasting the message.
|
||||
**/
|
||||
void itti_send_terminate_message(task_id_t task_id);
|
||||
|
||||
void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size);
|
||||
|
||||
int itti_free(task_id_t task_id, void *ptr);
|
||||
|
||||
#endif /* INTERTASK_INTERFACE_H_ */
|
||||
/* @} */
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/** @defgroup _intertask_interface_impl_ Intertask Interface Mechanisms
|
||||
* Implementation
|
||||
* @ingroup _ref_implementation_
|
||||
* @{
|
||||
*/
|
||||
|
||||
/********************************************************************************
|
||||
*
|
||||
* !!! This header should only be included by the file that initialize
|
||||
* the intertask interface module for the process !!!
|
||||
*
|
||||
* Other files should include "intertask_interface.h"
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef INTERTASK_INTERFACE_INIT_H_
|
||||
#define INTERTASK_INTERFACE_INIT_H_
|
||||
|
||||
#include "intertask_interface.h"
|
||||
|
||||
#ifndef CHECK_PROTOTYPE_ONLY
|
||||
|
||||
/* Map task id to printable name. */
|
||||
const task_info_t tasks_info[] = {
|
||||
{0, TASK_UNKNOWN, 0, 0, "TASK_UNKNOWN"},
|
||||
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) { tHREADiD##_THREAD, TASK_UNKNOWN, pRIO, qUEUEsIZE, #tHREADiD },
|
||||
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) { sUBtASKiD##_THREAD, tHREADiD##_THREAD, 0, qUEUEsIZE, #sUBtASKiD },
|
||||
#include <tasks_def.h>
|
||||
#undef SUB_TASK_DEF
|
||||
#undef TASK_DEF
|
||||
};
|
||||
|
||||
/* Map message id to message information */
|
||||
const message_info_t messages_info[] = {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) { iD, pRIO, sizeof(sTRUCT), #iD },
|
||||
#include <messages_def.h>
|
||||
#undef MESSAGE_DEF
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/** \brief Init function for the intertask interface. Init queues, Mutexes and Cond vars.
|
||||
* \param thread_max Maximum number of threads
|
||||
* \param messages_id_max Maximum message id
|
||||
* \param threads_name Pointer on the threads name information as created by this include file
|
||||
* \param messages_info Pointer on messages information as created by this include file
|
||||
**/
|
||||
int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
|
||||
const message_info_t *messages_info);
|
||||
|
||||
#endif /* INTERTASK_INTERFACE_INIT_H_ */
|
||||
/* @} */
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/** @defgroup _intertask_interface_impl_ Intertask Interface Mechanisms
|
||||
* Implementation
|
||||
* @ingroup _ref_implementation_
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef INTERTASK_INTERFACE_TYPES_H_
|
||||
#define INTERTASK_INTERFACE_TYPES_H_
|
||||
|
||||
#include "itti_types.h"
|
||||
#include "platform_types.h"
|
||||
|
||||
/* Defines to handle bit fields on unsigned long values */
|
||||
#define UL_BIT_MASK(lENGTH) ((1UL << (lENGTH)) - 1UL)
|
||||
#define UL_BIT_SHIFT(vALUE, oFFSET) ((vALUE) << (oFFSET))
|
||||
#define UL_BIT_UNSHIFT(vALUE, oFFSET) ((vALUE) >> (oFFSET))
|
||||
|
||||
#define UL_FIELD_MASK(oFFSET, lENGTH) UL_BIT_SHIFT(UL_BIT_MASK(lENGTH), (oFFSET))
|
||||
#define UL_FIELD_INSERT(vALUE, fIELD, oFFSET, lENGTH) (((vALUE) & (~UL_FIELD_MASK(oFFSET, lENGTH))) | UL_BIT_SHIFT(((fIELD) & UL_BIT_MASK(lENGTH)), oFFSET))
|
||||
#define UL_FIELD_EXTRACT(vALUE, oFFSET, lENGTH) (UL_BIT_UNSHIFT((vALUE), (oFFSET)) & UL_BIT_MASK(lENGTH))
|
||||
|
||||
/* Definitions of task ID fields */
|
||||
#define TASK_THREAD_ID_OFFSET 8
|
||||
#define TASK_THREAD_ID_LENGTH 8
|
||||
|
||||
#define TASK_SUB_TASK_ID_OFFSET 0
|
||||
#define TASK_SUB_TASK_ID_LENGTH 8
|
||||
|
||||
/* Defines to extract task ID fields */
|
||||
#define TASK_GET_THREAD_ID(tASKiD) (itti_desc.tasks_info[tASKiD].thread)
|
||||
#define TASK_GET_PARENT_TASK_ID(tASKiD) (itti_desc.tasks_info[tASKiD].parent_task)
|
||||
/* Extract the instance from a message */
|
||||
#define ITTI_MESSAGE_GET_INSTANCE(mESSAGE) ((mESSAGE)->ittiMsgHeader.instance)
|
||||
|
||||
#include <messages_types.h>
|
||||
|
||||
/* This enum defines messages ids. Each one is unique. */
|
||||
typedef enum {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) iD,
|
||||
#include <messages_def.h>
|
||||
#undef MESSAGE_DEF
|
||||
|
||||
MESSAGES_ID_MAX,
|
||||
} MessagesIds;
|
||||
|
||||
//! Thread id of each task
|
||||
typedef enum {
|
||||
THREAD_NULL = 0,
|
||||
|
||||
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) THREAD_##tHREADiD,
|
||||
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE)
|
||||
#include <tasks_def.h>
|
||||
#undef SUB_TASK_DEF
|
||||
#undef TASK_DEF
|
||||
|
||||
THREAD_MAX,
|
||||
THREAD_FIRST = 1,
|
||||
} thread_id_t;
|
||||
|
||||
//! Sub-tasks id, to defined offset form thread id
|
||||
typedef enum {
|
||||
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) tHREADiD##_THREAD = THREAD_##tHREADiD,
|
||||
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) sUBtASKiD##_THREAD = THREAD_##tHREADiD,
|
||||
#include <tasks_def.h>
|
||||
#undef SUB_TASK_DEF
|
||||
#undef TASK_DEF
|
||||
} task_thread_id_t;
|
||||
|
||||
//! Tasks id of each task
|
||||
typedef enum {
|
||||
TASK_UNKNOWN = 0,
|
||||
|
||||
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) tHREADiD,
|
||||
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) sUBtASKiD,
|
||||
#include <tasks_def.h>
|
||||
#undef SUB_TASK_DEF
|
||||
#undef TASK_DEF
|
||||
|
||||
TASK_MAX,
|
||||
TASK_FIRST = 1,
|
||||
} task_id_t;
|
||||
|
||||
typedef union msg_s {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) sTRUCT fIELDnAME;
|
||||
#include <messages_def.h>
|
||||
#undef MESSAGE_DEF
|
||||
} msg_t;
|
||||
|
||||
typedef uint16_t MessageHeaderSize;
|
||||
|
||||
typedef struct itti_lte_time_s {
|
||||
uint32_t frame;
|
||||
uint8_t slot;
|
||||
} itti_lte_time_t;
|
||||
|
||||
/** @struct MessageHeader
|
||||
* @brief Message Header structure for inter-task communication.
|
||||
*/
|
||||
typedef struct MessageHeader_s {
|
||||
MessagesIds messageId; /**< Unique message id as referenced in enum MessagesIds */
|
||||
|
||||
task_id_t originTaskId; /**< ID of the sender task */
|
||||
task_id_t destinationTaskId; /**< ID of the destination task */
|
||||
instance_t instance; /**< Task instance for virtualization */
|
||||
|
||||
MessageHeaderSize ittiMsgSize; /**< Message size (not including header size) */
|
||||
|
||||
itti_lte_time_t lte_time; /**< Reference LTE time */
|
||||
} MessageHeader;
|
||||
|
||||
/** @struct MessageDef
|
||||
* @brief Message structure for inter-task communication.
|
||||
* \internal
|
||||
* The attached attribute \c __packed__ is neccessary, because the memory allocation code expects \ref ittiMsg directly following \ref ittiMsgHeader.
|
||||
*/
|
||||
typedef struct __attribute__ ((__packed__)) MessageDef_s {
|
||||
MessageHeader ittiMsgHeader; /**< Message header */
|
||||
msg_t ittiMsg; /**< Union of payloads as defined in x_messages_def.h headers */
|
||||
} MessageDef;
|
||||
|
||||
#endif /* INTERTASK_INTERFACE_TYPES_H_ */
|
||||
/* @} */
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* This message asks for task initialization */
|
||||
MESSAGE_DEF(INITIALIZE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, initialize_message)
|
||||
|
||||
/* This message asks for task activation */
|
||||
MESSAGE_DEF(ACTIVATE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, activate_message)
|
||||
|
||||
/* This message asks for task deactivation */
|
||||
MESSAGE_DEF(DEACTIVATE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, deactivate_message)
|
||||
|
||||
/* This message asks for task termination */
|
||||
MESSAGE_DEF(TERMINATE_MESSAGE, MESSAGE_PRIORITY_MAX, IttiMsgEmpty, terminate_message)
|
||||
|
||||
/* Test message used for debug */
|
||||
MESSAGE_DEF(MESSAGE_TEST, MESSAGE_PRIORITY_MED, IttiMsgEmpty, message_test)
|
||||
|
||||
/* Error message */
|
||||
MESSAGE_DEF(ERROR_LOG, MESSAGE_PRIORITY_MAX, IttiMsgEmpty, error_log)
|
||||
/* Warning message */
|
||||
MESSAGE_DEF(WARNING_LOG, MESSAGE_PRIORITY_MAX, IttiMsgEmpty, warning_log)
|
||||
/* Notice message */
|
||||
MESSAGE_DEF(NOTICE_LOG, MESSAGE_PRIORITY_MED, IttiMsgEmpty, notice_log)
|
||||
/* Info message */
|
||||
MESSAGE_DEF(INFO_LOG, MESSAGE_PRIORITY_MED, IttiMsgEmpty, info_log)
|
||||
/* Debug message */
|
||||
MESSAGE_DEF(DEBUG_LOG, MESSAGE_PRIORITY_MED, IttiMsgEmpty, debug_log)
|
||||
|
||||
/* Generic log message for text */
|
||||
MESSAGE_DEF(GENERIC_LOG, MESSAGE_PRIORITY_MED, IttiMsgEmpty, generic_log)
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/** @brief Intertask Interface common types
|
||||
* Contains type definitions used for generating and parsing ITTI messages.
|
||||
* @author Laurent Winckel <laurent.winckel@eurecom.fr>
|
||||
*/
|
||||
|
||||
#ifndef _ITTI_TYPES_H_
|
||||
#define _ITTI_TYPES_H_
|
||||
|
||||
/* The current file is included in the ue_ip.ko compilation.
|
||||
* For it to work we need to include linux/types.h and
|
||||
* not stdint.h.
|
||||
* A solution to this problem is to use #ifndef __KERNEL__.
|
||||
* Maybe a better solution would be to clean things up
|
||||
* so that ue_ip.ko does not include the current file.
|
||||
*/
|
||||
#ifndef __KERNEL__
|
||||
# include <stdint.h>
|
||||
#else
|
||||
# include <linux/types.h>
|
||||
#endif
|
||||
|
||||
#define CHARS_TO_UINT32(c1, c2, c3, c4) (((c4) << 24) | ((c3) << 16) | ((c2) << 8) | (c1))
|
||||
|
||||
#define MESSAGE_NUMBER_CHAR_FORMAT "%11u"
|
||||
|
||||
/* Intertask message types */
|
||||
enum itti_message_types_e {
|
||||
ITTI_DUMP_XML_DEFINITION = CHARS_TO_UINT32 ('\n', 'I', 'x', 'd'),
|
||||
ITTI_DUMP_XML_DEFINITION_END = CHARS_TO_UINT32 ('i', 'X', 'D', '\n'),
|
||||
|
||||
ITTI_DUMP_MESSAGE_TYPE = CHARS_TO_UINT32 ('\n', 'I', 'm', 's'),
|
||||
ITTI_DUMP_MESSAGE_TYPE_END = CHARS_TO_UINT32 ('i', 'M', 'S', '\n'),
|
||||
|
||||
ITTI_STATISTIC_MESSAGE_TYPE = CHARS_TO_UINT32 ('\n', 'I', 's', 't'),
|
||||
ITTI_STATISTIC_MESSAGE_TYPE_END = CHARS_TO_UINT32 ('i', 'S', 'T', '\n'),
|
||||
|
||||
/* This signal is not meant to be used by remote analyzer */
|
||||
ITTI_DUMP_EXIT_SIGNAL = CHARS_TO_UINT32 ('e', 'X', 'I', 'T'),
|
||||
};
|
||||
|
||||
typedef uint32_t itti_message_types_t;
|
||||
|
||||
/* Message header is the common part that should never change between
|
||||
* remote process and this one.
|
||||
*/
|
||||
typedef struct {
|
||||
/* The size of this structure */
|
||||
uint32_t message_size;
|
||||
itti_message_types_t message_type;
|
||||
} itti_socket_header_t;
|
||||
|
||||
typedef struct {
|
||||
char message_number_char[12]; /* 9 chars are needed to store an unsigned 32 bits value in decimal, but must be a multiple of 32 bits to avoid alignment issues */
|
||||
} itti_signal_header_t;
|
||||
|
||||
|
||||
#define INSTANCE_DEFAULT (UINT16_MAX - 1)
|
||||
#define INSTANCE_ALL (UINT16_MAX)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
// These messages files are mandatory and must always be placed in first position
|
||||
#include "intertask_messages_def.h"
|
||||
#include "timer_messages_def.h"
|
||||
|
||||
// Dummy file for the generic intertask interface definition. Actual definition should be in top level build directory.
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "intertask_interface.h"
|
||||
#include "timer.h"
|
||||
#include "backtrace.h"
|
||||
#include "assertions.h"
|
||||
|
||||
#include "signals.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
#if defined (LOG_D) && defined (LOG_E)
|
||||
# define SIG_DEBUG(x, args...) LOG_D(RRC, x, ##args)
|
||||
# define SIG_ERROR(x, args...) LOG_E(RRC, x, ##args)
|
||||
#endif
|
||||
|
||||
#ifndef SIG_DEBUG
|
||||
# define SIG_DEBUG(x, args...) do { fprintf(stdout, "[SIG][D]"x, ##args); } while(0)
|
||||
#endif
|
||||
#ifndef SIG_ERROR
|
||||
# define SIG_ERROR(x, args...) do { fprintf(stdout, "[SIG][E]"x, ##args); } while(0)
|
||||
#endif
|
||||
|
||||
static sigset_t set;
|
||||
|
||||
int signal_mask(void)
|
||||
{
|
||||
/* We set the signal mask to avoid threads other than the main thread
|
||||
* to receive the timer signal. Note that threads created will inherit this
|
||||
* configuration.
|
||||
*/
|
||||
sigemptyset(&set);
|
||||
|
||||
sigaddset (&set, SIGTIMER);
|
||||
sigaddset (&set, SIGUSR1);
|
||||
sigaddset (&set, SIGABRT);
|
||||
sigaddset (&set, SIGSEGV);
|
||||
sigaddset (&set, SIGINT);
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) {
|
||||
perror ("sigprocmask");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int signal_handle(int *end)
|
||||
{
|
||||
int ret;
|
||||
siginfo_t info;
|
||||
|
||||
sigemptyset(&set);
|
||||
|
||||
sigaddset (&set, SIGTIMER);
|
||||
sigaddset (&set, SIGUSR1);
|
||||
sigaddset (&set, SIGABRT);
|
||||
sigaddset (&set, SIGSEGV);
|
||||
sigaddset (&set, SIGINT);
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) {
|
||||
perror ("sigprocmask");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Block till a signal is received.
|
||||
* NOTE: The signals defined by set are required to be blocked at the time
|
||||
* of the call to sigwait() otherwise sigwait() is not successful.
|
||||
*/
|
||||
if ((ret = sigwaitinfo(&set, &info)) == -1) {
|
||||
perror ("sigwait");
|
||||
return ret;
|
||||
}
|
||||
|
||||
//printf("Received signal %d\n", info.si_signo);
|
||||
|
||||
/* Real-time signals are non constant and are therefore not suitable for
|
||||
* use in switch.
|
||||
*/
|
||||
if (info.si_signo == SIGTIMER) {
|
||||
timer_handle_signal(&info);
|
||||
} else {
|
||||
/* Dispatch the signal to sub-handlers */
|
||||
switch(info.si_signo) {
|
||||
case SIGUSR1:
|
||||
SIG_DEBUG("Received SIGUSR1\n");
|
||||
*end = 1;
|
||||
break;
|
||||
|
||||
case SIGSEGV: /* Fall through */
|
||||
case SIGABRT:
|
||||
SIG_DEBUG("Received SIGABORT\n");
|
||||
backtrace_handle_signal(&info);
|
||||
break;
|
||||
|
||||
case SIGINT:
|
||||
printf("Received SIGINT\n");
|
||||
itti_send_terminate_message(TASK_UNKNOWN);
|
||||
*end = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
SIG_ERROR("Received unknown signal %d\n", info.si_signo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
// This task is mandatory and must always be placed in first position
|
||||
TASK_DEF(TASK_TIMER, TASK_PRIORITY_MED, 10)
|
||||
|
||||
// Dummy file for the generic intertask interface definition. Actual definition should be in top level build directory.
|
||||
@@ -1,255 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "assertions.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "timer.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "queue.h"
|
||||
|
||||
#if defined (LOG_D) && defined (LOG_E)
|
||||
# define TMR_DEBUG(x, args...) LOG_D(TMR, x, ##args)
|
||||
# define TMR_ERROR(x, args...) LOG_E(TMR, x, ##args)
|
||||
#endif
|
||||
|
||||
#ifndef TMR_DEBUG
|
||||
# define TMR_DEBUG(x, args...) do { fprintf(stdout, "[TMR][D]"x, ##args); } while(0)
|
||||
#endif
|
||||
#ifndef TMR_ERROR
|
||||
# define TMR_ERROR(x, args...) do { fprintf(stdout, "[TMR][E]"x, ##args); } while(0)
|
||||
#endif
|
||||
|
||||
int timer_handle_signal(siginfo_t *info);
|
||||
|
||||
struct timer_elm_s {
|
||||
task_id_t task_id; ///< Task ID which has requested the timer
|
||||
int32_t instance; ///< Instance of the task which has requested the timer
|
||||
timer_t timer; ///< Unique timer id
|
||||
timer_type_t type; ///< Timer type
|
||||
void *timer_arg; ///< Optional argument that will be passed when timer expires
|
||||
STAILQ_ENTRY(timer_elm_s) entries; ///< Pointer to next element
|
||||
};
|
||||
|
||||
typedef struct timer_desc_s {
|
||||
STAILQ_HEAD(timer_list_head, timer_elm_s) timer_queue;
|
||||
pthread_mutex_t timer_list_mutex;
|
||||
struct timespec timeout;
|
||||
} timer_desc_t;
|
||||
|
||||
static timer_desc_t timer_desc;
|
||||
|
||||
#define TIMER_SEARCH(vAR, tIMERfIELD, tIMERvALUE, tIMERqUEUE) \
|
||||
do { \
|
||||
STAILQ_FOREACH(vAR, tIMERqUEUE, entries) { \
|
||||
if (((vAR)->tIMERfIELD == tIMERvALUE)) \
|
||||
break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
int timer_handle_signal(siginfo_t *info)
|
||||
{
|
||||
struct timer_elm_s *timer_p;
|
||||
MessageDef *message_p;
|
||||
timer_has_expired_t *timer_expired_p;
|
||||
task_id_t task_id;
|
||||
int32_t instance;
|
||||
|
||||
/* Get back pointer to timer list element */
|
||||
timer_p = (struct timer_elm_s *)info->si_ptr;
|
||||
|
||||
// LG: To many traces for msc timer:
|
||||
TMR_DEBUG("Timer with id 0x%lx has expired\n", (long)timer_p->timer);
|
||||
|
||||
task_id = timer_p->task_id;
|
||||
instance = timer_p->instance;
|
||||
message_p = itti_alloc_new_message(TASK_TIMER, TIMER_HAS_EXPIRED);
|
||||
|
||||
timer_expired_p = &message_p->ittiMsg.timer_has_expired;
|
||||
|
||||
timer_expired_p->timer_id = (long)timer_p->timer;
|
||||
timer_expired_p->arg = timer_p->timer_arg;
|
||||
|
||||
/* Timer is a one shot timer, remove it */
|
||||
if (timer_p->type == TIMER_ONE_SHOT) {
|
||||
// if (timer_delete(timer_p->timer) < 0) {
|
||||
// TMR_DEBUG("Failed to delete timer 0x%lx\n", (long)timer_p->timer);
|
||||
// }
|
||||
// TMR_DEBUG("Removed timer 0x%lx\n", (long)timer_p->timer);
|
||||
// pthread_mutex_lock(&timer_desc.timer_list_mutex);
|
||||
// STAILQ_REMOVE(&timer_desc.timer_queue, timer_p, timer_elm_s, entries);
|
||||
// pthread_mutex_unlock(&timer_desc.timer_list_mutex);
|
||||
// free(timer_p);
|
||||
// timer_p = NULL;
|
||||
if (timer_remove((long)timer_p->timer) != 0) {
|
||||
TMR_DEBUG("Failed to delete timer 0x%lx\n", (long)timer_p->timer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Notify task of timer expiry */
|
||||
if (itti_send_msg_to_task(task_id, instance, message_p) < 0) {
|
||||
TMR_DEBUG("Failed to send msg TIMER_HAS_EXPIRED to task %u\n", task_id);
|
||||
free(message_p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(ENB_AGENT_SB_IF)
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_setup(
|
||||
uint32_t interval_sec,
|
||||
uint32_t interval_us,
|
||||
task_id_t task_id,
|
||||
int32_t instance,
|
||||
timer_type_t type,
|
||||
void *timer_arg,
|
||||
long *timer_id)
|
||||
{
|
||||
struct sigevent se;
|
||||
struct itimerspec its;
|
||||
struct timer_elm_s *timer_p;
|
||||
timer_t timer;
|
||||
|
||||
if (timer_id == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
AssertFatal (type < TIMER_TYPE_MAX, "Invalid timer type (%d/%d)!\n", type, TIMER_TYPE_MAX);
|
||||
|
||||
/* Allocate new timer list element */
|
||||
timer_p = malloc(sizeof(struct timer_elm_s));
|
||||
|
||||
if (timer_p == NULL) {
|
||||
TMR_ERROR("Failed to create new timer element\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&timer, 0, sizeof(timer_t));
|
||||
memset(&se, 0, sizeof(struct sigevent));
|
||||
|
||||
timer_p->task_id = task_id;
|
||||
timer_p->instance = instance;
|
||||
timer_p->type = type;
|
||||
timer_p->timer_arg = timer_arg;
|
||||
|
||||
/* Setting up alarm */
|
||||
/* Set and enable alarm */
|
||||
se.sigev_notify = SIGEV_SIGNAL;
|
||||
se.sigev_signo = SIGTIMER;
|
||||
se.sigev_value.sival_ptr = timer_p;
|
||||
|
||||
/* At the timer creation, the timer structure will be filled in with timer_id,
|
||||
* which is unique for this process. This id is allocated by kernel and the
|
||||
* value might be used to distinguish timers.
|
||||
*/
|
||||
if (timer_create(CLOCK_REALTIME, &se, &timer) < 0) {
|
||||
TMR_ERROR("Failed to create timer: (%s:%d)\n", strerror(errno), errno);
|
||||
free(timer_p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Fill in the first expiration value. */
|
||||
its.it_value.tv_sec = interval_sec;
|
||||
its.it_value.tv_nsec = interval_us * 1000;
|
||||
|
||||
if (type == TIMER_PERIODIC) {
|
||||
/* Asked for periodic timer. We set the interval time */
|
||||
its.it_interval.tv_sec = interval_sec;
|
||||
its.it_interval.tv_nsec = interval_us * 1000;
|
||||
} else {
|
||||
/* Asked for one-shot timer. Do not set the interval field */
|
||||
its.it_interval.tv_sec = 0;
|
||||
its.it_interval.tv_nsec = 0;
|
||||
}
|
||||
|
||||
timer_settime(timer, 0, &its, NULL);
|
||||
/* Simply set the timer_id argument. so it can be used by caller */
|
||||
*timer_id = (long)timer;
|
||||
TMR_DEBUG("Requesting new %s timer with id 0x%lx that expires within "
|
||||
"%d sec and %d usec\n",
|
||||
type == TIMER_PERIODIC ? "periodic" : "single shot",
|
||||
*timer_id, interval_sec, interval_us);
|
||||
|
||||
timer_p->timer = timer;
|
||||
|
||||
/* Lock the queue and insert the timer at the tail */
|
||||
pthread_mutex_lock(&timer_desc.timer_list_mutex);
|
||||
STAILQ_INSERT_TAIL(&timer_desc.timer_queue, timer_p, entries);
|
||||
pthread_mutex_unlock(&timer_desc.timer_list_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_remove(long timer_id)
|
||||
{
|
||||
int rc = 0;
|
||||
struct timer_elm_s *timer_p;
|
||||
|
||||
TMR_DEBUG("Removing timer 0x%lx\n", timer_id);
|
||||
|
||||
pthread_mutex_lock(&timer_desc.timer_list_mutex);
|
||||
TIMER_SEARCH(timer_p, timer, ((timer_t)timer_id), &timer_desc.timer_queue);
|
||||
|
||||
/* We didn't find the timer in list */
|
||||
if (timer_p == NULL) {
|
||||
pthread_mutex_unlock(&timer_desc.timer_list_mutex);
|
||||
TMR_ERROR("Didn't find timer 0x%lx in list\n", timer_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
STAILQ_REMOVE(&timer_desc.timer_queue, timer_p, timer_elm_s, entries);
|
||||
pthread_mutex_unlock(&timer_desc.timer_list_mutex);
|
||||
|
||||
if (timer_delete(timer_p->timer) < 0) {
|
||||
TMR_ERROR("Failed to delete timer 0x%lx\n", (long)timer_p->timer);
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
free(timer_p);
|
||||
timer_p = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
TMR_DEBUG("Initializing TIMER task interface\n");
|
||||
|
||||
memset(&timer_desc, 0, sizeof(timer_desc_t));
|
||||
|
||||
STAILQ_INIT(&timer_desc.timer_queue);
|
||||
pthread_mutex_init(&timer_desc.timer_list_mutex, NULL);
|
||||
|
||||
TMR_DEBUG("Initializing TIMER task interface: DONE\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef TIMER_H_
|
||||
#define TIMER_H_
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#define SIGTIMER SIGRTMIN
|
||||
|
||||
typedef enum timer_type_s {
|
||||
TIMER_PERIODIC,
|
||||
TIMER_ONE_SHOT,
|
||||
TIMER_TYPE_MAX,
|
||||
} timer_type_t;
|
||||
|
||||
int timer_handle_signal(siginfo_t *info);
|
||||
|
||||
/** \brief Request a new timer
|
||||
* \param interval_sec timer interval in seconds
|
||||
* \param interval_us timer interval in micro seconds
|
||||
* \param task_id task id of the task requesting the timer
|
||||
* \param instance instance of the task requesting the timer
|
||||
* \param type timer type
|
||||
* \param timer_id unique timer identifier
|
||||
* @returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int timer_setup(
|
||||
uint32_t interval_sec,
|
||||
uint32_t interval_us,
|
||||
task_id_t task_id,
|
||||
int32_t instance,
|
||||
timer_type_t type,
|
||||
void *timer_arg,
|
||||
long *timer_id);
|
||||
|
||||
/** \brief Remove the timer from list
|
||||
* \param timer_id unique timer id
|
||||
* @returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
|
||||
int timer_remove(long timer_id);
|
||||
#define timer_stop timer_remove
|
||||
|
||||
/** \brief Initialize timer task and its API
|
||||
* \param mme_config MME common configuration
|
||||
* @returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int timer_init(void);
|
||||
|
||||
#endif
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
MESSAGE_DEF(TIMER_HAS_EXPIRED, MESSAGE_PRIORITY_MED_PLUS, timer_has_expired_t, timer_has_expired)
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef TIMER_MESSAGES_TYPES_H_
|
||||
#define TIMER_MESSAGES_TYPES_H_
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
// Defines to access message fields.
|
||||
#define TIMER_HAS_EXPIRED(mSGpTR) (mSGpTR)->ittiMsg.timer_has_expired
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
typedef struct {
|
||||
void *arg;
|
||||
long timer_id;
|
||||
} timer_has_expired_t;
|
||||
|
||||
#endif /* TIMER_MESSAGES_TYPES_H_ */
|
||||
@@ -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)
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
|
||||
#include "liblfds611.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "openair2/COMMON/phy_messages_def.h"
|
||||
#include "openair2/COMMON/mac_messages_def.h"
|
||||
#include "openair2/COMMON/rlc_messages_def.h"
|
||||
#include "openair2/COMMON/pdcp_messages_def.h"
|
||||
#include "openair2/COMMON/rrc_messages_def.h"
|
||||
#include "openair2/COMMON/nas_messages_def.h"
|
||||
#if ENABLE_RAL
|
||||
#include "openair2/COMMON/ral_messages_def.h"
|
||||
#endif
|
||||
#include "openair2/COMMON/s1ap_messages_def.h"
|
||||
#include "openair2/COMMON/x2ap_messages_def.h"
|
||||
#include "openair2/COMMON/sctp_messages_def.h"
|
||||
#include "openair2/COMMON/udp_messages_def.h"
|
||||
#include "openair2/COMMON/gtpv1_u_messages_def.h"
|
||||
#include "openair2/COMMON/flexran_messages_def.h"
|
||||
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
Author: Laurent THOMAS, Open Cells
|
||||
copyleft: OpenAirInterface Software Alliance and it's licence
|
||||
*/
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
|
||||
#include <intertask_interface.h>
|
||||
|
||||
typedef struct timer_elm_s {
|
||||
timer_type_t type; ///< Timer type
|
||||
long instance;
|
||||
long duration;
|
||||
uint64_t timeout;
|
||||
void *timer_arg; ///< Optional argument that will be passed when timer expires
|
||||
} timer_elm_t ;
|
||||
|
||||
typedef struct task_list_s {
|
||||
task_info_t admin;
|
||||
pthread_t thread;
|
||||
pthread_mutex_t queue_cond_lock;
|
||||
std::vector<MessageDef *> message_queue;
|
||||
std::map<long,timer_elm_t> timer_map;
|
||||
uint64_t next_timer=UINT64_MAX;
|
||||
struct epoll_event *events =NULL;
|
||||
int nb_fd_epoll=0;
|
||||
int nb_events=0;
|
||||
int epoll_fd=-1;
|
||||
int sem_fd=-1;
|
||||
} task_list_t;
|
||||
|
||||
int timer_expired(int fd);
|
||||
task_list_t tasks[TASK_MAX];
|
||||
|
||||
extern "C" {
|
||||
void *pool_buffer_init (void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *pool_buffer_clean (void *arg) {
|
||||
//-----------------------------------------------------------------------------
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_mem_block (mem_block_t *leP, const char *caller) {
|
||||
AssertFatal(leP!=NULL,"");
|
||||
free(leP);
|
||||
}
|
||||
|
||||
mem_block_t *get_free_mem_block (uint32_t sizeP, const char *caller) {
|
||||
mem_block_t *ptr=(mem_block_t *)malloc(sizeP+sizeof(mem_block_t));
|
||||
ptr->next = NULL;
|
||||
ptr->previous = NULL;
|
||||
ptr->data=((unsigned char *)ptr)+sizeof(mem_block_t);
|
||||
ptr->size=sizeP;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size) {
|
||||
void *ptr = NULL;
|
||||
AssertFatal ((ptr=malloc (size)) != NULL, "Memory allocation of %zu bytes failed (%d -> %d)!\n",
|
||||
size, origin_task_id, destination_task_id);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int itti_free(task_id_t task_id, void *ptr) {
|
||||
AssertFatal (ptr != NULL, "Trying to free a NULL pointer (%d)!\n", task_id);
|
||||
free (ptr);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
MessageDef *itti_alloc_new_message_sized(task_id_t origin_task_id, MessagesIds message_id, MessageHeaderSize size) {
|
||||
MessageDef *temp = (MessageDef *)itti_malloc (origin_task_id, TASK_UNKNOWN, sizeof(MessageHeader) + size);
|
||||
temp->ittiMsgHeader.messageId = message_id;
|
||||
temp->ittiMsgHeader.originTaskId = origin_task_id;
|
||||
temp->ittiMsgHeader.ittiMsgSize = size;
|
||||
return temp;
|
||||
}
|
||||
|
||||
MessageDef *itti_alloc_new_message(task_id_t origin_task_id, MessagesIds message_id) {
|
||||
int size=sizeof(MessageHeader) + messages_info[message_id].size;
|
||||
MessageDef *temp = (MessageDef *)itti_malloc (origin_task_id, TASK_UNKNOWN, size);
|
||||
temp->ittiMsgHeader.messageId = message_id;
|
||||
temp->ittiMsgHeader.originTaskId = origin_task_id;
|
||||
temp->ittiMsgHeader.ittiMsgSize = size;
|
||||
return temp;
|
||||
//return itti_alloc_new_message_sized(origin_task_id, message_id, messages_info[message_id].size);
|
||||
}
|
||||
|
||||
static inline int itti_send_msg_to_task_locked(task_id_t destination_task_id, instance_t instance, MessageDef *message) {
|
||||
task_list_t *t=tasks+destination_task_id;
|
||||
message->ittiMsgHeader.destinationTaskId = destination_task_id;
|
||||
message->ittiMsgHeader.instance = instance;
|
||||
message->ittiMsgHeader.lte_time.frame = 0;
|
||||
message->ittiMsgHeader.lte_time.slot = 0;
|
||||
int message_id = message->ittiMsgHeader.messageId;
|
||||
size_t s=t->message_queue.size();
|
||||
|
||||
if ( s > t->admin.queue_size )
|
||||
LOG_E(TMR,"Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s );
|
||||
|
||||
if ( s > 50 )
|
||||
LOG_I(TMR,"Queue for %s task size: %ld\n",itti_get_task_name(destination_task_id), s+1);
|
||||
|
||||
t->message_queue.insert(t->message_queue.begin(), message);
|
||||
eventfd_t sem_counter = 1;
|
||||
AssertFatal ( sizeof(sem_counter) == write(t->sem_fd, &sem_counter, sizeof(sem_counter)), "");
|
||||
LOG_D(TMR,"sent messages id=%d to %s\n",message_id, t->admin.name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int itti_send_msg_to_task(task_id_t destination_task_id, instance_t instance, MessageDef *message) {
|
||||
task_list_t *t=&tasks[destination_task_id];
|
||||
pthread_mutex_lock (&t->queue_cond_lock);
|
||||
int ret=itti_send_msg_to_task_locked(destination_task_id, instance, message);
|
||||
pthread_mutex_unlock (&t->queue_cond_lock);
|
||||
|
||||
while ( t->message_queue.size()>0 && t->admin.func != NULL )
|
||||
t->admin.func(NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void itti_subscribe_event_fd(task_id_t task_id, int fd) {
|
||||
struct epoll_event event;
|
||||
task_list_t *t=&tasks[task_id];
|
||||
t->nb_fd_epoll++;
|
||||
t->events = (struct epoll_event *)realloc((void *)t->events,
|
||||
t->nb_fd_epoll * sizeof(struct epoll_event));
|
||||
event.events = EPOLLIN | EPOLLERR;
|
||||
event.data.u64 = 0;
|
||||
event.data.fd = fd;
|
||||
AssertFatal(epoll_ctl(t->epoll_fd, EPOLL_CTL_ADD, fd, &event) == 0,
|
||||
"epoll_ctl (EPOLL_CTL_ADD) failed for task %s, fd %d: %s!\n",
|
||||
itti_get_task_name(task_id), fd, strerror(errno));
|
||||
}
|
||||
|
||||
void itti_unsubscribe_event_fd(task_id_t task_id, int fd) {
|
||||
task_list_t *t=&tasks[task_id];
|
||||
AssertFatal (epoll_ctl(t->epoll_fd, EPOLL_CTL_DEL, fd, NULL) == 0,
|
||||
"epoll_ctl (EPOLL_CTL_DEL) failed for task %s, fd %d: %s!\n",
|
||||
itti_get_task_name(task_id), fd, strerror(errno));
|
||||
t->nb_fd_epoll--;
|
||||
}
|
||||
|
||||
static inline int itti_get_events_locked(task_id_t task_id, struct epoll_event **events) {
|
||||
task_list_t *t=&tasks[task_id];
|
||||
uint64_t current_time=0;
|
||||
|
||||
do {
|
||||
if ( t->next_timer != UINT64_MAX ) {
|
||||
struct timespec tp;
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
current_time=(uint64_t)tp.tv_sec*1000+tp.tv_nsec/(1000*1000);
|
||||
|
||||
if ( t->next_timer < current_time) {
|
||||
t->next_timer=UINT64_MAX;
|
||||
|
||||
// Proceed expired timer
|
||||
for ( auto it=t->timer_map.begin() ; it != t->timer_map.end() ; ++it ) {
|
||||
if ( it->second.timeout < current_time ) {
|
||||
MessageDef *message = itti_alloc_new_message(TASK_TIMER, TIMER_HAS_EXPIRED);
|
||||
message->ittiMsg.timer_has_expired.timer_id=it->first;
|
||||
message->ittiMsg.timer_has_expired.arg=it->second.timer_arg;
|
||||
|
||||
if (itti_send_msg_to_task_locked(task_id, it->second.instance, message) < 0) {
|
||||
LOG_W(TMR,"Failed to send msg TIMER_HAS_EXPIRED to task %u\n", task_id);
|
||||
free(message);
|
||||
t->timer_map.erase(it);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( it->second.type==TIMER_PERIODIC ) {
|
||||
it->second.timeout+=it->second.duration;
|
||||
|
||||
if (it->second.timeout < t->next_timer)
|
||||
t->next_timer=it->second.timeout;
|
||||
} else
|
||||
t->timer_map.erase(it);
|
||||
} else if (it->second.timeout < t->next_timer)
|
||||
t->next_timer=it->second.timeout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int epoll_timeout = -1;
|
||||
|
||||
if ( t->next_timer != UINT64_MAX )
|
||||
epoll_timeout = t->next_timer-current_time;
|
||||
|
||||
pthread_mutex_unlock(&t->queue_cond_lock);
|
||||
LOG_D(TMR,"enter blocking wait for %s\n", itti_get_task_name(task_id));
|
||||
t->nb_events = epoll_wait(t->epoll_fd,t->events,t->nb_fd_epoll, epoll_timeout);
|
||||
} while (t->nb_events < 0 && (errno == EINTR || errno == EAGAIN ) );
|
||||
|
||||
AssertFatal (t->nb_events >=0,
|
||||
"epoll_wait failed for task %s, nb fds %d, timeout %lu: %s!\n",
|
||||
itti_get_task_name(task_id), t->nb_fd_epoll, t->next_timer != UINT64_MAX ? t->next_timer-current_time : -1, strerror(errno));
|
||||
LOG_D(TMR,"receive on %d descriptors for %s\n", t->nb_events, itti_get_task_name(task_id));
|
||||
|
||||
if (t->nb_events == 0)
|
||||
/* No data to read -> return */
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < t->nb_events; i++) {
|
||||
/* Check if there is an event for ITTI for the event fd */
|
||||
if ((t->events[i].events & EPOLLIN) &&
|
||||
(t->events[i].data.fd == t->sem_fd)) {
|
||||
eventfd_t sem_counter;
|
||||
/* Read will always return 1 */
|
||||
AssertFatal( sizeof(sem_counter) == read (t->sem_fd, &sem_counter, sizeof(sem_counter)), "");
|
||||
/* Mark that the event has been processed */
|
||||
t->events[i].events &= ~EPOLLIN;
|
||||
}
|
||||
}
|
||||
|
||||
*events = t->events;
|
||||
return t->nb_events;
|
||||
}
|
||||
|
||||
int itti_get_events(task_id_t task_id, struct epoll_event **events) {
|
||||
pthread_mutex_lock(&tasks[task_id].queue_cond_lock);
|
||||
return itti_get_events_locked(task_id, events);
|
||||
}
|
||||
|
||||
void itti_receive_msg(task_id_t task_id, MessageDef **received_msg) {
|
||||
// Reception of one message, blocking caller
|
||||
task_list_t *t=&tasks[task_id];
|
||||
pthread_mutex_lock(&t->queue_cond_lock);
|
||||
|
||||
// Weird condition to deal with crap legacy itti interface
|
||||
if ( t->nb_fd_epoll == 1 ) {
|
||||
while (t->message_queue.empty()) {
|
||||
itti_get_events_locked(task_id, &t->events);
|
||||
pthread_mutex_lock(&t->queue_cond_lock);
|
||||
}
|
||||
} else {
|
||||
if (t->message_queue.empty()) {
|
||||
itti_get_events_locked(task_id, &t->events);
|
||||
pthread_mutex_lock(&t->queue_cond_lock);
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy design: we return even if we have no message
|
||||
// in this case, *received_msg is NULL
|
||||
if (t->message_queue.empty()) {
|
||||
*received_msg=NULL;
|
||||
LOG_D(TMR,"task %s received even from other fd (total fds: %d), returning msg NULL\n",t->admin.name, t->nb_fd_epoll);
|
||||
} else {
|
||||
*received_msg=t->message_queue.back();
|
||||
t->message_queue.pop_back();
|
||||
LOG_D(TMR,"task %s received a message\n",t->admin.name);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock (&t->queue_cond_lock);
|
||||
}
|
||||
|
||||
void itti_poll_msg(task_id_t task_id, MessageDef **received_msg) {
|
||||
//reception of one message, non-blocking
|
||||
task_list_t *t=&tasks[task_id];
|
||||
pthread_mutex_lock(&t->queue_cond_lock);
|
||||
|
||||
if (!t->message_queue.empty()) {
|
||||
LOG_D(TMR,"task %s received a message in polling mode\n",t->admin.name);
|
||||
*received_msg=t->message_queue.back();
|
||||
t->message_queue.pop_back();
|
||||
} else
|
||||
*received_msg=NULL;
|
||||
|
||||
pthread_mutex_unlock (&t->queue_cond_lock);
|
||||
}
|
||||
|
||||
int itti_create_task(task_id_t task_id, void *(*start_routine)(void *), void *args_p) {
|
||||
task_list_t *t=&tasks[task_id];
|
||||
AssertFatal ( pthread_create (&t->thread, NULL, start_routine, args_p) ==0,
|
||||
"Thread creation for task %d failed!\n", task_id);
|
||||
pthread_setname_np( t->thread, itti_get_task_name(task_id) );
|
||||
LOG_I(TMR,"Created Posix thread %s\n", itti_get_task_name(task_id) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void itti_exit_task(void) {
|
||||
pthread_exit (NULL);
|
||||
}
|
||||
|
||||
void itti_terminate_tasks(task_id_t task_id) {
|
||||
// Sends Terminate signals to all tasks.
|
||||
itti_send_terminate_message (task_id);
|
||||
usleep(100*1000); // Allow the tasks to receive the message before going returning to main thread
|
||||
}
|
||||
|
||||
int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
|
||||
const message_info_t *messages_info) {
|
||||
AssertFatal(TASK_MAX<UINT16_MAX, "Max itti tasks");
|
||||
|
||||
for(int i=0; i<task_max; ++i) {
|
||||
LOG_I(TMR,"Starting itti queue: %s as task %d\n", tasks_info[i].name, i);
|
||||
pthread_mutex_init(&tasks[i].queue_cond_lock, NULL);
|
||||
memcpy(&tasks[i].admin, &tasks_info[i], sizeof(task_info_t));
|
||||
AssertFatal( ( tasks[i].epoll_fd = epoll_create1(0) ) >=0, "");
|
||||
AssertFatal( ( tasks[i].sem_fd = eventfd(0, EFD_SEMAPHORE) ) >=0, "");
|
||||
itti_subscribe_event_fd((task_id_t)i, tasks[i].sem_fd);
|
||||
|
||||
if (tasks[i].admin.threadFunc != NULL)
|
||||
itti_create_task((task_id_t)i, tasks[i].admin.threadFunc, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_setup(
|
||||
uint32_t interval_sec,
|
||||
uint32_t interval_us,
|
||||
task_id_t task_id,
|
||||
int32_t instance,
|
||||
timer_type_t type,
|
||||
void *timer_arg,
|
||||
long *timer_id) {
|
||||
task_list_t *t=&tasks[task_id];
|
||||
|
||||
do {
|
||||
// set the taskid in the timer id to keep compatible with the legacy API
|
||||
// timer_remove() takes only the timer id as parameter
|
||||
*timer_id=(random()%UINT16_MAX) << 16 | task_id ;
|
||||
} while ( t->timer_map.find(*timer_id) != t->timer_map.end());
|
||||
|
||||
/* Allocate new timer list element */
|
||||
timer_elm_t timer;
|
||||
struct timespec tp;
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
|
||||
if (interval_us%1000 != 0)
|
||||
LOG_W(TMR, "Can't set timer precision below 1ms, rounding it\n");
|
||||
|
||||
timer.duration = interval_sec*1000+interval_us/1000;
|
||||
timer.timeout= ((uint64_t)tp.tv_sec*1000+tp.tv_nsec/(1000*1000)+timer.duration);
|
||||
timer.instance = instance;
|
||||
timer.type = type;
|
||||
timer.timer_arg = timer_arg;
|
||||
pthread_mutex_lock (&t->queue_cond_lock);
|
||||
t->timer_map[*timer_id]= timer;
|
||||
|
||||
if (timer.timeout < t->next_timer)
|
||||
t->next_timer=timer.timeout;
|
||||
|
||||
eventfd_t sem_counter = 1;
|
||||
AssertFatal ( sizeof(sem_counter) == write(t->sem_fd, &sem_counter, sizeof(sem_counter)), "");
|
||||
pthread_mutex_unlock (&t->queue_cond_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_remove(long timer_id) {
|
||||
task_id_t task_id=(task_id_t)(timer_id&0xffff);
|
||||
int ret;
|
||||
pthread_mutex_lock (&tasks[task_id].queue_cond_lock);
|
||||
ret=tasks[task_id].timer_map.erase(timer_id);
|
||||
pthread_mutex_unlock (&tasks[task_id].queue_cond_lock);
|
||||
|
||||
if (ret==1)
|
||||
return 0;
|
||||
else {
|
||||
LOG_W(TMR, "tried to remove a non existing timer\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *itti_get_message_name(MessagesIds message_id) {
|
||||
return messages_info[message_id].name;
|
||||
}
|
||||
|
||||
const char *itti_get_task_name(task_id_t task_id) {
|
||||
return tasks[task_id].admin.name;
|
||||
}
|
||||
|
||||
// void for compatibility
|
||||
void itti_send_terminate_message(task_id_t task_id) {
|
||||
}
|
||||
|
||||
void itti_wait_tasks_end(void) {
|
||||
while(1)
|
||||
sleep(24*3600);
|
||||
}
|
||||
|
||||
void itti_update_lte_time(uint32_t frame, uint8_t slot) {}
|
||||
void itti_set_task_real_time(task_id_t task_id) {}
|
||||
void itti_mark_task_ready(task_id_t task_id) {
|
||||
// Function meaning is clear, but legacy implementation is wrong
|
||||
// keep it void is fine: today implementation accepts messages in the queue before task is ready
|
||||
}
|
||||
void itti_wait_ready(int wait_tasks) {
|
||||
// Stupid function, kept for compatibility (the parameter is meaningless!!!)
|
||||
}
|
||||
int signal_mask(void) { return 0;}
|
||||
}
|
||||
@@ -0,0 +1,536 @@
|
||||
/*
|
||||
Author: Laurent THOMAS, Open Cells
|
||||
Copyleft: OpenAirInterface software alliance and it's licence
|
||||
*/
|
||||
#ifndef INTERTASK_INTERFACE_H_
|
||||
#define INTERTASK_INTERFACE_H_
|
||||
#include <stdint.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include <mem_block.h>
|
||||
#include <assertions.h>
|
||||
|
||||
|
||||
typedef enum timer_type_s {
|
||||
TIMER_PERIODIC,
|
||||
TIMER_ONE_SHOT,
|
||||
TIMER_TYPE_MAX,
|
||||
} timer_type_t;
|
||||
|
||||
typedef struct {
|
||||
void *arg;
|
||||
long timer_id;
|
||||
} timer_has_expired_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t interval_sec;
|
||||
uint32_t interval_us;
|
||||
long task_id;
|
||||
int32_t instance;
|
||||
timer_type_t type;
|
||||
void *timer_arg;
|
||||
long timer_id;
|
||||
} timer_create_t;
|
||||
|
||||
typedef struct {
|
||||
long task_id;
|
||||
long timer_id;
|
||||
} timer_delete_t;
|
||||
|
||||
|
||||
typedef struct itti_lte_time_s {
|
||||
uint32_t frame;
|
||||
uint8_t slot;
|
||||
} itti_lte_time_t;
|
||||
|
||||
|
||||
typedef struct IttiMsgEmpty_s {
|
||||
} IttiMsgEmpty;
|
||||
|
||||
typedef struct IttiMsgText_s {
|
||||
uint32_t size;
|
||||
char text[];
|
||||
} IttiMsgText;
|
||||
|
||||
#include <openair2/COMMON/phy_messages_types.h>
|
||||
#include <openair2/COMMON/mac_messages_types.h>
|
||||
#include <openair2/COMMON/rlc_messages_types.h>
|
||||
#include <openair2/COMMON/pdcp_messages_types.h>
|
||||
#include <openair2/COMMON/networkDef.h>
|
||||
#include <openair2/COMMON/as_message.h>
|
||||
#include <openair2/RRC/LTE/rrc_types.h>
|
||||
#include <openair2/COMMON/rrc_messages_types.h>
|
||||
|
||||
#include <openair3/NAS/COMMON/UTIL/OctetString.h>
|
||||
#include <openair3/NAS/COMMON/IES/AccessPointName.h>
|
||||
#include <openair3/NAS/COMMON/IES/AdditionalUpdateResult.h>
|
||||
#include <openair3/NAS/COMMON/IES/AdditionalUpdateType.h>
|
||||
#include <openair3/NAS/COMMON/IES/ApnAggregateMaximumBitRate.h>
|
||||
#include <openair3/NAS/COMMON/IES/AuthenticationFailureParameter.h>
|
||||
#include <openair3/NAS/COMMON/IES/AuthenticationParameterAutn.h>
|
||||
#include <openair3/NAS/COMMON/IES/AuthenticationParameterRand.h>
|
||||
#include <openair3/NAS/COMMON/IES/AuthenticationResponseParameter.h>
|
||||
#include <openair3/NAS/COMMON/IES/CipheringKeySequenceNumber.h>
|
||||
#include <openair3/NAS/COMMON/IES/Cli.h>
|
||||
#include <openair3/NAS/COMMON/IES/CsfbResponse.h>
|
||||
#include <openair3/NAS/COMMON/IES/DaylightSavingTime.h>
|
||||
#include <openair3/NAS/COMMON/IES/DetachType.h>
|
||||
#include <openair3/NAS/COMMON/IES/DrxParameter.h>
|
||||
#include <openair3/NAS/COMMON/IES/EmergencyNumberList.h>
|
||||
#include <openair3/NAS/COMMON/IES/EmmCause.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsAttachResult.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsAttachType.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsBearerContextStatus.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsBearerIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsMobileIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsNetworkFeatureSupport.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsQualityOfService.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsUpdateResult.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsUpdateType.h>
|
||||
#include <openair3/NAS/COMMON/IES/EsmCause.h>
|
||||
#include <openair3/NAS/COMMON/IES/EsmInformationTransferFlag.h>
|
||||
#include <openair3/NAS/COMMON/IES/EsmMessageContainer.h>
|
||||
#include <openair3/NAS/COMMON/IES/GprsTimer.h>
|
||||
#include <openair3/NAS/COMMON/IES/GutiType.h>
|
||||
#include <openair3/NAS/COMMON/IES/IdentityType2.h>
|
||||
#include <openair3/NAS/COMMON/IES/ImeisvRequest.h>
|
||||
#include <openair3/NAS/COMMON/IES/KsiAndSequenceNumber.h>
|
||||
#include <openair3/NAS/COMMON/IES/LcsClientIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/LcsIndicator.h>
|
||||
#include <openair3/NAS/COMMON/IES/LinkedEpsBearerIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/LlcServiceAccessPointIdentifier.h>
|
||||
#include <openair3/NAS/COMMON/IES/LocationAreaIdentification.h>
|
||||
#include <openair3/NAS/COMMON/IES/MessageType.h>
|
||||
#include <openair3/NAS/COMMON/IES/MobileIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/MobileStationClassmark2.h>
|
||||
#include <openair3/NAS/COMMON/IES/MobileStationClassmark3.h>
|
||||
#include <openair3/NAS/COMMON/IES/MsNetworkCapability.h>
|
||||
#include <openair3/NAS/COMMON/IES/MsNetworkFeatureSupport.h>
|
||||
#include <openair3/NAS/COMMON/IES/NasKeySetIdentifier.h>
|
||||
#include <openair3/NAS/COMMON/IES/NasMessageContainer.h>
|
||||
#include <openair3/NAS/COMMON/IES/NasRequestType.h>
|
||||
#include <openair3/NAS/COMMON/IES/NasSecurityAlgorithms.h>
|
||||
#include <openair3/NAS/COMMON/IES/NetworkName.h>
|
||||
#include <openair3/NAS/COMMON/IES/Nonce.h>
|
||||
#include <openair3/NAS/COMMON/IES/PacketFlowIdentifier.h>
|
||||
#include <openair3/NAS/COMMON/IES/PagingIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/PdnAddress.h>
|
||||
#include <openair3/NAS/COMMON/IES/PdnType.h>
|
||||
#include <openair3/NAS/COMMON/IES/PlmnList.h>
|
||||
#include <openair3/NAS/COMMON/IES/ProcedureTransactionIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/ProtocolConfigurationOptions.h>
|
||||
#include <openair3/NAS/COMMON/IES/ProtocolDiscriminator.h>
|
||||
#include <openair3/NAS/COMMON/IES/PTmsiSignature.h>
|
||||
#include <openair3/NAS/COMMON/IES/QualityOfService.h>
|
||||
#include <openair3/NAS/COMMON/IES/RadioPriority.h>
|
||||
#include <openair3/NAS/COMMON/IES/SecurityHeaderType.h>
|
||||
#include <openair3/NAS/COMMON/IES/ServiceType.h>
|
||||
#include <openair3/NAS/COMMON/IES/ShortMac.h>
|
||||
#include <openair3/NAS/COMMON/IES/SsCode.h>
|
||||
#include <openair3/NAS/COMMON/IES/SupportedCodecList.h>
|
||||
#include <openair3/NAS/COMMON/IES/TimeZoneAndTime.h>
|
||||
#include <openair3/NAS/COMMON/IES/TimeZone.h>
|
||||
#include <openair3/NAS/COMMON/IES/TmsiStatus.h>
|
||||
#include <openair3/NAS/COMMON/IES/TrackingAreaIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/TrackingAreaIdentityList.h>
|
||||
#include <openair3/NAS/COMMON/IES/TrafficFlowAggregateDescription.h>
|
||||
#include <openair3/NAS/COMMON/IES/TrafficFlowTemplate.h>
|
||||
#include <openair3/NAS/COMMON/IES/TransactionIdentifier.h>
|
||||
#include <openair3/NAS/COMMON/IES/UeNetworkCapability.h>
|
||||
#include <openair3/NAS/COMMON/IES/UeRadioCapabilityInformationUpdateNeeded.h>
|
||||
#include <openair3/NAS/COMMON/IES/UeSecurityCapability.h>
|
||||
#include <openair3/NAS/COMMON/IES/VoiceDomainPreferenceAndUeUsageSetting.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextAccept.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDefaultEpsBearerContextAccept.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDefaultEpsBearerContextReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDefaultEpsBearerContextRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceAllocationReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceAllocationRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceModificationReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceModificationRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/DeactivateEpsBearerContextAccept.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/DeactivateEpsBearerContextRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/esm_cause.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/EsmInformationRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/EsmInformationResponse.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/EsmStatus.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ModifyEpsBearerContextAccept.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ModifyEpsBearerContextReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ModifyEpsBearerContextRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/PdnConnectivityReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/PdnConnectivityRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/PdnDisconnectReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/PdnDisconnectRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/esm_msgDef.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/esm_msg.h>
|
||||
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AttachAccept.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AttachComplete.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AttachReject.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AttachRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationFailure.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationReject.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationResponse.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/CsServiceNotification.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/DetachAccept.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/DetachRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/DownlinkNasTransport.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/emm_cause.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/EmmInformation.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/EmmStatus.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/ExtendedServiceRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/GutiReallocationCommand.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/GutiReallocationComplete.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/IdentityRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/IdentityResponse.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/NASSecurityModeCommand.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/NASSecurityModeComplete.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/SecurityModeReject.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/ServiceReject.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/ServiceRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateAccept.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateComplete.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateReject.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/UplinkNasTransport.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/emm_msgDef.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/emm_msg.h>
|
||||
|
||||
#include <openair3/NAS/COMMON/API/NETWORK/nas_message.h>
|
||||
#include <openair2/COMMON/nas_messages_types.h>
|
||||
#if ENABLE_RAL
|
||||
#include <ral_messages_types.h>
|
||||
#endif
|
||||
#include <openair2/COMMON/s1ap_messages_types.h>
|
||||
#include <openair2/COMMON/x2ap_messages_types.h>
|
||||
#include <openair2/COMMON/sctp_messages_types.h>
|
||||
#include <openair2/COMMON/udp_messages_types.h>
|
||||
#include <openair2/COMMON/gtpv1_u_messages_types.h>
|
||||
#include <openair3/SCTP/sctp_eNB_task.h>
|
||||
#include <openair3/NAS/UE/nas_proc_defs.h>
|
||||
#include <openair3/NAS/UE/ESM/esmData.h>
|
||||
#include <openair3/NAS/COMMON/UTIL/nas_timer.h>
|
||||
#include <openair3/NAS/UE/ESM/esm_pt_defs.h>
|
||||
#include <openair3/NAS/UE/EMM/emm_proc_defs.h>
|
||||
#include <openair3/NAS/UE/EMM/emmData.h>
|
||||
#include <openair3/NAS/UE/EMM/IdleMode_defs.h>
|
||||
#include <openair3/NAS/UE/EMM/emm_fsm_defs.h>
|
||||
#include <openair3/NAS/UE/EMM/emmData.h>
|
||||
#include <openair3/NAS/COMMON/securityDef.h>
|
||||
#include <openair3/NAS/UE/EMM/Authentication.h>
|
||||
#include <openair3/NAS/UE/EMM/SecurityModeControl.h>
|
||||
#include <openair3/NAS/UE/API/USIM/usim_api.h>
|
||||
#include <openair3/NAS/COMMON/userDef.h>
|
||||
#include <openair3/NAS/UE/API/USER/at_command.h>
|
||||
#include <openair3/NAS/UE/API/USER/at_response.h>
|
||||
#include <openair3/NAS/UE/API/USER/user_api_defs.h>
|
||||
#include <openair3/NAS/UE/EMM/LowerLayer_defs.h>
|
||||
#include <openair3/NAS/UE/user_defs.h>
|
||||
#include <openair3/NAS/UE/nas_ue_task.h>
|
||||
#include <openair3/S1AP/s1ap_eNB.h>
|
||||
//#include <proto.h>
|
||||
|
||||
/*
|
||||
static const char *const messages_definition_xml = {
|
||||
#include <messages_xml.h>
|
||||
};
|
||||
*/
|
||||
|
||||
typedef uint32_t MessageHeaderSize;
|
||||
typedef uint32_t itti_message_types_t;
|
||||
typedef unsigned long message_number_t;
|
||||
#define MESSAGE_NUMBER_SIZE (sizeof(unsigned long))
|
||||
|
||||
typedef enum task_priorities_e {
|
||||
TASK_PRIORITY_MAX = 100,
|
||||
TASK_PRIORITY_MAX_LEAST = 85,
|
||||
TASK_PRIORITY_MED_PLUS = 70,
|
||||
TASK_PRIORITY_MED = 55,
|
||||
TASK_PRIORITY_MED_LEAST = 40,
|
||||
TASK_PRIORITY_MIN_PLUS = 25,
|
||||
TASK_PRIORITY_MIN = 10,
|
||||
} task_priorities_t;
|
||||
|
||||
typedef struct {
|
||||
task_priorities_t priority;
|
||||
unsigned int queue_size;
|
||||
/* Printable name */
|
||||
char name[256];
|
||||
void *(*func)(void *) ;
|
||||
void *(*threadFunc)(void *) ;
|
||||
} task_info_t;
|
||||
//
|
||||
//TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL,NULL)
|
||||
//TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL, NULL)
|
||||
//TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL)
|
||||
//TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000, NULL, NULL)
|
||||
|
||||
#define FOREACH_TASK(TASK_DEF) \
|
||||
TASK_DEF(TASK_UNKNOWN, TASK_PRIORITY_MED, 50, NULL, NULL) \
|
||||
TASK_DEF(TASK_TIMER, TASK_PRIORITY_MED, 10, NULL, NULL) \
|
||||
TASK_DEF(TASK_L2L1, TASK_PRIORITY_MAX, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_BM, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_PHY_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_MAC_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RLC_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RRC_ENB_NB_IoT, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_PDCP_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL,NULL)\
|
||||
TASK_DEF(TASK_RAL_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_X2AP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_SCTP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_ENB_APP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_FLEXRAN_AGENT,TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_PHY_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_MAC_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RLC_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_PDCP_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RRC_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_NAS_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RAL_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_MSC, TASK_PRIORITY_MED, 200, NULL, NULL)\
|
||||
TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL)\
|
||||
TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000, NULL, NULL)\
|
||||
TASK_DEF(TASK_MAX, TASK_PRIORITY_MED, 200, NULL, NULL)
|
||||
|
||||
#define TASK_DEF(TaskID, pRIO, qUEUEsIZE, FuNc, ThreadFunc) { pRIO, qUEUEsIZE, #TaskID, FuNc, ThreadFunc },
|
||||
|
||||
/* Map task id to printable name. */
|
||||
static const task_info_t tasks_info[] = {
|
||||
FOREACH_TASK(TASK_DEF)
|
||||
};
|
||||
|
||||
#define TASK_ENUM(TaskID, pRIO, qUEUEsIZE, FuNc,ThreadFunc ) TaskID,
|
||||
//! Tasks id of each task
|
||||
typedef enum {
|
||||
FOREACH_TASK(TASK_ENUM)
|
||||
} task_id_t;
|
||||
|
||||
|
||||
typedef task_id_t thread_id_t;
|
||||
|
||||
typedef enum message_priorities_e {
|
||||
MESSAGE_PRIORITY_MAX = 100,
|
||||
MESSAGE_PRIORITY_MAX_LEAST = 85,
|
||||
MESSAGE_PRIORITY_MED_PLUS = 70,
|
||||
MESSAGE_PRIORITY_MED = 55,
|
||||
MESSAGE_PRIORITY_MED_LEAST = 40,
|
||||
MESSAGE_PRIORITY_MIN_PLUS = 25,
|
||||
MESSAGE_PRIORITY_MIN = 10,
|
||||
} message_priorities_t;
|
||||
|
||||
|
||||
#define FOREACH_MSG(INTERNAL_MSG) \
|
||||
INTERNAL_MSG(TIMER_HAS_EXPIRED, MESSAGE_PRIORITY_MED, timer_has_expired_t, timer_has_expired) \
|
||||
INTERNAL_MSG(INITIALIZE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, initialize_message) \
|
||||
INTERNAL_MSG(ACTIVATE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, activate_message) \
|
||||
INTERNAL_MSG(DEACTIVATE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, deactivate_message) \
|
||||
INTERNAL_MSG(TERMINATE_MESSAGE, MESSAGE_PRIORITY_MAX, IttiMsgEmpty, terminate_message) \
|
||||
INTERNAL_MSG(MESSAGE_TEST, MESSAGE_PRIORITY_MED, IttiMsgEmpty, message_test)
|
||||
|
||||
/* This enum defines messages ids. Each one is unique. */
|
||||
typedef enum {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) iD,
|
||||
FOREACH_MSG(MESSAGE_DEF)
|
||||
#include <all_msg.h>
|
||||
#undef MESSAGE_DEF
|
||||
MESSAGES_ID_MAX,
|
||||
} MessagesIds;
|
||||
|
||||
typedef union msg_s {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) sTRUCT fIELDnAME;
|
||||
FOREACH_MSG(MESSAGE_DEF)
|
||||
#include <all_msg.h>
|
||||
#undef MESSAGE_DEF
|
||||
} msg_t;
|
||||
|
||||
typedef struct MessageHeader_s {
|
||||
MessagesIds messageId; /**< Unique message id as referenced in enum MessagesIds */
|
||||
task_id_t originTaskId; /**< ID of the sender task */
|
||||
task_id_t destinationTaskId; /**< ID of the destination task */
|
||||
instance_t instance; /**< Task instance for virtualization */
|
||||
itti_lte_time_t lte_time;
|
||||
MessageHeaderSize ittiMsgSize; /**< Message size (not including header size) */
|
||||
} MessageHeader;
|
||||
|
||||
typedef struct message_info_s {
|
||||
int id;
|
||||
message_priorities_t priority;
|
||||
/* Message payload size */
|
||||
MessageHeaderSize size;
|
||||
/* Printable name */
|
||||
const char name[256];
|
||||
} message_info_t;
|
||||
|
||||
/* Map message id to message information */
|
||||
static const message_info_t messages_info[] = {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) { iD, pRIO, sizeof(sTRUCT), #iD },
|
||||
FOREACH_MSG(MESSAGE_DEF)
|
||||
#include <all_msg.h>
|
||||
#undef MESSAGE_DEF
|
||||
};
|
||||
|
||||
typedef struct __attribute__ ((__packed__)) MessageDef_s {
|
||||
MessageHeader ittiMsgHeader; /**< Message header */
|
||||
msg_t ittiMsg;
|
||||
} MessageDef;
|
||||
|
||||
|
||||
|
||||
/* Extract the instance from a message */
|
||||
#define ITTI_MESSAGE_GET_INSTANCE(mESSAGE) ((mESSAGE)->ittiMsgHeader.instance)
|
||||
#define ITTI_MSG_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.messageId)
|
||||
#define ITTI_MSG_ORIGIN_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.originTaskId)
|
||||
#define ITTI_MSG_DESTINATION_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.destinationTaskId)
|
||||
#define ITTI_MSG_INSTANCE(mSGpTR) ((mSGpTR)->ittiMsgHeader.instance)
|
||||
#define ITTI_MSG_NAME(mSGpTR) itti_get_message_name(ITTI_MSG_ID(mSGpTR))
|
||||
#define ITTI_MSG_ORIGIN_NAME(mSGpTR) itti_get_task_name(ITTI_MSG_ORIGIN_ID(mSGpTR))
|
||||
#define ITTI_MSG_DESTINATION_NAME(mSGpTR) itti_get_task_name(ITTI_MSG_DESTINATION_ID(mSGpTR))
|
||||
#define TIMER_HAS_EXPIRED(mSGpTR) (mSGpTR)->ittiMsg.timer_has_expired
|
||||
|
||||
#define INSTANCE_DEFAULT (UINT16_MAX - 1)
|
||||
|
||||
static inline int64_t clock_difftime_ns(struct timespec start, struct timespec end) {
|
||||
return (int64_t)( end.tv_sec-start.tv_sec) * (int64_t)(1000*1000*1000) + end.tv_nsec-start.tv_nsec;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \brief Send a message to a task (could be itself)
|
||||
\param task_id Task ID
|
||||
\param instance Instance of the task used for virtualization
|
||||
\param message Pointer to the message to send
|
||||
@returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int itti_send_msg_to_task(task_id_t task_id, instance_t instance, MessageDef *message);
|
||||
|
||||
/** \brief Add a new fd to monitor.
|
||||
NOTE: it is up to the user to read data associated with the fd
|
||||
\param task_id Task ID of the receiving task
|
||||
\param fd The file descriptor to monitor
|
||||
**/
|
||||
void itti_subscribe_event_fd(task_id_t task_id, int fd);
|
||||
|
||||
/** \brief Remove a fd from the list of fd to monitor
|
||||
\param task_id Task ID of the task
|
||||
\param fd The file descriptor to remove
|
||||
**/
|
||||
void itti_unsubscribe_event_fd(task_id_t task_id, int fd);
|
||||
|
||||
/** \brief Return the list of events excluding the fd associated with itti
|
||||
\param task_id Task ID of the task
|
||||
\param events events list
|
||||
@returns number of events to handle
|
||||
**/
|
||||
int itti_get_events(task_id_t task_id, struct epoll_event **events);
|
||||
|
||||
/** \brief Retrieves a message in the queue associated to task_id.
|
||||
If the queue is empty, the thread is blocked till a new message arrives.
|
||||
\param task_id Task ID of the receiving task
|
||||
\param received_msg Pointer to the allocated message
|
||||
**/
|
||||
void itti_receive_msg(task_id_t task_id, MessageDef **received_msg);
|
||||
|
||||
/** \brief Try to retrieves a message in the queue associated to task_id.
|
||||
\param task_id Task ID of the receiving task
|
||||
\param received_msg Pointer to the allocated message
|
||||
**/
|
||||
void itti_poll_msg(task_id_t task_id, MessageDef **received_msg);
|
||||
|
||||
/** \brief Start thread associated to the task
|
||||
\param task_id task to start
|
||||
\param start_routine entry point for the task
|
||||
\param args_p Optional argument to pass to the start routine
|
||||
@returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int itti_create_task(task_id_t task_id,
|
||||
void *(*start_routine) (void *),
|
||||
void *args_p);
|
||||
|
||||
/** \brief Exit the current task.
|
||||
**/
|
||||
void itti_exit_task(void);
|
||||
|
||||
/** \brief Initiate termination of all tasks.
|
||||
\param task_id task that is completed
|
||||
**/
|
||||
void itti_terminate_tasks(task_id_t task_id);
|
||||
|
||||
// Void for legacy compatibility
|
||||
void itti_wait_ready(int wait_tasks);
|
||||
void itti_mark_task_ready(task_id_t task_id);
|
||||
|
||||
/** \brief Return the printable string associated with the message
|
||||
\param message_id Id of the message
|
||||
**/
|
||||
const char *itti_get_message_name(MessagesIds message_id);
|
||||
|
||||
/** \brief Return the printable string associated with a task id
|
||||
\param thread_id Id of the task
|
||||
**/
|
||||
const char *itti_get_task_name(task_id_t task_id);
|
||||
|
||||
/** \brief Alloc and memset(0) a new itti message.
|
||||
\param origin_task_id Task ID of the sending task
|
||||
\param message_id Message ID
|
||||
@returns NULL in case of failure or newly allocated mesage ref
|
||||
**/
|
||||
MessageDef *itti_alloc_new_message(
|
||||
task_id_t origin_task_id,
|
||||
MessagesIds message_id);
|
||||
|
||||
/** \brief Alloc and memset(0) a new itti message.
|
||||
\param origin_task_id Task ID of the sending task
|
||||
\param message_id Message ID
|
||||
\param size size of the payload to send
|
||||
@returns NULL in case of failure or newly allocated mesage ref
|
||||
**/
|
||||
MessageDef *itti_alloc_new_message_sized(
|
||||
task_id_t origin_task_id,
|
||||
MessagesIds message_id,
|
||||
MessageHeaderSize size);
|
||||
|
||||
/** \brief handle signals and wait for all threads to join when the process complete.
|
||||
This function should be called from the main thread after having created all ITTI tasks.
|
||||
**/
|
||||
void itti_wait_tasks_end(void);
|
||||
#define THREAD_MAX 0 //for compatibility
|
||||
void itti_set_task_real_time(task_id_t task_id);
|
||||
|
||||
/** \brief Send a termination message to all tasks.
|
||||
\param task_id task that is broadcasting the message.
|
||||
**/
|
||||
void itti_send_terminate_message(task_id_t task_id);
|
||||
|
||||
void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size);
|
||||
void *calloc_or_fail(size_t size);
|
||||
void *malloc_or_fail(size_t size);
|
||||
int memory_read(const char *datafile, void *data, size_t size);
|
||||
int itti_free(task_id_t task_id, void *ptr);
|
||||
|
||||
int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
|
||||
const message_info_t *messages_info);
|
||||
int timer_setup(
|
||||
uint32_t interval_sec,
|
||||
uint32_t interval_us,
|
||||
task_id_t task_id,
|
||||
int32_t instance,
|
||||
timer_type_t type,
|
||||
void *timer_arg,
|
||||
long *timer_id);
|
||||
|
||||
|
||||
int timer_remove(long timer_id);
|
||||
#define timer_stop timer_remove
|
||||
int signal_handle(int *end);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* INTERTASK_INTERFACE_H_ */
|
||||
@@ -303,8 +303,6 @@ char sv1[64];
|
||||
}
|
||||
int proccmd_exit(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
extern void exit_fun(const char* s);
|
||||
|
||||
if (debug > 0)
|
||||
prnt("process module received %s\n",buf);
|
||||
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
/*!\brief Initilization and reconfiguration routines for LTE PHY */
|
||||
#include "phy_init.h"
|
||||
@@ -27,12 +27,11 @@
|
||||
#include "PHY/LTE_REFSIG/lte_refsig.h"
|
||||
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
|
||||
|
||||
void generate_64qam_table(void)
|
||||
{
|
||||
void init_sss(void);
|
||||
|
||||
void generate_64qam_table(void) {
|
||||
int a,b,c,index;
|
||||
|
||||
|
||||
for (a=-1; a<=1; a+=2)
|
||||
for (b=-1; b<=1; b+=2)
|
||||
for (c=-1; c<=1; c+=2) {
|
||||
@@ -41,9 +40,7 @@ void generate_64qam_table(void)
|
||||
}
|
||||
}
|
||||
|
||||
void generate_16qam_table(void)
|
||||
{
|
||||
|
||||
void generate_16qam_table(void) {
|
||||
int a,b,index;
|
||||
|
||||
for (a=-1; a<=1; a+=2)
|
||||
@@ -53,54 +50,42 @@ void generate_16qam_table(void)
|
||||
}
|
||||
}
|
||||
|
||||
void generate_qpsk_table(void)
|
||||
{
|
||||
|
||||
void generate_qpsk_table(void) {
|
||||
int a,index;
|
||||
|
||||
for (a=-1; a<=1; a+=2) {
|
||||
index = (1+a)/2;
|
||||
qpsk_table[index] = -a*QPSK;
|
||||
qpsk_table[index] = -a*QPSK;
|
||||
}
|
||||
}
|
||||
|
||||
void init_lte_top(LTE_DL_FRAME_PARMS *frame_parms)
|
||||
{
|
||||
|
||||
void init_7_5KHz(void);
|
||||
void init_lte_top(LTE_DL_FRAME_PARMS *frame_parms) {
|
||||
ccodelte_init();
|
||||
ccodelte_init_inv();
|
||||
|
||||
init_dfts();
|
||||
|
||||
|
||||
phy_generate_viterbi_tables_lte();
|
||||
|
||||
load_codinglib();
|
||||
lte_sync_time_init(frame_parms);
|
||||
|
||||
generate_ul_ref_sigs();
|
||||
generate_ul_ref_sigs_rx();
|
||||
|
||||
generate_64qam_table();
|
||||
generate_16qam_table();
|
||||
generate_qpsk_table();
|
||||
generate_RIV_tables();
|
||||
|
||||
init_unscrambling_lut();
|
||||
init_scrambling_lut();
|
||||
//set_taus_seed(1328);
|
||||
|
||||
|
||||
init_7_5KHz();
|
||||
init_sss();
|
||||
}
|
||||
|
||||
void free_lte_top(void)
|
||||
{
|
||||
void free_lte_top(void) {
|
||||
free_codinglib();
|
||||
lte_sync_time_free();
|
||||
|
||||
/* free_ul_ref_sigs() is called in phy_free_lte_eNB() */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @}*/
|
||||
@}*/
|
||||
|
||||
@@ -91,7 +91,7 @@ int32_t temp_in_ifft_0[2048*2] __attribute__((aligned(32)));
|
||||
eNB->ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS2 +
|
||||
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+Ns]) % 12;
|
||||
|
||||
Msc_idx_ptr = (uint16_t*) bsearch(&Msc_RS, dftsizes, 33, sizeof(uint16_t), compareints);
|
||||
Msc_idx_ptr = (uint16_t*) bsearch(&Msc_RS, dftsizes, 34, sizeof(uint16_t), compareints);
|
||||
|
||||
if (Msc_idx_ptr)
|
||||
Msc_RS_idx = Msc_idx_ptr - dftsizes;
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
#include "lte_refsig.h"
|
||||
#include "PHY/defs_eNB.h"
|
||||
|
||||
uint16_t dftsizes[33] = {12,24,36,48,60,72,96,108,120,144,180,192,216,240,288,300,324,360,384,432,480,540,576,600,648,720,864,900,960,972,1080,1152,1200};
|
||||
uint16_t dftsizes[34] = {12,24,36,48,60,72,96,108,120,144,180,192,216,240,288,300,324,360,384,432,480,540,576,600,648,720,768,864,900,960,972,1080,1152,1200};
|
||||
|
||||
uint16_t ref_primes[33] = {11,23,31,47,59,71,89,107,113,139,179,191,211,239,283,293,317,359,383,431,479,523,571,599,647,719,863,887,953,971,1069,1151,1193};
|
||||
uint16_t ref_primes[34] = {11,23,31,47,59,71,89,107,113,139,179,191,211,239,283,293,317,359,383,431,479,523,571,599,647,719,761,863,887,953,971,1069,1151,1193};
|
||||
|
||||
|
||||
int16_t *ul_ref_sigs[30][2][33];
|
||||
int16_t *ul_ref_sigs_rx[30][2][33]; //these contain the sequences in repeated format and quantized to QPSK ifdef IFFT_FPGA
|
||||
int16_t *ul_ref_sigs[30][2][34];
|
||||
int16_t *ul_ref_sigs_rx[30][2][34]; //these contain the sequences in repeated format and quantized to QPSK ifdef IFFT_FPGA
|
||||
|
||||
/* 36.211 table 5.5.1.2-1 */
|
||||
char ref12[360] = {-1,1,3,-3,3,3,1,1,3,1,-3,3,1,1,3,3,3,-1,1,-3,-3,1,-3,3,1,1,-3,-3,-3,-1,-3,-3,1,-3,1,-1,-1,1,1,1,1,-1,-3,-3,1,-3,3,-1,-1,3,1,-1,1,-1,-3,-1,1,-1,1,3,1,-3,3,-1,-1,1,1,-1,-1,3,-3,1,-1,3,-3,-3,-3,3,1,-1,3,3,-3,1,-3,-1,-1,-1,1,-3,3,-1,1,-3,3,1,1,-3,3,1,-1,-1,-1,1,1,3,-1,1,1,-3,-1,3,3,-1,-3,1,1,1,1,1,-1,3,-1,1,1,-3,-3,-1,-3,-3,3,-1,3,1,-1,-1,3,3,-3,1,3,1,3,3,1,-3,1,1,-3,1,1,1,-3,-3,-3,1,3,3,-3,3,-3,1,1,3,-1,-3,3,3,-3,1,-1,-3,-1,3,1,3,3,3,-1,1,3,-1,1,-3,-1,-1,1,1,3,1,-1,-3,1,3,1,-1,1,3,3,3,-1,-1,3,-1,-3,1,1,3,-3,3,-3,-3,3,1,3,-1,-3,3,1,1,-3,1,-3,-3,-1,-1,1,-3,-1,3,1,3,1,-1,-1,3,-3,-1,-3,-1,-1,-3,1,1,1,1,3,1,-1,1,-3,-1,-1,3,-1,1,-3,-3,-3,-3,-3,1,-1,-3,1,1,-3,-3,-3,-3,-1,3,-3,1,-3,3,1,1,-1,-3,-1,-3,1,-1,1,3,-1,1,1,1,3,1,3,3,-1,1,-1,-3,-3,1,1,-3,3,3,1,3,3,1,-3,-1,-1,3,1,3,-3,-3,3,-3,1,-1,-1,3,-1,-3,-3,-1,-3,-1,-3,3,1,-1,1,3,-3,-3,-1,3,-3,3,-1,3,3,-3,3,3,-1,-1,3,-3,-3,-1,-1,-3,-1,3,-3,3,1,-1};
|
||||
@@ -49,7 +49,7 @@ void generate_ul_ref_sigs(void)
|
||||
unsigned int u,v,Msc_RS,q,m,n;
|
||||
|
||||
// These are the Zadoff-Chu sequences (for RB 3-100)
|
||||
for (Msc_RS=2; Msc_RS<33; Msc_RS++) {
|
||||
for (Msc_RS=2; Msc_RS<34; Msc_RS++) {
|
||||
for (u=0; u<30; u++) {
|
||||
for (v=0; v<2; v++) {
|
||||
qbar = ref_primes[Msc_RS] * (u+1)/(double)31;
|
||||
@@ -119,7 +119,7 @@ void generate_ul_ref_sigs_rx(void)
|
||||
unsigned int u,v,Msc_RS,q,m,n;
|
||||
|
||||
// These are the complex conjugated Zadoff-Chu sequences quantized to QPSK stored in repeated format (for RB 3-100)
|
||||
for (Msc_RS=2; Msc_RS<33; Msc_RS++) {
|
||||
for (Msc_RS=2; Msc_RS<34; Msc_RS++) {
|
||||
for (u=0; u<30; u++) {
|
||||
for (v=0; v<2; v++) {
|
||||
qbar = ref_primes[Msc_RS] * (u+1)/(double)31;
|
||||
@@ -186,7 +186,7 @@ void free_ul_ref_sigs(void)
|
||||
|
||||
unsigned int u,v,Msc_RS;
|
||||
|
||||
for (Msc_RS=0; Msc_RS<33; Msc_RS++) {
|
||||
for (Msc_RS=0; Msc_RS<34; Msc_RS++) {
|
||||
for (u=0; u<30; u++) {
|
||||
for (v=0; v<2; v++) {
|
||||
if (ul_ref_sigs[u][v][Msc_RS]) {
|
||||
|
||||
@@ -357,28 +357,36 @@ void conv_rballoc(uint8_t ra_header,uint32_t rb_alloc,uint32_t N_RB_DL,uint32_t
|
||||
break;
|
||||
|
||||
case 50:
|
||||
AssertFatal(ra_header==0,"resource type 1 not supported for N_RB_DL=50\n");
|
||||
if (ra_header==0) {
|
||||
|
||||
for (i=16; i>0; i--) {
|
||||
if ((rb_alloc&(1<<i)) != 0)
|
||||
rb_alloc2[(3*(16-i))>>5] |= (7<<((3*(16-i))%32));
|
||||
for (i=16; i>0; i--) {
|
||||
if ((rb_alloc&(1<<i)) != 0)
|
||||
rb_alloc2[(3*(16-i))>>5] |= (7<<((3*(16-i))%32));
|
||||
}
|
||||
|
||||
// bit mask across
|
||||
if ((rb_alloc2[0]>>31)==1)
|
||||
rb_alloc2[1] |= 1;
|
||||
|
||||
if ((rb_alloc&1) != 0)
|
||||
rb_alloc2[1] |= (3<<16);
|
||||
}
|
||||
else {
|
||||
LOG_W(PHY,"resource type 1 not supported for N_RB_DL=50\n");
|
||||
}
|
||||
|
||||
// bit mask across
|
||||
if ((rb_alloc2[0]>>31)==1)
|
||||
rb_alloc2[1] |= 1;
|
||||
|
||||
if ((rb_alloc&1) != 0)
|
||||
rb_alloc2[1] |= (3<<16);
|
||||
break;
|
||||
|
||||
case 100:
|
||||
AssertFatal(ra_header==0,"resource type 1 not supported for N_RB_DL=100\n");
|
||||
for (i=0; i<25; i++) {
|
||||
if ((rb_alloc&(1<<(24-i))) != 0)
|
||||
rb_alloc2[(4*i)>>5] |= (0xf<<((4*i)%32));
|
||||
|
||||
// printf("rb_alloc2[%d] (type 0) %x (%d)\n",(4*i)>>5,rb_alloc2[(4*i)>>5],rb_alloc&(1<<i));
|
||||
if (ra_header==0) {
|
||||
for (i=0; i<25; i++) {
|
||||
if ((rb_alloc&(1<<(24-i))) != 0)
|
||||
rb_alloc2[(4*i)>>5] |= (0xf<<((4*i)%32));
|
||||
|
||||
// printf("rb_alloc2[%d] (type 0) %x (%d)\n",(4*i)>>5,rb_alloc2[(4*i)>>5],rb_alloc&(1<<i));
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG_W(PHY,"resource type 1 not supported for N_RB_DL=100\n");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -33,10 +33,10 @@
|
||||
#include "PHY/defs_eNB.h"
|
||||
#include "PHY/TOOLS/alaw_lut.h"
|
||||
|
||||
#include "time_utils.h"
|
||||
|
||||
//#include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
|
||||
#include "targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
|
||||
#include <intertask_interface.h>
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
//#define DEBUG_DL_MOBIPASS
|
||||
//#define DEBUG_UL_MOBIPASS
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,68 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
int16_t *d0_sss;
|
||||
int16_t *d5_sss;
|
||||
|
||||
#define MyAssert(x) { if(!(x)) { printf("Error in table intialization: %s:%d\n",__FILE__,__LINE__); exit(1);}}
|
||||
#define gen(table, formula) { \
|
||||
int x[31]= {0}; \
|
||||
x[4]=1; \
|
||||
for(int i=0; i<26; i++) \
|
||||
x[i+5]=formula; \
|
||||
for (int i=0; i<31; i++) \
|
||||
table[i]=1-2*x[i]; \
|
||||
}
|
||||
|
||||
#define mod31(a) (a)%31
|
||||
#define mod2(a) (a)%2
|
||||
#define mod8(a) (a)%8
|
||||
void init_sss(void) {
|
||||
MyAssert(0==posix_memalign((void **)&d0_sss, 16,504*31*2*sizeof(*d0_sss)));
|
||||
MyAssert(0==posix_memalign((void **)&d5_sss, 16,504*31*2*sizeof(*d5_sss)));
|
||||
int s[31];
|
||||
gen(s, mod2(x[i+2]+x[i]));
|
||||
int z[31];
|
||||
gen(z, mod2(x[i+4]+x[i+2]+x[i+1]+x[i]));
|
||||
int c[31];
|
||||
gen(c, mod2(x[i+3]+x[i]));
|
||||
|
||||
for (int Nid2=0; Nid2<3; Nid2++) {
|
||||
for (int Nid1=0; Nid1<168; Nid1++) {
|
||||
int qprime = Nid1/30;
|
||||
int q = (Nid1+(qprime*(qprime+1))/2)/30;
|
||||
int mprime = Nid1 + q*(q+1)/2;
|
||||
int m0 = mprime%31;
|
||||
int m1 = (m0+mprime/31+1)%31;
|
||||
int rowIndex=(Nid2+3*Nid1)*31*2;
|
||||
|
||||
for (int i=0; i<31; i++) {
|
||||
d0_sss[rowIndex+i*2]= s[mod31(i+m0)] * c[mod31(i+Nid2)];
|
||||
d5_sss[rowIndex+i*2]= s[mod31(i+m1)] * c[mod31(i+Nid2)];
|
||||
d0_sss[rowIndex+i*2+1]= s[mod31(i+m1)] * c[mod31(i+Nid2+3)] * z[mod31(i+mod8(m0))];
|
||||
d5_sss[rowIndex+i*2+1]= s[mod31(i+m0)] * c[mod31(i+Nid2+3)] * z[mod31(i+mod8(m1))];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SSS_TABLES_TEST
|
||||
void main () {
|
||||
printf("int16_t d0_sss[504*62] = {");
|
||||
|
||||
for (int i=0; i<504*62; i++)
|
||||
printf("%d,\n",d0_sss[i]);
|
||||
|
||||
printf("};\n\n");
|
||||
printf("int16_t d5_sss[504*62] = {");
|
||||
|
||||
for (int i=0; i<504*62; i++)
|
||||
printf("%d,\n",d5_sss[i]);
|
||||
|
||||
printf("};\n\n");
|
||||
}
|
||||
#endif
|
||||
@@ -1,53 +0,0 @@
|
||||
% generate s
|
||||
x = zeros(1,30);
|
||||
x(1:5) = [0 0 0 0 1];
|
||||
for i=1:26
|
||||
x(i+5) = rem(x(i+2) + x(i),2);
|
||||
end
|
||||
s = 1 - 2*x;
|
||||
|
||||
% generate z
|
||||
x = zeros(1,30);
|
||||
x(1:5) = [0 0 0 0 1];
|
||||
for i=1:26
|
||||
x(i+5) = rem(x(i+4)+ x(i+2) + x(i+1) + x(i),2);
|
||||
end
|
||||
z = 1 - 2*x;
|
||||
% generate c
|
||||
x = zeros(1,30);
|
||||
x(1:5) = [0 0 0 0 1];
|
||||
for i=1:26
|
||||
x(i+5) = rem(x(i+3) + x(i),2);
|
||||
end
|
||||
c = 1 - 2*x;
|
||||
d0 = zeros(504,62);
|
||||
d5 = zeros(504,62);
|
||||
for Nid2=0:2,
|
||||
c0 = [c((1+Nid2) : end) c(1:Nid2)];
|
||||
c1 = [c((4+Nid2) : end) c(1:(3+Nid2))];
|
||||
for Nid1=0:167,
|
||||
qprime = floor(Nid1/30);
|
||||
q = floor((Nid1+qprime*(qprime+1)/2)/30);
|
||||
mprime = Nid1 + q*(q+1)/2;
|
||||
m0 = rem(mprime,31);
|
||||
m1 = rem(m0+floor(mprime/31)+1,31);
|
||||
sm0 = [s((1+m0) : end) s(1:m0)];
|
||||
sm1 = [s((1+m1) : end) s(1:m1)];
|
||||
m0mod8 = rem(m0,8);
|
||||
m1mod8 = rem(m1,8);
|
||||
zm0 = [z((1+m0mod8) : end) z(1:m0mod8)];
|
||||
zm1 = [z((1+m1mod8) : end) z(1:m1mod8)];
|
||||
d0(1+Nid2+(3*Nid1),1:2:62) = sm0.*c0;
|
||||
d5(1+Nid2+(3*Nid1),1:2:62) = sm1.*c0;
|
||||
d0(1+Nid2+(3*Nid1),2:2:62) = sm1.*c1.*zm0;
|
||||
d5(1+Nid2+(3*Nid1),2:2:62) = sm0.*c1.*zm1;
|
||||
end
|
||||
end
|
||||
fd = fopen("sss.h","w");
|
||||
fprintf(fd,"s16 d0_sss[504*62] = {");
|
||||
fprintf(fd,"%d,",d0);
|
||||
fprintf(fd,"};\n\n");
|
||||
fprintf(fd,"s16 d5_sss[504*62] = {");
|
||||
fprintf(fd,"%d,",d5);
|
||||
fprintf(fd,"};\n\n");
|
||||
fclose(fd);
|
||||
@@ -25,10 +25,10 @@ extern char lte_cqi_snr_dB[15];
|
||||
extern short conjugate[8],conjugate2[8];
|
||||
extern short minus_one[8];
|
||||
extern short minus_one[8];
|
||||
extern short *ul_ref_sigs[30][2][33];
|
||||
extern short *ul_ref_sigs_rx[30][2][33];
|
||||
extern unsigned short dftsizes[33];
|
||||
extern unsigned short ref_primes[33];
|
||||
extern short *ul_ref_sigs[30][2][34];
|
||||
extern short *ul_ref_sigs_rx[30][2][34];
|
||||
extern unsigned short dftsizes[34];
|
||||
extern unsigned short ref_primes[34];
|
||||
|
||||
extern int qam64_table[8],qam16_table[4],qpsk_table[2];
|
||||
|
||||
@@ -44,7 +44,7 @@ extern unsigned short scfdma_amps[26];
|
||||
|
||||
extern char dci_format_strings[15][13];
|
||||
|
||||
extern int16_t d0_sss[504*62],d5_sss[504*62];
|
||||
extern int16_t *d0_sss,*d5_sss;
|
||||
|
||||
extern uint8_t wACK[5][4];
|
||||
extern int8_t wACK_RX[5][4];
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include "dlsch_tbs.h"
|
||||
//#include "dlsch_tbs_full.h"
|
||||
#include "sss.h"
|
||||
|
||||
unsigned short lte_cqi_eff1024[16] = {156, //-6, .15234
|
||||
240, //-4 .234
|
||||
|
||||
@@ -335,6 +335,12 @@ void lte_idft(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *z, uint16_t Msc_PUSCH)
|
||||
dft720((int16_t*)idft_in2,(int16_t*)idft_out2,1);
|
||||
break;
|
||||
|
||||
case 768:
|
||||
dft768((int16_t*)idft_in0,(int16_t*)idft_out0,1);
|
||||
dft768((int16_t*)idft_in1,(int16_t*)idft_out1,1);
|
||||
dft768((int16_t*)idft_in2,(int16_t*)idft_out2,1);
|
||||
break;
|
||||
|
||||
case 864:
|
||||
dft864((int16_t*)idft_in0,(int16_t*)idft_out0,1);
|
||||
dft864((int16_t*)idft_in1,(int16_t*)idft_out1,1);
|
||||
|
||||
@@ -83,7 +83,7 @@ int generate_drs_pusch(PHY_VARS_UE *ue,
|
||||
// cyclic_shift1 = 0;
|
||||
Msc_RS = 12*nb_rb;
|
||||
|
||||
Msc_idx_ptr = (uint16_t*) bsearch(&Msc_RS, dftsizes, 33, sizeof(uint16_t), compareints);
|
||||
Msc_idx_ptr = (uint16_t*) bsearch(&Msc_RS, dftsizes, 34, sizeof(uint16_t), compareints);
|
||||
|
||||
if (Msc_idx_ptr)
|
||||
Msc_RS_idx = Msc_idx_ptr - dftsizes;
|
||||
|
||||
@@ -181,7 +181,7 @@ int32_t generate_srs(LTE_DL_FRAME_PARMS *frame_parms,
|
||||
return(-1);
|
||||
}
|
||||
|
||||
Msc_idx_ptr = (uint16_t*) bsearch((uint16_t*) &Msc_RS, (uint16_t*) dftsizes, 33, sizeof(uint16_t), compareints);
|
||||
Msc_idx_ptr = (uint16_t*) bsearch((uint16_t*) &Msc_RS, (uint16_t*) dftsizes, 34, sizeof(uint16_t), compareints);
|
||||
|
||||
if (Msc_idx_ptr)
|
||||
Msc_RS_idx = Msc_idx_ptr - dftsizes;
|
||||
|
||||
@@ -287,6 +287,12 @@ void dft_lte(int32_t *z,int32_t *d, int32_t Msc_PUSCH, uint8_t Nsymb)
|
||||
dft720((int16_t*)dft_in2,(int16_t*)dft_out2,1);
|
||||
break;
|
||||
|
||||
case 768:
|
||||
dft768((int16_t*)dft_in0,(int16_t*)dft_out0,1);
|
||||
dft768((int16_t*)dft_in1,(int16_t*)dft_out1,1);
|
||||
dft768((int16_t*)dft_in2,(int16_t*)dft_out2,1);
|
||||
break;
|
||||
|
||||
case 864:
|
||||
dft864((int16_t*)dft_in0,(int16_t*)dft_out0,1);
|
||||
dft864((int16_t*)dft_in1,(int16_t*)dft_out1,1);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <assert.h>
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <PHY/MODULATION/modulation_extern.h>
|
||||
using namespace std;
|
||||
extern "C" {
|
||||
void gen_sig(int RB, int len, double ratio, int16_t *table_n, int16_t *table_e ) {
|
||||
double samplerate = 30.72e6*ratio;
|
||||
double ofdm_size = 2048*ratio;
|
||||
double PI = std::acos(-1);
|
||||
std::complex<int> tt;
|
||||
complex<double> t[len];
|
||||
int index=0;
|
||||
double cp0 = 160*ratio;
|
||||
double cp = 144*ratio;
|
||||
|
||||
for (int i=-cp0; i<ofdm_size; i++)
|
||||
t[index++] = polar( 32767.0, -2*PI*i*7.5e3/samplerate);
|
||||
|
||||
for(int x=0 ; x <6 ; x++)
|
||||
for (int i=-cp; i<ofdm_size; i++)
|
||||
t[index++] = polar( 32767.0, -2*PI*i*7.5e3/samplerate);
|
||||
|
||||
for (int i=0; i < len ; i++) {
|
||||
table_n[i*2] = floor(real(t[i]));
|
||||
table_n[i*2+1] = floor(imag(t[i]));
|
||||
}
|
||||
|
||||
index=0;
|
||||
double cpe = 512*ratio;
|
||||
|
||||
for(int x=0 ; x <6 ; x++)
|
||||
for (int i=-cpe; i<ofdm_size; i++)
|
||||
t[index++] = polar( 32767.0, -2*PI*i*7.5e3/samplerate);
|
||||
|
||||
for (int i=0; i < len ; i++) {
|
||||
table_e[i*2] = floor(real(t[i]));
|
||||
table_e[i*2+1] = floor(imag(t[i]));
|
||||
}
|
||||
}
|
||||
|
||||
int16_t *s6n_kHz_7_5;
|
||||
int16_t *s6e_kHz_7_5;
|
||||
int16_t *s15n_kHz_7_5;
|
||||
int16_t *s15e_kHz_7_5;
|
||||
int16_t *s25n_kHz_7_5;
|
||||
int16_t *s25e_kHz_7_5;
|
||||
int16_t *s50n_kHz_7_5;
|
||||
int16_t *s50e_kHz_7_5;
|
||||
int16_t *s75n_kHz_7_5;
|
||||
int16_t *s75e_kHz_7_5;
|
||||
int16_t *s100n_kHz_7_5;
|
||||
int16_t *s100e_kHz_7_5;
|
||||
int16_t **tables[12]= {&s6n_kHz_7_5,&s6e_kHz_7_5,
|
||||
&s15n_kHz_7_5,&s15e_kHz_7_5,
|
||||
&s25n_kHz_7_5,&s25e_kHz_7_5,
|
||||
&s50n_kHz_7_5,&s50e_kHz_7_5,
|
||||
&s75n_kHz_7_5,&s75e_kHz_7_5,
|
||||
&s100n_kHz_7_5,&s100e_kHz_7_5,
|
||||
};
|
||||
int tables_size_bytes[12];
|
||||
#define MyAssert(x) { if(!(x)) { printf("Error in table intialization: %s:%d\n",__FILE__,__LINE__); exit(1);}}
|
||||
void init_7_5KHz(void) {
|
||||
const map<int,double> tables_7_5KHz= {{6,1.0/16},{15,1.0/8},{25,1.0/4},{50,1.0/2},{75,3.0/4},{100,1.0}};
|
||||
int tables_idx=0;
|
||||
|
||||
for (auto it=tables_7_5KHz.begin(); it!=tables_7_5KHz.end(); ++it) {
|
||||
int len=15360*it->second;
|
||||
tables_size_bytes[tables_idx]=sizeof(int16_t)*2*len;
|
||||
tables_size_bytes[tables_idx+1]=sizeof(int16_t)*2*len;
|
||||
MyAssert(0==posix_memalign((void **)tables[tables_idx],
|
||||
16,tables_size_bytes[tables_idx]));
|
||||
MyAssert(0==posix_memalign((void **)tables[tables_idx+1],
|
||||
16,tables_size_bytes[tables_idx+1]));
|
||||
gen_sig(it->first, len, it->second, *tables[tables_idx], *tables[tables_idx+1]);
|
||||
tables_idx+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
|
||||
function [] = gen_7_5_kHz()
|
||||
[s6_n2, s6_e2] = gen_sig(6);
|
||||
[s15_n2, s15_e2] = gen_sig(15);
|
||||
[s25_n2, s25_e2] = gen_sig(25);
|
||||
[s50_n2, s50_e2] = gen_sig(50);
|
||||
[s75_n2, s75_e2] = gen_sig(75);
|
||||
[s100_n2, s100_e2] = gen_sig(100);
|
||||
|
||||
|
||||
fd=fopen("kHz_7_5.h","w");
|
||||
fprintf(fd,"s16 s6n_kHz_7_5[%d]__attribute__((aligned(16))) = {",length(s6_n2));
|
||||
fprintf(fd,"%d,",s6_n2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s6_n2(end));
|
||||
|
||||
fprintf(fd,"s16 s6e_kHz_7_5[%d]__attribute__((aligned(16))) = {",length(s6_e2));
|
||||
fprintf(fd,"%d,",s6_e2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s6_e2(end));
|
||||
|
||||
fprintf(fd,"s16 s15n_kHz_7_5[%d]__attribute__((aligned(16))) = {",length(s15_n2));
|
||||
fprintf(fd,"%d,",s15_n2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s15_n2(end));
|
||||
|
||||
fprintf(fd,"s16 s15e_kHz_7_5[%d]__attribute__((aligned(16))) = {",length(s15_e2));
|
||||
fprintf(fd,"%d,",s15_e2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s15_e2(end));
|
||||
|
||||
fprintf(fd,"s16 s25n_kHz_7_5[%d]__attribute__((aligned(16))) = {",length(s25_n2));
|
||||
fprintf(fd,"%d,",s25_n2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s25_n2(end));
|
||||
|
||||
fprintf(fd,"s16 s25e_kHz_7_5[%d]__attribute__((aligned(16))) = {",length(s25_e2));
|
||||
fprintf(fd,"%d,",s25_e2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s25_e2(end));
|
||||
|
||||
fprintf(fd,"s16 s50n_kHz_7_5[%d]__attribute__((aligned(16))) = {",length(s50_n2));
|
||||
fprintf(fd,"%d,",s50_n2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s50_n2(end));
|
||||
|
||||
fprintf(fd,"s16 s50e_kHz_7_5[%d]__attribute__((aligned(16))) = {",length(s50_e2));
|
||||
fprintf(fd,"%d,",s50_e2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s50_e2(end));
|
||||
|
||||
fprintf(fd,"s16 s75n_kHz_7_5[%d]__attribute__((aligned(16))) = {",length(s75_n2));
|
||||
fprintf(fd,"%d,",s75_n2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s75_n2(end));
|
||||
|
||||
fprintf(fd,"s16 s75e_kHz_7_5[%d]__attribute__((aligned(16))) = {",length(s75_e2));
|
||||
fprintf(fd,"%d,",s75_e2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s75_e2(end));
|
||||
|
||||
fprintf(fd,"s16 s100n_kHz_7_5[%d]__attribute__((aligned(16)))= {",length(s100_n2));
|
||||
fprintf(fd,"%d,",s100_n2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s100_n2(end));
|
||||
|
||||
fprintf(fd,"s16 s100e_kHz_7_5[%d]__attribute__((aligned(16)))= {",length(s100_n2));
|
||||
fprintf(fd,"%d,",s100_e2(1:(end-1)));
|
||||
fprintf(fd,"%d};\n\n",s100_e2(end));
|
||||
|
||||
fclose(fd);
|
||||
end
|
||||
|
||||
|
||||
function [s_n2, s_e2] = gen_sig(RB)
|
||||
% 20MHz BW
|
||||
cp0 = 160;
|
||||
cp = 144;
|
||||
cpe = 512;
|
||||
samplerate = 30.72e6;
|
||||
ofdm_size = 2048;
|
||||
len = 15360;
|
||||
switch(RB)
|
||||
case 6
|
||||
ratio = 1/16;
|
||||
case 15
|
||||
ratio = 1/8;
|
||||
case 25
|
||||
ratio = 1/4;
|
||||
case 50
|
||||
ratio = 1/2;
|
||||
case 75
|
||||
ratio = 3/4;
|
||||
case 100
|
||||
ratio = 1;
|
||||
otherwise
|
||||
disp("Wrong Number of RB");
|
||||
end
|
||||
cp0 = cp0*ratio;
|
||||
cp = cp*ratio;
|
||||
cpe = cpe*ratio;
|
||||
samplerate = samplerate*ratio;
|
||||
ofdm_size = ofdm_size*ratio;
|
||||
len = len*ratio;
|
||||
|
||||
s_n0 = floor(32767*exp(-sqrt(-1)*2*pi*(-cp0:ofdm_size-1)*7.5e3/samplerate));
|
||||
s_n1 = floor(32767*exp(-sqrt(-1)*2*pi*(-cp:ofdm_size-1)*7.5e3/samplerate));
|
||||
s_n = [s_n0 s_n1 s_n1 s_n1 s_n1 s_n1 s_n1];
|
||||
s_n2 = zeros(1, 2*len);
|
||||
s_n2(1:2:end) = real(s_n);
|
||||
s_n2(2:2:end) = imag(s_n);
|
||||
s_e = floor(32767*exp(-sqrt(-1)*2*pi*(-cpe:ofdm_size-1)*7.5e3/samplerate));
|
||||
s_e = [s_e s_e s_e s_e s_e s_e];
|
||||
s_e2 = zeros(1, 2*len);
|
||||
s_e2(1:2:end) = real(s_e);
|
||||
s_e2(2:2:end) = imag(s_e);
|
||||
end
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,38 +1,44 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
|
||||
extern int16_t s6n_kHz_7_5[1920];
|
||||
extern int16_t s6e_kHz_7_5[1920];
|
||||
extern int16_t s15n_kHz_7_5[3840];
|
||||
extern int16_t s15e_kHz_7_5[3840];
|
||||
extern int16_t s25n_kHz_7_5[7680];
|
||||
extern int16_t s25e_kHz_7_5[7680];
|
||||
extern int16_t s50n_kHz_7_5[15360];
|
||||
extern int16_t s50e_kHz_7_5[15360];
|
||||
extern int16_t s75n_kHz_7_5[23040];
|
||||
extern int16_t s75e_kHz_7_5[23040];
|
||||
extern int16_t s100n_kHz_7_5[30720];
|
||||
extern int16_t s100e_kHz_7_5[30720];
|
||||
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
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int16_t *s6n_kHz_7_5;
|
||||
extern int16_t *s6e_kHz_7_5;
|
||||
extern int16_t *s15n_kHz_7_5;
|
||||
extern int16_t *s15e_kHz_7_5;
|
||||
extern int16_t *s25n_kHz_7_5;
|
||||
extern int16_t *s25e_kHz_7_5;
|
||||
extern int16_t *s50n_kHz_7_5;
|
||||
extern int16_t *s50e_kHz_7_5;
|
||||
extern int16_t *s75n_kHz_7_5;
|
||||
extern int16_t *s75e_kHz_7_5;
|
||||
extern int16_t *s100n_kHz_7_5;
|
||||
extern int16_t *s100e_kHz_7_5;
|
||||
|
||||
|
||||
extern short conjugate75[8];
|
||||
extern short conjugate75_2[8];
|
||||
extern short negate[8];
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "kHz_7_5.h"
|
||||
|
||||
short conjugate75[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1} ;
|
||||
short conjugate75_2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1} ;
|
||||
|
||||
@@ -3099,7 +3099,7 @@ void dft128(int16_t *x,int16_t *y,int scale)
|
||||
dft64((int16_t*)(xtmp+32),(int16_t*)(ytmp+16),1);
|
||||
if (LOG_DUMPFLAG(DEBUG_DFT)) {
|
||||
LOG_M("dft128a.m","dfta",ytmp,64,1,1);
|
||||
LOG_M("dft128b.m","dftb",ytmp+16,64,1,1);*/
|
||||
LOG_M("dft128b.m","dftb",ytmp+16,64,1,1);
|
||||
}
|
||||
for (i=0; i<16; i++) {
|
||||
bfly2_16(ytmpp,ytmpp+16,
|
||||
|
||||
@@ -375,6 +375,7 @@ void dft576(int16_t *x,int16_t *y,uint8_t scale_flag);
|
||||
void dft600(int16_t *x,int16_t *y,uint8_t scale_flag);
|
||||
void dft648(int16_t *x,int16_t *y,uint8_t scale_flag);
|
||||
void dft720(int16_t *x,int16_t *y,uint8_t scale_flag);
|
||||
void dft768(int16_t *x,int16_t *y,uint8_t scale_flag);
|
||||
void dft864(int16_t *x,int16_t *y,uint8_t scale_flag);
|
||||
void dft900(int16_t *x,int16_t *y,uint8_t scale_flag);
|
||||
void dft960(int16_t *x,int16_t *y,uint8_t scale_flag);
|
||||
|
||||
+18
-12
@@ -33,7 +33,9 @@
|
||||
#define __PHY_DEFS_COMMON_H__
|
||||
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -928,7 +930,6 @@ typedef enum {
|
||||
#endif
|
||||
|
||||
|
||||
void exit_fun(const char* s);
|
||||
|
||||
#include "common/utils/LOG/log_extern.h"
|
||||
extern pthread_cond_t sync_cond;
|
||||
@@ -994,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);
|
||||
}
|
||||
@@ -1013,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);
|
||||
}
|
||||
@@ -1034,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);
|
||||
}
|
||||
@@ -1056,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);
|
||||
}
|
||||
|
||||
@@ -1342,16 +1342,21 @@ void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
//compute the expected ULSCH RX power (for the stats)
|
||||
ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered
|
||||
|
||||
if (ulsch_harq->cqi_crc_status == 1) {
|
||||
if (RC.mac != NULL) { /* ulsim dose not use RC.mac context. */
|
||||
if (ulsch_harq->cqi_crc_status == 1) {
|
||||
#ifdef DEBUG_PHY_PROC
|
||||
//if (((frame%10) == 0) || (frame < 50))
|
||||
print_CQI(ulsch_harq->o,ulsch_harq->uci_format,0,fp->N_RB_DL);
|
||||
#endif
|
||||
|
||||
fill_ulsch_cqi_indication(eNB,frame,subframe,
|
||||
ulsch_harq,
|
||||
ulsch->rnti);
|
||||
|
||||
fill_ulsch_cqi_indication(eNB,frame,subframe,ulsch_harq,ulsch->rnti);
|
||||
RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe));
|
||||
} else {
|
||||
if(RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag & (1 << subframe) ){
|
||||
RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe));
|
||||
RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_timer=30;
|
||||
LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",frame,subframe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == (1+MAX_TURBO_ITERATIONS)) {
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "SCHED/defs.h"
|
||||
#include "SCHED/vars.h"
|
||||
#include "LAYER2/MAC/vars.h"
|
||||
#include "intertask_interface_init.h"
|
||||
|
||||
#include "OCG_vars.h"
|
||||
#include "UTIL/LOG/log_extern.h"
|
||||
|
||||
@@ -22,10 +22,14 @@
|
||||
openair0_device openair0;
|
||||
volatile int oai_exit=0;
|
||||
|
||||
void exit_fun(const char *s) { exit(-1); }
|
||||
void exit_function(const char* file, const char* function, const int line,const char *s) {
|
||||
const char * msg= s==NULL ? "no comment": s;
|
||||
printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
extern unsigned int dlsch_tbs25[27][25],TBStable[27][110];
|
||||
extern unsigned char offset_mumimo_llr_drange_fix;
|
||||
|
||||
extern unsigned short dftsizes[33];
|
||||
extern short *ul_ref_sigs[30][2][33];
|
||||
extern unsigned short dftsizes[34];
|
||||
extern short *ul_ref_sigs[30][2][34];
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef SIGNALS_H_
|
||||
#define SIGNALS_H_
|
||||
/*
|
||||
* flexran_messages_def.h
|
||||
*
|
||||
* Created on: Apr 26, 2018
|
||||
* Author: R. Schmidt
|
||||
*/
|
||||
|
||||
int signal_mask(void);
|
||||
|
||||
int signal_handle(int *end);
|
||||
|
||||
#endif /* SIGNALS_H_ */
|
||||
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"
|
||||
|
||||
@@ -34,9 +34,6 @@
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
#include "itti_types.h"
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// GENERIC TYPES
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -110,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
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -288,4 +291,7 @@ typedef struct protocol_ctxt_s {
|
||||
(CTXT_Pp)->rnti
|
||||
|
||||
#define CHECK_CTXT_ARGS(CTXT_Pp)
|
||||
|
||||
#define exit_fun(msg) exit_function(__FILE__,__FUNCTION__,__LINE__,msg)
|
||||
void exit_function(const char* file, const char* function, const int line, const char* s);
|
||||
#endif
|
||||
|
||||
@@ -19,11 +19,14 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_REQ , MESSAGE_PRIORITY_MED, sctp_new_association_req_t , sctp_new_association_req)
|
||||
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_RESP, MESSAGE_PRIORITY_MED, sctp_new_association_resp_t , sctp_new_association_resp)
|
||||
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_IND , MESSAGE_PRIORITY_MED, sctp_new_association_ind_t , sctp_new_association_ind)
|
||||
MESSAGE_DEF(SCTP_REGISTER_UPPER_LAYER, MESSAGE_PRIORITY_MED, sctp_listener_register_upper_layer_t, sctp_listener_register_upper_layer)
|
||||
MESSAGE_DEF(SCTP_DATA_REQ, MESSAGE_PRIORITY_MED, sctp_data_req_t , sctp_data_req)
|
||||
MESSAGE_DEF(SCTP_DATA_IND, MESSAGE_PRIORITY_MED, sctp_data_ind_t , sctp_data_ind)
|
||||
MESSAGE_DEF(SCTP_INIT_MSG, MESSAGE_PRIORITY_MED, sctp_init_t , sctp_init)
|
||||
MESSAGE_DEF(SCTP_CLOSE_ASSOCIATION, MESSAGE_PRIORITY_MAX, sctp_close_association_t , sctp_close_association)
|
||||
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_REQ , MESSAGE_PRIORITY_MED, sctp_new_association_req_t , sctp_new_association_req)
|
||||
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_REQ_MULTI, MESSAGE_PRIORITY_MED, sctp_new_association_req_multi_t , sctp_new_association_req_multi)
|
||||
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_RESP, MESSAGE_PRIORITY_MED, sctp_new_association_resp_t , sctp_new_association_resp)
|
||||
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_IND , MESSAGE_PRIORITY_MED, sctp_new_association_ind_t , sctp_new_association_ind)
|
||||
MESSAGE_DEF(SCTP_REGISTER_UPPER_LAYER, MESSAGE_PRIORITY_MED, sctp_listener_register_upper_layer_t , sctp_listener_register_upper_layer)
|
||||
MESSAGE_DEF(SCTP_DATA_REQ, MESSAGE_PRIORITY_MED, sctp_data_req_t , sctp_data_req)
|
||||
MESSAGE_DEF(SCTP_DATA_IND, MESSAGE_PRIORITY_MED, sctp_data_ind_t , sctp_data_ind)
|
||||
MESSAGE_DEF(SCTP_INIT_MSG, MESSAGE_PRIORITY_MED, sctp_init_t , sctp_init)
|
||||
MESSAGE_DEF(SCTP_INIT_MSG_MULTI_REQ, MESSAGE_PRIORITY_MED, sctp_init_t , sctp_init_multi)
|
||||
MESSAGE_DEF(SCTP_INIT_MSG_MULTI_CNF, MESSAGE_PRIORITY_MED, sctp_init_msg_multi_cnf_t , sctp_init_msg_multi_cnf)
|
||||
MESSAGE_DEF(SCTP_CLOSE_ASSOCIATION, MESSAGE_PRIORITY_MAX, sctp_close_association_t , sctp_close_association)
|
||||
|
||||
@@ -22,13 +22,16 @@
|
||||
#ifndef SCTP_MESSAGES_TYPES_H_
|
||||
#define SCTP_MESSAGES_TYPES_H_
|
||||
|
||||
#define SCTP_NEW_ASSOCIATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_req
|
||||
#define SCTP_NEW_ASSOCIATION_RESP(mSGpTR)(mSGpTR)->ittiMsg.sctp_new_association_resp
|
||||
#define SCTP_NEW_ASSOCIATION_IND(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_ind
|
||||
#define SCTP_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.sctp_data_ind
|
||||
#define SCTP_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_data_req
|
||||
#define SCTP_INIT_MSG(mSGpTR) (mSGpTR)->ittiMsg.sctp_init
|
||||
#define SCTP_CLOSE_ASSOCIATION(mSGpTR) (mSGpTR)->ittiMsg.sctp_close_association
|
||||
#define SCTP_NEW_ASSOCIATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_req
|
||||
#define SCTP_NEW_ASSOCIATION_REQ_MULTI(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_req_multi
|
||||
#define SCTP_NEW_ASSOCIATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_resp
|
||||
#define SCTP_NEW_ASSOCIATION_IND(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_ind
|
||||
#define SCTP_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.sctp_data_ind
|
||||
#define SCTP_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_data_req
|
||||
#define SCTP_INIT_MSG(mSGpTR) (mSGpTR)->ittiMsg.sctp_init
|
||||
#define SCTP_INIT_MSG_MULTI_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_init_multi
|
||||
#define SCTP_INIT_MSG_MULTI_CNF(mSGpTR) (mSGpTR)->ittiMsg.sctp_init_msg_multi_cnf
|
||||
#define SCTP_CLOSE_ASSOCIATION(mSGpTR) (mSGpTR)->ittiMsg.sctp_close_association
|
||||
|
||||
enum sctp_state_e {
|
||||
SCTP_STATE_CLOSED,
|
||||
@@ -56,6 +59,32 @@ typedef struct sctp_new_association_req_s {
|
||||
net_ip_address_t remote_address;
|
||||
} sctp_new_association_req_t;
|
||||
|
||||
typedef struct sctp_new_association_req_multi_s {
|
||||
/* Upper layer connexion identifier */
|
||||
uint16_t ulp_cnx_id;
|
||||
|
||||
/* The port to connect to */
|
||||
uint16_t port;
|
||||
/* Payload Protocol Identifier to use */
|
||||
uint32_t ppid;
|
||||
|
||||
/* Number of streams used for this association */
|
||||
uint16_t in_streams;
|
||||
uint16_t out_streams;
|
||||
|
||||
/* Local address to bind to */
|
||||
net_ip_address_t local_address;
|
||||
/* Remote address to connect to */
|
||||
net_ip_address_t remote_address;
|
||||
|
||||
/* Multi-socket descriptor */
|
||||
int multi_sd;
|
||||
} sctp_new_association_req_multi_t;
|
||||
|
||||
typedef struct sctp_init_msg_multi_cnf_s {
|
||||
int multi_sd;
|
||||
} sctp_init_msg_multi_cnf_t;
|
||||
|
||||
typedef struct sctp_new_association_ind_s {
|
||||
/* Assoc id of the new association */
|
||||
int32_t assoc_id;
|
||||
|
||||
@@ -22,21 +22,21 @@
|
||||
/* eNB application layer -> X2AP messages */
|
||||
/* ITTI LOG messages */
|
||||
/* ENCODER */
|
||||
MESSAGE_DEF(X2AP_RESET_REQUST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_reset_request_log)
|
||||
MESSAGE_DEF(X2AP_RESOURCE_STATUS_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_response_log)
|
||||
MESSAGE_DEF(X2AP_RESOURCE_STATUS_FAILURE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_failure_log)
|
||||
MESSAGE_DEF(X2AP_RESET_REQUST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_reset_request_log)
|
||||
MESSAGE_DEF(X2AP_RESOURCE_STATUS_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_response_log)
|
||||
MESSAGE_DEF(X2AP_RESOURCE_STATUS_FAILURE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_failure_log)
|
||||
|
||||
/* Messages for X2AP logging */
|
||||
MESSAGE_DEF(X2AP_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_setup_request_log)
|
||||
MESSAGE_DEF(X2AP_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_setup_request_log)
|
||||
|
||||
|
||||
/* eNB application layer -> X2AP messages */
|
||||
MESSAGE_DEF(X2AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, x2ap_register_enb_req_t , x2ap_register_enb_req)
|
||||
MESSAGE_DEF(X2AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, x2ap_register_enb_req_t , x2ap_register_enb_req)
|
||||
|
||||
/* X2AP -> eNB application layer messages */
|
||||
MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_register_enb_cnf_t , x2ap_register_enb_cnf)
|
||||
MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregistered_enb_ind_t , x2ap_deregistered_enb_ind)
|
||||
MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_register_enb_cnf_t , x2ap_register_enb_cnf)
|
||||
MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregistered_enb_ind_t , x2ap_deregistered_enb_ind)
|
||||
|
||||
/* handover messages X2AP <-> RRC */
|
||||
MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req)
|
||||
MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack)
|
||||
MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req)
|
||||
MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
+13
-13
@@ -19,19 +19,19 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*
|
||||
* messages_types.h
|
||||
*
|
||||
* Created on: Oct 14, 2013
|
||||
* Author: winckel
|
||||
/*! \file flexran_agent_mac_slice_verification.h
|
||||
* \brief MAC Agent slice verification helper functions
|
||||
* \author Robert Schmidt
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
*/
|
||||
|
||||
#ifndef MESSAGES_TYPES_H_
|
||||
#define MESSAGES_TYPES_H_
|
||||
#include "flexran_agent_common_internal.h"
|
||||
#include "flexran_agent_mac_internal.h"
|
||||
|
||||
#include "intertask_messages_types.h"
|
||||
#include "timer_messages_types.h"
|
||||
|
||||
// Dummy file for the generic intertask interface definition. Actual definition should be in top level build directory.
|
||||
|
||||
#endif /* MESSAGES_TYPES_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 {
|
||||
|
||||
+119
-13
@@ -39,7 +39,6 @@
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
# include "intertask_interface.h"
|
||||
# include "timer.h"
|
||||
# if defined(ENABLE_USE_MME)
|
||||
# include "s1ap_eNB.h"
|
||||
# include "sctp_eNB_task.h"
|
||||
@@ -48,7 +47,7 @@
|
||||
# define EPC_MODE_ENABLED 0
|
||||
# endif
|
||||
|
||||
//# include "x2ap_eNB.h"
|
||||
# include "x2ap_eNB.h"
|
||||
# include "x2ap_messages_types.h"
|
||||
# define X2AP_ENB_REGISTER_RETRY_DELAY 10
|
||||
|
||||
@@ -65,6 +64,8 @@ extern RAN_CONTEXT_t RC;
|
||||
# define ENB_REGISTER_RETRY_DELAY 10
|
||||
# endif
|
||||
|
||||
#include "targets/RT/USER/lte-softmodem.h"
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
@@ -156,7 +157,7 @@ static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end)
|
||||
|
||||
RCconfig_X2(msg_p, enb_id);
|
||||
|
||||
//itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
|
||||
itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
|
||||
|
||||
register_enb_x2_pending++;
|
||||
}
|
||||
@@ -178,8 +179,8 @@ void *eNB_app_task(void *args_p)
|
||||
long enb_register_retry_timer_id;
|
||||
# endif
|
||||
uint32_t x2_register_enb_pending;
|
||||
//uint32_t x2_registered_enb;
|
||||
//long x2_enb_register_retry_timer_id;
|
||||
uint32_t x2_registered_enb;
|
||||
long x2_enb_register_retry_timer_id;
|
||||
uint32_t enb_id;
|
||||
MessageDef *msg_p = NULL;
|
||||
instance_t instance;
|
||||
@@ -226,7 +227,7 @@ void *eNB_app_task(void *args_p)
|
||||
#endif
|
||||
|
||||
/* Try to register each eNB with each other */
|
||||
// x2_registered_enb = 0;
|
||||
x2_registered_enb = 0;
|
||||
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
|
||||
|
||||
do {
|
||||
@@ -245,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),
|
||||
@@ -297,16 +302,67 @@ void *eNB_app_task(void *args_p)
|
||||
|
||||
case TIMER_HAS_EXPIRED:
|
||||
# if defined(ENABLE_USE_MME)
|
||||
LOG_I(ENB_APP, " Received %s: timer_id %ld\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id);
|
||||
LOG_I(ENB_APP, " Received %s: timer_id %ld\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id);
|
||||
|
||||
if (TIMER_HAS_EXPIRED (msg_p).timer_id == enb_register_retry_timer_id) {
|
||||
/* Restart the registration process */
|
||||
registered_enb = 0;
|
||||
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end);//, enb_properties_p);
|
||||
}
|
||||
#endif
|
||||
if (TIMER_HAS_EXPIRED (msg_p).timer_id == enb_register_retry_timer_id) {
|
||||
/* Restart the registration process */
|
||||
registered_enb = 0;
|
||||
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end);//, enb_properties_p);
|
||||
}
|
||||
|
||||
if (TIMER_HAS_EXPIRED (msg_p).timer_id == x2_enb_register_retry_timer_id) {
|
||||
/* Restart the registration process */
|
||||
x2_registered_enb = 0;
|
||||
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
|
||||
}
|
||||
# endif
|
||||
break;
|
||||
|
||||
case X2AP_DEREGISTERED_ENB_IND:
|
||||
LOG_W(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p),
|
||||
X2AP_DEREGISTERED_ENB_IND(msg_p).nb_x2);
|
||||
|
||||
/* TODO handle recovering of registration */
|
||||
break;
|
||||
|
||||
case X2AP_REGISTER_ENB_CNF:
|
||||
LOG_I(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p),
|
||||
X2AP_REGISTER_ENB_CNF(msg_p).nb_x2);
|
||||
|
||||
DevAssert(x2_register_enb_pending > 0);
|
||||
x2_register_enb_pending--;
|
||||
|
||||
/* Check if at least eNB is registered with one target eNB */
|
||||
if (X2AP_REGISTER_ENB_CNF(msg_p).nb_x2 > 0) {
|
||||
x2_registered_enb++;
|
||||
}
|
||||
|
||||
/* Check if all register eNB requests have been processed */
|
||||
if (x2_register_enb_pending == 0) {
|
||||
if (x2_registered_enb == enb_nb) {
|
||||
/* If all eNB are registered, start RRC HO task */
|
||||
|
||||
}else {
|
||||
uint32_t x2_not_associated = enb_nb - x2_registered_enb;
|
||||
|
||||
LOG_W(ENB_APP, " %d eNB %s not associated with the target\n",
|
||||
x2_not_associated, x2_not_associated > 1 ? "are" : "is");
|
||||
// timer to retry
|
||||
/* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
|
||||
if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
|
||||
INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
|
||||
&x2_enb_register_retry_timer_id) < 0) {
|
||||
LOG_E(ENB_APP, " Can not start eNB X2AP register: retry timer, use \"sleep\" instead!\n");
|
||||
|
||||
sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
|
||||
/* Restart the registration process */
|
||||
x2_registered_enb = 0;
|
||||
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(ENB_APP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
|
||||
@@ -322,3 +378,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");
|
||||
exit_fun("can not restart L1L2, killing lte-softmodem");
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
#else
|
||||
#include "RRC/LTE/MESSAGES/SystemInformationBlockType2.h"
|
||||
#endif
|
||||
#include "intertask_interface_types.h"
|
||||
#include "RRC/LTE/rrc_defs.h"
|
||||
#include <intertask_interface.h>
|
||||
|
||||
#define IPV4_STR_ADDR_TO_INT_NWBO(AdDr_StR,NwBo,MeSsAgE ) do {\
|
||||
struct in_addr inp;\
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
|
||||
# include "tree.h"
|
||||
# include "intertask_interface.h"
|
||||
# include "timer.h"
|
||||
|
||||
#define FLEXRAN_VERSION 0
|
||||
|
||||
@@ -167,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,57 +31,7 @@
|
||||
|
||||
#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"
|
||||
|
||||
void handle_reconfiguration(mid_t mod_id)
|
||||
{
|
||||
struct timespec start, end;
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
flexran_agent_info_t *flexran = RC.flexran[mod_id];
|
||||
|
||||
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_F(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);
|
||||
}
|
||||
#include "enb_app.h"
|
||||
|
||||
int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length) {
|
||||
|
||||
@@ -589,3 +539,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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
|
||||
# include "tree.h"
|
||||
# include "intertask_interface.h"
|
||||
# include "timer.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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--;
|
||||
@@ -787,13 +788,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
|
||||
// unsigned char aggregation;
|
||||
mac_rlc_status_resp_t rlc_status;
|
||||
unsigned char header_len_dcch = 0, header_len_dcch_tmp = 0;
|
||||
unsigned char header_len_dtch = 0, header_len_dtch_tmp =
|
||||
0, header_len_dtch_last = 0;
|
||||
unsigned char header_len_dtch = 0, header_len_dtch_tmp = 0, header_len_dtch_last = 0;
|
||||
unsigned char ta_len = 0;
|
||||
unsigned char sdu_lcids[NB_RB_MAX], lcid, offset, num_sdus = 0;
|
||||
uint16_t nb_rb, nb_rb_temp, nb_available_rb;
|
||||
uint16_t TBS, j, sdu_lengths[NB_RB_MAX], rnti, padding =
|
||||
0, post_padding = 0;
|
||||
uint16_t TBS, j, sdu_lengths[NB_RB_MAX], rnti, padding = 0, post_padding = 0;
|
||||
unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
|
||||
unsigned char round = 0;
|
||||
unsigned char harq_pid = 0;
|
||||
@@ -818,7 +817,10 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
|
||||
nfapi_dl_config_request_pdu_t *dl_config_pdu;
|
||||
int tdd_sfa;
|
||||
int ta_update;
|
||||
|
||||
#ifdef DEBUG_eNB_SCHEDULER
|
||||
int k;
|
||||
#endif
|
||||
|
||||
start_meas(&eNB->schedule_dlsch);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
|
||||
(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN);
|
||||
@@ -1335,8 +1337,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
|
||||
"[eNB %d][DCCH] CC_id %d Got %d bytes :",
|
||||
module_idP, CC_id, sdu_lengths[0]);
|
||||
|
||||
for (j = 0; j < sdu_lengths[0]; j++) {
|
||||
LOG_T(MAC, "%x ", dlsch_buffer[j]);
|
||||
for (k = 0; k < sdu_lengths[0]; k++) {
|
||||
LOG_T(MAC, "%x ", dlsch_buffer[k]);
|
||||
}
|
||||
|
||||
LOG_T(MAC, "\n");
|
||||
@@ -1389,8 +1391,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
|
||||
"[eNB %d][DCCH1] CC_id %d Got %d bytes :",
|
||||
module_idP, CC_id, sdu_lengths[num_sdus]);
|
||||
|
||||
for (j = 0; j < sdu_lengths[num_sdus]; j++) {
|
||||
LOG_T(MAC, "%x ", dlsch_buffer[j]);
|
||||
for (k = 0; k < sdu_lengths[num_sdus]; k++) {
|
||||
LOG_T(MAC, "%x ", dlsch_buffer[k]);
|
||||
}
|
||||
|
||||
LOG_T(MAC, "\n");
|
||||
@@ -1638,8 +1640,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
|
||||
#ifdef DEBUG_eNB_SCHEDULER
|
||||
LOG_T(MAC, "[eNB %d] First 16 bytes of DLSCH : \n",module_idP );
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
LOG_T(MAC, "%x.", dlsch_buffer[i]);
|
||||
for (k = 0; k < 16; k++) {
|
||||
LOG_T(MAC, "%x.", dlsch_buffer[k]);
|
||||
}
|
||||
|
||||
LOG_T(MAC, "\n");
|
||||
|
||||
@@ -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;
|
||||
@@ -1157,11 +1155,11 @@ program_dlsch_acknak(module_id_t module_idP, int CC_idP, int UE_idP,
|
||||
}
|
||||
break;
|
||||
case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE:
|
||||
AssertFatal(use_simultaneous_pucch_pusch == 1,
|
||||
AssertFatal(use_simultaneous_pucch_pusch == 0,
|
||||
"Cannot be NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE, simultaneous_pucch_pusch is active");
|
||||
break;
|
||||
case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE:
|
||||
AssertFatal(use_simultaneous_pucch_pusch == 0,
|
||||
AssertFatal(use_simultaneous_pucch_pusch == 1,
|
||||
"Cannot be NFAPI_UL_CONFIG_ULSCH_UCI_PDU_TYPE, simultaneous_pucch_pusch is inactive\n");
|
||||
break;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -1514,7 +1402,8 @@ schedule_ulsch_rnti(module_id_t module_idP,
|
||||
ul_req_index = 0;
|
||||
dlsch_flag = 0;
|
||||
for(ul_req_index = 0;ul_req_index < ul_req_tmp_body->number_of_pdus;ul_req_index++){
|
||||
if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE){
|
||||
if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE &&
|
||||
ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti){
|
||||
dlsch_flag = 1;
|
||||
LOG_D(MAC,"Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI HARQ to ULSCH HARQ(first)\n",frameP,subframeP,rnti,ul_req_index);
|
||||
break;
|
||||
@@ -1522,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
|
||||
@@ -1585,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
|
||||
@@ -1602,7 +1491,8 @@ schedule_ulsch_rnti(module_id_t module_idP,
|
||||
ul_req_index = 0;
|
||||
dlsch_flag = 0;
|
||||
for(ul_req_index = 0;ul_req_index < ul_req_tmp_body->number_of_pdus;ul_req_index++){
|
||||
if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE){
|
||||
if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE &&
|
||||
ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti){
|
||||
dlsch_flag = 1;
|
||||
LOG_D(MAC,"Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI HARQ to ULSCH HARQ(first)\n",frameP,subframeP,rnti,ul_req_index);
|
||||
break;
|
||||
|
||||
+123
-2
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
+1228
-898
File diff suppressed because it is too large
Load Diff
@@ -412,9 +412,9 @@ boolean_t pdcp_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 )
|
||||
if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti )
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -410,7 +410,7 @@ struct cx_entity *nas_CLASS_cx6(struct sk_buff *skb,
|
||||
#endif //NAS_DEBUG_CLASS
|
||||
|
||||
//if ((dst = (unsigned int*)&(((struct rt6_info *)skbdst)->rt6i_gateway)) == 0){
|
||||
if ((dst = ((struct iphdr*)(skb_network_header(skb)))->daddr) == 0) {
|
||||
if ( (dst = &((struct iphdr*)(skb_network_header(skb)))->daddr) == NULL) {
|
||||
|
||||
printk("nas_CLASS_cx6: dst addr is null \n");
|
||||
p = p->next;
|
||||
@@ -475,7 +475,7 @@ struct cx_entity *nas_CLASS_cx4(struct sk_buff *skb,
|
||||
if (skb!=NULL) {
|
||||
daddr = ((struct iphdr*)(skb_network_header(skb)))->daddr;
|
||||
|
||||
if (daddr!=NULL) {
|
||||
if (daddr!=0) {
|
||||
|
||||
#ifdef NAS_DEBUG_CLASS
|
||||
printk("[NAS][CLASS][IPv4] Searching for %d.%d.%d.%d\n",
|
||||
|
||||
@@ -53,17 +53,14 @@ void nas_COMMON_receive(uint16_t dlen,
|
||||
struct sk_buff *skb;
|
||||
struct ipversion *ipv;
|
||||
struct nas_priv *gpriv=netdev_priv(nasdev[inst]);
|
||||
uint32_t odaddr,osaddr;
|
||||
|
||||
//int i;
|
||||
|
||||
unsigned char protocol;
|
||||
|
||||
unsigned char /**addr,*/ *daddr,*saddr,*ifaddr /*,sn*/;
|
||||
|
||||
//struct udphdr *uh;
|
||||
//struct tcphdr *th;
|
||||
uint16_t *cksum,check;
|
||||
|
||||
struct iphdr *network_header;
|
||||
|
||||
@@ -114,11 +111,12 @@ void nas_COMMON_receive(uint16_t dlen,
|
||||
// Make the third byte of both the source and destination equal to the fourth of the destination
|
||||
|
||||
|
||||
|
||||
unsigned char * ifaddr, *saddr, daddr;
|
||||
daddr = (unsigned char *)&((struct iphdr *)skb->data)->daddr;
|
||||
odaddr = ((struct iphdr *)skb->data)->daddr;
|
||||
// sn = addr[3];
|
||||
saddr = (unsigned char *)&((struct iphdr *)skb->data)->saddr;
|
||||
uint32_t odaddr,osaddr;
|
||||
osaddr = ((struct iphdr *)skb->data)->saddr;
|
||||
|
||||
if (daddr[0] == saddr[0]) {// same network
|
||||
@@ -219,6 +217,7 @@ void nas_COMMON_receive(uint16_t dlen,
|
||||
|
||||
case IPPROTO_TCP:
|
||||
|
||||
uint16_t *cksum,check;
|
||||
cksum = (uint16_t*)&(((struct tcphdr*)(((char *)network_header + (network_header->ihl<<2))))->check);
|
||||
//check = csum_tcpudp_magic(((struct iphdr *)network_header)->saddr, ((struct iphdr *)network_header)->daddr, tcp_hdrlen(skb), IPPROTO_TCP, ~(*cksum));
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ int nas_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
// End debug information
|
||||
netif_stop_queue(dev);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || RHEL_RELEASE_CODE>=1796
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE>=1796)
|
||||
netif_trans_update(dev);
|
||||
#else
|
||||
dev->trans_start = jiffies;
|
||||
@@ -306,7 +306,7 @@ void nas_tx_timeout(struct net_device *dev)
|
||||
printk("TX_TIMEOUT: begin\n");
|
||||
// (struct nas_priv *)(dev->priv)->stats.tx_errors++;
|
||||
(priv->stats).tx_errors++;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || RHEL_RELEASE_CODE>=1796
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE>=1796)
|
||||
netif_trans_update(dev);
|
||||
#else
|
||||
dev->trans_start = jiffies;
|
||||
@@ -324,7 +324,7 @@ static const struct net_device_ops nasmesh_netdev_ops = {
|
||||
.ndo_set_mac_address = NULL,
|
||||
.ndo_set_config = nas_set_config,
|
||||
.ndo_do_ioctl = nas_CTL_ioctl,
|
||||
#if RHEL_RELEASE_CODE>=1797
|
||||
#if (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE>=1797)
|
||||
.extended.ndo_change_mtu = nas_change_mtu,
|
||||
#else
|
||||
.ndo_change_mtu = nas_change_mtu,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user