diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index aa11892fa6..15c44aed22 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -34,4 +34,5 @@ job1:
- sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR
- sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $EXTERNAL_SHARE_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$EXTERNAL_SHARE_DIR
- cat $OPENAIR_DIR/cmake_targets/autotests/log/results_autotests.xml
- when: manual
+ only:
+ - triggers
diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 3169c6cc98..81ddf37503 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -119,6 +119,7 @@ endmacro(add_list_string_option)
####################################################
# compilation flags
#############################################
+#set(CMAKE_BUILD_TYPE "Debug")
if (CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
endif()
@@ -235,6 +236,7 @@ add_boolean_option(DEBUG_OMG False "???")
add_boolean_option(XFORMS False "This adds the possibility to see the signal oscilloscope")
add_boolean_option(PRINT_STATS False "This adds the possibility to see the status")
add_boolean_option(T_TRACER False "Activate the T tracer, a debugging/monitoring framework" )
+add_boolean_option(UE_AUTOTEST_TRACE False "Activate UE autotest specific logs")
add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering")
@@ -475,7 +477,7 @@ include_directories ("${X2AP_DIR}")
# Hardware dependant options
###################################
add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4")
-add_list1_option(NB_ANTENNAS_TX "2" "Number of antennas in transmission" "1" "2" "4")
+add_list1_option(NB_ANTENNAS_TX "4" "Number of antennas in transmission" "1" "2" "4")
add_list1_option(NB_ANTENNAS_TXRX "2" "Number of antennas in ????" "1" "2" "4")
add_list2_option(RF_BOARD "EXMIMO" "RF head type" "None" "EXMIMO" "OAI_USRP" "OAI_BLADERF" "CPRIGW" "OAI_LMSSDR")
@@ -621,7 +623,7 @@ add_boolean_option(MESSAGE_CHART_GENERATOR False "For generating sequenc
add_boolean_option(MESSAGE_CHART_GENERATOR_RLC_MAC False "trace RLC-MAC exchanges in sequence diagrams")
add_boolean_option(MESSAGE_CHART_GENERATOR_PHY False "trace some PHY exchanges in sequence diagrams")
-add_boolean_option(ENB_AGENT True "enable eNB agent to inteface with a SDN contrller")
+add_boolean_option(FLEXRAN_AGENT_SB_IF False "enable FlexRAN agent to inteface with a SDN controller")
########################
# Include order
@@ -817,8 +819,10 @@ include_directories("${OPENAIR_DIR}/targets/ARCH/COMMON")
include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/USERSPACE/LIB/")
include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/DEFS")
include_directories("${OPENAIR2_DIR}/ENB_APP")
+include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC")
include_directories("${OPENAIR2_DIR}/UTIL/OSA")
include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/inc")
+include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/inc")
include_directories("${OPENAIR2_DIR}/UTIL/MEM")
include_directories("${OPENAIR2_DIR}/UTIL/LISTS")
include_directories("${OPENAIR2_DIR}/UTIL/FIFO")
@@ -837,6 +841,94 @@ include_directories("${OPENAIR_DIR}")
# Utilities Library
################
+if (FLEXRAN_AGENT_SB_IF)
+ # set the version of protobuf messages, V3 not supported yet
+ add_list1_option(FLPT_VERSION V2 "FLPT MSG protobuf grammar version" V2 V3)
+
+ if (${FLPT_VERSION} STREQUAL "V2")
+ set (FLPTDIR V2)
+ elseif (${FLPT_VERSION} STREQUAL "V3")
+ set (FLPTDIR V3)
+ endif(${FLPT_VERSION} STREQUAL "V2")
+
+ set(FLPT_MSG_DIR ${OPENAIR2_DIR}/ENB_APP/MESSAGES/${FLPTDIR} )
+ set(FLPT_MSG_FILES
+ ${FLPT_MSG_DIR}/header.proto
+ ${FLPT_MSG_DIR}/flexran.proto
+ ${FLPT_MSG_DIR}/stats_common.proto
+ ${FLPT_MSG_DIR}/stats_messages.proto
+ ${FLPT_MSG_DIR}/time_common.proto
+ ${FLPT_MSG_DIR}/controller_commands.proto
+ ${FLPT_MSG_DIR}/mac_primitives.proto
+ ${FLPT_MSG_DIR}/config_messages.proto
+ ${FLPT_MSG_DIR}/config_common.proto
+ ${FLPT_MSG_DIR}/control_delegation.proto
+ )
+
+ set(FLPT_C_DIR ${protobuf_generated_dir}/${FLPTDIR})
+ #message("calling protoc_call=${protoc_call} FLPT_C_DIR=${FLPT_C_DIR} FLPT_MSG_FILES=${FLPT_MSG_FILES}")
+ execute_process(COMMAND ${protoc_call} ${FLPT_C_DIR} ${FLPT_MSG_DIR} ${FLPT_MSG_FILES})
+ file(GLOB FLPT_source ${FLPT_C_DIR}/*.c)
+ set(FLPT_OAI_generated
+ ${FLPT_C_DIR}/header.pb-c.c
+ ${FLPT_C_DIR}/flexran.pb-c.c
+ ${FLPT_C_DIR}/stats_common.pb-c.c
+ ${FLPT_C_DIR}/stats_messages.pb-c.c
+ ${FLPT_C_DIR}/time_common.pb-c.c
+ ${FLPT_C_DIR}/controller_commands.pb-c.c
+ ${FLPT_C_DIR}/mac_primitives.pb-c.c
+ ${FLPT_C_DIR}/config_messages.pb-c.c
+ ${FLPT_C_DIR}/config_common.pb-c.c
+ ${FLPT_C_DIR}/control_delegation.pb-c.c
+ )
+
+ file(GLOB flpt_h ${FLPT_C_DIR}/*.h)
+ set(flpt_h ${flpt_h} )
+
+ add_library(FLPT_MSG
+ ${FLPT_OAI_generated}
+ ${FLPT_source}
+ )
+ set(FLPT_MSG_LIB FLPT_MSG)
+ #message("prpt c dir is : ${FLPT_C_DIR}")
+ include_directories (${FLPT_C_DIR})
+
+ add_library(ASYNC_IF
+ ${OPENAIR2_DIR}/UTIL/ASYNC_IF/socket_link.c
+ ${OPENAIR2_DIR}/UTIL/ASYNC_IF/link_manager.c
+ ${OPENAIR2_DIR}/UTIL/ASYNC_IF/message_queue.c
+ ${OPENAIR2_DIR}/UTIL/ASYNC_IF/ringbuffer_queue.c
+ )
+ set(ASYNC_IF_LIB ASYNC_IF)
+ include_directories(${OPENAIR2_DIR}/UTIL/ASYNC_IF)
+
+ add_library(FLEXRAN_AGENT
+ ${OPENAIR2_DIR}/ENB_APP/flexran_agent_handler.c
+ ${OPENAIR2_DIR}/ENB_APP/flexran_agent_common.c
+ ${OPENAIR2_DIR}/ENB_APP/flexran_agent_common_internal.c
+ ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c
+ ${OPENAIR2_DIR}/ENB_APP/flexran_agent.c
+ ${OPENAIR2_DIR}/ENB_APP/flexran_agent_task_manager.c
+ ${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
+ )
+ set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT)
+ #include_directories(${OPENAIR2_DIR}/ENB_APP)
+
+ set(PROTOBUF_LIB "protobuf-c")
+
+ FIND_PATH(LIBYAML_INCLUDE_DIR NAMES yaml.h)
+ FIND_LIBRARY(LIBYAML_LIBRARIES NAMES yaml libyaml)
+
+ INCLUDE(FindPackageHandleStandardArgs)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(Yaml DEFAULT_MSG LIBYAML_LIBRARIES LIBYAML_INCLUDE_DIR)
+ MARK_AS_ADVANCED(LIBYAML_INCLUDE_DIR LIBYAML_LIBRARIES)
+
+ #set(PROTOBUF_LIB "protobuf") #for Cpp
+endif()
+
+
add_library(HASHTABLE
${OPENAIR_DIR}/common/utils/hashtable/hashtable.c
${OPENAIR_DIR}/common/utils/hashtable/obj_hashtable.c
@@ -930,6 +1022,7 @@ set(SCHED_SRC
${OPENAIR1_DIR}/SCHED/phy_mac_stub.c
${OPENAIR1_DIR}/SCHED/pucch_pc.c
${OPENAIR1_DIR}/SCHED/pusch_pc.c
+ ${OPENAIR1_DIR}/SCHED/srs_pc.c
)
add_library(SCHED_LIB ${SCHED_SRC})
@@ -978,11 +1071,14 @@ set(PHY_SRC
${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_mbsfn.c
${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_ul.c
${OPENAIR1_DIR}/PHY/MODULATION/ul_7_5_kHz.c
+ ${OPENAIR1_DIR}/PHY/MODULATION/beamforming.c
+ ${OPENAIR1_DIR}/PHY/MODULATION/compute_bf_weights.c
${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/freq_equalization.c
${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_time.c
${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_timefreq.c
${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_adjust_sync.c
${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c
+ ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c
${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c
${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_est_freq_offset.c
@@ -1095,7 +1191,17 @@ set (MAC_SRC
${MAC_DIR}/eNB_scheduler_RA.c
${MAC_DIR}/pre_processor.c
${MAC_DIR}/config.c
- )
+ )
+
+if (FLEXRAN_AGENT_SB_IF)
+
+set (MAC_SRC ${MAC_SRC}
+ ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue.c
+ ${MAC_DIR}/flexran_agent_scheduler_dataplane.c
+ ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue_remote.c
+)
+
+endif()
set (ENB_APP_SRC
${OPENAIR2_DIR}/ENB_APP/enb_app.c
@@ -1108,6 +1214,14 @@ add_library(L2
${ENB_APP_SRC})
# ${OPENAIR2_DIR}/RRC/L2_INTERFACE/openair_rrc_L2_interface.c)
+if (FLEXRAN_AGENT_SB_IF)
+
+#Test for adding a shared library
+add_library(default_sched SHARED ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue.c)
+add_library(remote_sched SHARED ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue_remote.c)
+
+endif()
+
# L3 Libs
##########################
@@ -1468,6 +1582,23 @@ add_library(LFDS
${lfds}/lfds611_abstraction/lfds611_abstraction_malloc.c
)
+set(lfds7 ${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/src/)
+file(GLOB lfds7_queue ${lfds7}/lfds700_queue/*.c)
+file(GLOB lfds7_ring ${lfds7}/lfds700_ringbuffer/*.c)
+file(GLOB lfds7_qbss ${lfds7}/lfds700_queue_bounded_singleconsumer_singleproducer/*.c)
+file(GLOB lfds7_stack ${lfds7}/lfds700_stack/*.c)
+file(GLOB lfds7_freelist ${lfds7}/lfds700_freelist/*.c)
+file(GLOB lfds7_btree ${lfds7}/lfds700_btree_addonly_unbalanced/*.c)
+file(GLOB lfds7_hash ${lfds7}/lfds700_hash_addonly/*.c)
+file(GLOB lfds7_ordered_list ${lfds7}/lfds700_list_addonly_ordered_singlylinked/*.c)
+file(GLOB lfds7_unordered_list ${lfds7}/lfds700_list_addonly_singlylinked_unordered/*.c)
+file(GLOB lfds7_misc ${lfds7}/lfds700_misc/*.c)
+
+include_directories(${lfds7})
+add_library(LFDS7
+ ${lfds7_queue} ${lfds7_ring} ${lfds7_qbss} ${lfds7_stack} ${lfds7_freelist} ${lfds7_btree} ${lfds7_hash} ${lfds7_ordered_list} ${lfds7_unordered_list} ${lfds7_misc}
+)
+
# Simulation library
##########################
add_library(SIMU
@@ -1644,11 +1775,11 @@ add_executable(lte-softmodem
target_link_libraries (lte-softmodem -ldl
-Wl,--start-group
- RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB}
+ RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
-Wl,--end-group )
target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES})
-target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} )
+target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
target_link_libraries (lte-softmodem ${LIB_LMS_LIBRARIES})
target_link_libraries (lte-softmodem ${T_LIB})
@@ -1678,11 +1809,11 @@ add_executable(lte-softmodem-nos1
)
target_link_libraries (lte-softmodem-nos1
-Wl,--start-group
- RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB}
+ RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
-Wl,--end-group )
target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES})
-target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} )
+target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
target_link_libraries (lte-softmodem-nos1 ${LIB_LMS_LIBRARIES})
target_link_libraries (lte-softmodem-nos1 ${T_LIB})
@@ -1823,20 +1954,24 @@ add_executable(oaisim_nos1
target_include_directories(oaisim_nos1 PUBLIC ${OPENAIR_TARGETS}/SIMU/USER)
target_link_libraries (oaisim_nos1
-Wl,--start-group
- RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB}
+ RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
-Wl,--end-group )
target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES})
-target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib}
- ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES})
+target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib}
+ ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
#Force link with forms, regardless XFORMS option
target_link_libraries (oaisim_nos1 forms)
+
+#message("protobuflib is ${PROTOBUF_LIB}")
+
target_link_libraries (oaisim_nos1 ${T_LIB})
+
# Unitary tests for each piece of L1: example, mbmssim is MBMS L1 simulator
#####################################
-foreach(myExe dlsim ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim)
+foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim)
add_executable(${myExe}
${OPENAIR_BIN_DIR}/messages_xml.h
${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c
@@ -1844,7 +1979,8 @@ foreach(myExe dlsim ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syn
${T_SOURCE}
)
target_link_libraries (${myExe}
- -Wl,--start-group SIMU UTIL SCHED_LIB PHY LFDS ${ITTI_LIB} -Wl,--end-group
+
+ -Wl,--start-group SIMU UTIL SCHED_LIB PHY LFDS ${ITTI_LIB} LFDS7 -Wl,--end-group
pthread m rt ${CONFIG_LIBRARIES} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${T_LIB}
)
endforeach(myExe)
@@ -1917,6 +2053,7 @@ if (${T_TRACER})
add_dependencies(oaisim generate_T)
add_dependencies(oaisim_nos1 generate_T)
add_dependencies(dlsim generate_T)
+ add_dependencies(dlsim_tm7 generate_T)
add_dependencies(ulsim generate_T)
add_dependencies(pbchsim generate_T)
add_dependencies(scansim generate_T)
diff --git a/cmake_targets/autotests/openair.py b/cmake_targets/autotests/openair.py
index 5cea3aa121..7ad118ef1b 100644
--- a/cmake_targets/autotests/openair.py
+++ b/cmake_targets/autotests/openair.py
@@ -75,7 +75,7 @@ class openair(core):
return (stdout, stderr)
def connect(self, username, password, prompt='PEXPECT_OAI'):
- max_retries=100
+ max_retries=10
i=0
while i <= max_retries:
self.prompt1 = prompt
@@ -97,9 +97,9 @@ class openair(core):
# need to look for twice the string of the prompt
self.oai.prompt()
self.oai.prompt()
- self.oai.sendline('uptime')
- self.oai.prompt()
- print self.oai.before
+# self.oai.sendline('uptime')
+# self.oai.prompt()
+# print self.oai.before
break
except Exception, e:
error=''
@@ -171,7 +171,7 @@ class openair(core):
sys.exit(1)
def disconnect(self):
- print 'disconnecting the ssh connection to ' + self.address + '\n'
+# print 'disconnecting the ssh connection to ' + self.address + '\n'
self.oai.send('exit')
# self.cancel()
diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py
index ada0cf0932..9f08a00d1a 100755
--- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py
+++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py
@@ -20,10 +20,14 @@
# * contact@openairinterface.org
# */
-# \author Rohit Gupta
+# \author Rohit Gupta - Benoit ROBERT (benoit.robert@syrtem.com)
# \version 0.1
# @ingroup _test
+# \Changelog
+# 2016-11-18 :
+# - Add progess bar during test execution update_progress()
+
import tempfile
import threading
import sys
@@ -37,6 +41,8 @@ import math #from time import clock
import xml.etree.ElementTree as ET
import re
+#from dict2xml import dict2xml as xmlify
+
from colorama import Fore, Back, Style
import numpy as np
@@ -57,6 +63,36 @@ import ssh
from ssh import SSHSession
import argparse
+
+# update_progress() : Displays or updates a console progress bar
+## Accepts a float between 0 and 1. Any int will be converted to a float.
+## A value under 0 represents a 'halt'.
+## A value at 1 or bigger represents 100%
+def update_progress(progress, prefix_string):
+ barLength = 20 # Modify this to change the length of the progress bar
+ status = ""
+ #print "progress = "+ str(progress)
+ if isinstance(progress, int):
+ progress = float(progress)
+ if not isinstance(progress, float):
+ progress = 0
+ status = "error: progress var must be float\r\n"
+ if progress < 0:
+ progress = 0
+ status = "Halt...\r\n"
+ if progress >= 1:
+ progress = 1
+ status = "Done...\r\n"
+ block = int(round(barLength*progress))
+ text = "\r"+prefix_string+" [{0}] {1}% {2}".format( "="*block + " "*(barLength-block), progress*100, status)
+ sys.stdout.write(text)
+ sys.stdout.flush()
+
+
+def exit_prog(exit_val):
+ print(Style.RESET_ALL),
+ sys.exit(exit_val)
+
# \brief write a string to a file
# \param filename name of file
# \param string string to write
@@ -271,7 +307,7 @@ def update_config_file(oai, config_string, logdirRepo, python_script):
# \param logdir_local_base local directory
# \param operation operation to perform (get_all, put_all) transfers recursively for directories
def SSHSessionWrapper(machine, username, key_file, password, logdir_remote, logdir_local_base, operation):
- max_tries = 100
+ max_tries = 10
i=0
while i <= max_tries:
i = i +1
@@ -306,30 +342,50 @@ def SSHSessionWrapper(machine, username, key_file, password, logdir_remote, logd
# \param CleanUpAluLteBox program to terminate AlU Bell Labs LTE Box
# \param ExmimoRfStop String to stop EXMIMO card (specified in test_case_list.xml)
def cleanOldPrograms(oai, programList, CleanUpAluLteBox, ExmimoRfStop, logdir, logdirOAI5GRepo):
- cmd = 'sudo -E killall -s INT -q -r ' + programList + ' ; sleep 5 ; sudo -E killall -9 -q -r ' + programList
+ cmd = 'killall -9 ' + programList
result = oai.send(cmd, True)
- print "Killing old programs..." + result
+# print "\t\t > "+cmd
+# print "\t\t < "+result
+
+# print "Killing old programs on ..." + result
programArray = programList.split()
programListJoin = '|'.join(programArray)
cmd = " ( date ;echo \"Starting cleaning old programs.. \" ; dmesg|tail ; echo \"Current disk space.. \" ; df -h )>& " + logdir + "/oai_test_setup_cleanup.log.`hostname` 2>&1 ; sync"
result=oai.send_recv(cmd)
+# print "\t\t > "+cmd
+# print "\t\t < "+result
+
cmd = cleanupOldProgramsScript + ' ' + '\''+programListJoin+'\''
#result = oai.send_recv(cmd)
#print result
result = oai.send_expect_false(cmd, 'Match found', False)
- print "Looking for old programs..." + result
+# print "\t\t > "+cmd
+# print "\t\t < "+result
+
+# print "Looking for old programs..." + result
res=oai.send_recv(CleanUpAluLteBox, True)
+# print "\t\t > "+CleanUpAluLteBox
+# print "\t\t < "+res
cmd= " echo \"Starting EXmimoRF Stop... \" >> " + logdir + "/oai_test_setup_cleanup.log.`hostname` 2>&1 ; sync ";
- oai.send_recv(cmd)
+ result = oai.send_recv(cmd)
+# print "\t\t > "+cmd
+# print "\t\t < "+result
cmd = "( " + "cd " + logdirOAI5GRepo + " ; source oaienv ; " + ExmimoRfStop + " ) >> " + logdir + "/oai_test_setup_cleanup.log.`hostname` 2>&1 ; sync "
- print "cleanoldprograms cmd = " + cmd
+# print "cleanoldprograms cmd = " + cmd
res=oai.send_recv(cmd, False, timeout=600)
+# print "\t\t > "+cmd
+# print "\t\t < "+res
+
cmd= " echo \"Stopping EXmimoRF Stop... \" >> " + logdir + "/oai_test_setup_cleanup.log.`hostname` 2>&1 ; sync ";
- oai.send_recv(cmd)
+ result = oai.send_recv(cmd)
+# print "\t\t > "+cmd
+# print "\t\t < "+result
#res = oai.send_recv(ExmimoRfStop, False)
cmd = " ( date ;echo \"Finished cleaning old programs.. \" ; dmesg | tail)>> $HOME/.oai_test_setup_cleanup.log.`hostname` 2>&1 ; sync"
res=oai.send_recv(cmd)
+# print "\t\t > "+cmd
+# print "\t\t < "+res
# \brief Class thread to launch a generic command on remote machine
# \param threadID number of thread (for book keeping)
@@ -355,10 +411,10 @@ class oaiThread (threading.Thread):
try:
oai = openair('localdomain',self.machine)
oai.connect(self.username, self.password)
- print "Starting " + self.threadname + " on machine " + self.machine
+ # print "Starting " + self.threadname + " on machine " + self.machine
result = oai.send_recv(self.cmd, self.sudo, self.timeout)
- print "result = " + result
- print "Exiting " + self.threadname
+ #print "result = " + result
+ #print "Exiting " + self.threadname
oai.disconnect()
except Exception, e:
error=''
@@ -1269,6 +1325,8 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
if testcase_verdict != 'PASS': # if something went wrong to not run test cases
max_ntries=0
+ indent="\t\t"
+
runs_results = []
nb_runs = 0
nb_run_pass = 0
@@ -1288,9 +1346,11 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
#
# RUN initialization
# ----------------------------------------------------
- print (Fore.WHITE + indent + "> RUN_"+str(run).zfill(2)+" : " ),
-
- sys.stdout.flush()
+
+ prefix_string = Fore.WHITE + indent + "> RUN_"+str(run).zfill(2)+" :"
+
+# print (Fore.WHITE + indent + "> RUN_"+str(run).zfill(2)+" : " ),
+# sys.stdout.flush()
run_start_time=datetime.datetime.now()
@@ -1406,8 +1466,34 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
threads.append(thread_UE)
thread_eNB.start()
thread_UE.start()
+
+ run_work_inprogress_flag = True
+ progress_step = timeout_thread/20
+ progress_count = 0
+
+ while (run_work_inprogress_flag):
+
+
+ update_progress(float(progress_count)/float(timeout_thread),prefix_string)
+
+ time.sleep(progress_step)
+
+ progress_count += progress_step
+
+# sys.stdout.write ('#')
+# sys.stdout.flush()
+
+ run_work_inprogress_flag = False
+ for t in threads:
+ if t.isAlive():
+ run_work_inprogress_flag = True
+
+
+ update_progress(1,prefix_string)
+
for t in threads:
- t.join()
+ t.join()
+
#
#
@@ -1422,10 +1508,12 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
fname = logdir_local_run+ '/UE_exec' + '_' + str(run) + '_.log'
cell_synch_status = analyser.check_cell_synchro(fname)
+ print (Fore.WHITE + indent + "> Check Cell synchro :"),
+
if cell_synch_status == 'CELL_SYNCH':
- print '!!!!!!!!!!!!!! Cell synchronized !!!!!!!!!!!'
+ print ( Fore.GREEN + cell_synch_status)
else :
- print '!!!!!!!!!!!!!! Cell NOT NOT synchronized !!!!!!!!!!!'
+ print ( Fore.RED + cell_synch_status)
metric_checks_flag = 0
ue_seg_fault_status = analyser.check_exec_seg_fault(fname)
@@ -1444,6 +1532,9 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
# UE side metrics
metricList=testcase.findall('UE_metric')
for metric in metricList:
+
+ metric_verdict = 'PASS'
+
metric_def = {}
metric_def['id'] = metric.get('id')
metric_def['description'] = metric.get('description')
@@ -1464,15 +1555,19 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
metric_extracted = analyser.do_extract_metrics(args)
- print "\t > Metric "+metric_def['id']+" :"
- print "\t\t> min = "+ str( metric_extracted['metric_min'] )
- print "\t\t> min_index = "+ str( metric_extracted['metric_min_index'] )
- print "\t\t> max = "+ str( metric_extracted['metric_max'] )
- print "\t\t> max_index = "+ str( metric_extracted['metric_max_index'] )
- print "\t\t> mean = "+ str( metric_extracted['metric_mean'] )
- print "\t\t> median = "+ str( metric_extracted['metric_median'] )
+ print (Fore.WHITE + indent + "> Metric : "+metric_def['id']),
+ print ("(min="+str( metric_extracted['metric_min'])+", max="+str( metric_extracted['metric_max'])+", mean="+str( metric_extracted['metric_mean'])+", median="+str( metric_extracted['metric_median'])+")")
- verdict = analyser.do_check_verdict(metric_def, metric_extracted)
+# print "\t > Metric "+metric_def['id']+" :"
+# print "\t\t> min = "+ str( metric_extracted['metric_min'] )
+# print "\t\t> min_index = "+ str( metric_extracted['metric_min_index'] )
+# print "\t\t> max = "+ str( metric_extracted['metric_max'] )
+# print "\t\t> max_index = "+ str( metric_extracted['metric_max_index'] )
+# print "\t\t> mean = "+ str( metric_extracted['metric_mean'] )
+# print "\t\t> median = "+ str( metric_extracted['metric_median'] )
+
+ if metric_def['pass_fail_stat'] :
+ metric_verdict = analyser.do_check_verdict(metric_def, metric_extracted)
metric_fig = logdir_local_run+ '/UE_metric_'+ metric_def['id']+'_' + str(run) + '_.png'
analyser.do_img_metrics(metric_def, metric_extracted, metric_fig)
@@ -1500,6 +1595,13 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
runs_metrics.append(run_metrics)
+ if metric_verdict != 'PASS':
+ verdict = metric_verdict
+
+ # End Metrics LOOP
+ # ---------------------
+
+
# Traffic analysis
if UE_traffic_exec != "":
@@ -1553,9 +1655,9 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
run_stop_time=datetime.datetime.now()
run_duration = run_stop_time-run_start_time
# print (Fore.WHITE + ("duration=" :"),
- print (Fore.WHITE + indent + "> RUN duration : "+ str(run_duration) +"s" )
+ print (Fore.WHITE + indent + "> RUN duration : "+ str(run_duration) +"s" )
- print (Fore.WHITE + indent + "> RUN verdict :"),
+ print (Fore.WHITE + indent + "> RUN verdict :"),
if verdict == 'PASS':
nb_run_pass += 1
@@ -1585,6 +1687,8 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
# END RUN LOOP
#----------------------------------------------------
+ indent="\t"
+
# Test case duration
# ----------------------------------
testcase_time_stop = datetime.datetime.now()
@@ -1624,11 +1728,9 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
else:
print (Fore.YELLOW+'INCONCLUSIVE')
- duration= testcase_time_stop - testcase_time_start
- xmlFile = logdir_local_testcase + '/test.' + testcasename + '.xml'
- xml="\n \n"
- write_file(xmlFile, xml, mode="w")
+ print(Style.RESET_ALL)
+ duration= testcase_time_stop - testcase_time_start
test_result = dict(testcase_name=testcasename,
testcaseclass=testcaseclass,
@@ -1647,7 +1749,17 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
testcase_eNBMachine =eNBMachine,
testcase_UEMachine =UEMachine,
runs_results = runs_results)
- #test_results.append(test_result)
+ test_results.append(test_result)
+
+ xmlFile = logdir_local_testcase + '/test.' + testcasename + '.xml'
+ xml="\n \n"
+ write_file(xmlFile, xml, mode="w")
+
+# xmlFile_ng = logdir_local_testcase + '/test.' + testcasename + '_ng.xml'
+# xml_ng = xmlify(test_result, wrap=testcasename, indent=" ")
+# write_file(xmlFile_ng, xml_ng, mode="w")
+
+
return testcase_verdict
@@ -1666,12 +1778,12 @@ def search_test_case_group(testcasename, testcasegroup, test_case_exclude):
if entry.find('+') >=0:
match = re.search(entry, testcasename)
if match:
- print "\nSkipping test case as it is found in black list: " + testcasename
+ #print "\nSkipping test case as it is found in black list: " + testcasename
return False
else:
match = entry.find(testcasename)
if match >=0:
- print "\nSkipping test case as it is found in black list: " + testcasename
+ #print "\nSkipping test case as it is found in black list: " + testcasename
return False
if testcasegroup == '':
return True
@@ -1759,6 +1871,7 @@ if openairdir_local is None:
print "Environment variable OPENAIR_DIR not set correctly"
sys.exit()
locallogdir = openairdir_local + '/cmake_targets/autotests/log'
+reportdir = openairdir_local + '/cmake_targets/autotests/report'
MachineList = ''
MachineListGeneric=''
MachineDescDic={}
@@ -1767,12 +1880,19 @@ flag_start_testcase=False
nruns_lte_softmodem=''
flag_skip_git_head_check=False
flag_skip_oai_install=False
+flag_skip_machine_preparation=False
+flag_skip_sanity_check=False
+flag_generate_html_report = False
Timeout_cmd=''
xmlInputFile=''
-print "Number of arguments argc = " + str(len(sys.argv))
+
+#print "Number of arguments argc = " + str(len(sys.argv))
#for index in range(1,len(sys.argv) ):
# print "argv_" + str(index) + " : " + sys.argv[index]
+oai_list = []
+
+
i=1
while i < len (sys.argv):
arg=sys.argv[i]
@@ -1832,9 +1952,15 @@ while i < len (sys.argv):
i = i +1
elif arg == '--skip-oai-install':
flag_skip_oai_install=True
+ elif arg == '--skip-machine-preparation':
+ flag_skip_machine_preparation=True
+ elif arg == '--skip-sanity-check':
+ flag_skip_sanity_check=True
elif arg == '--test-suite' :
xmlInputFile = sys.argv[i+1]
i = i +1
+ elif arg == '--generate-html-report':
+ flag_generate_html_report=True
elif arg == '-h' :
print "-s: This flag *MUST* be set to start the test cases"
print "-r: Remove the log directory in autotests"
@@ -1852,90 +1978,65 @@ while i < len (sys.argv):
print "--skip-git-head-check: skip checking of GitHead remote/local branch (only for debugging)"
print "--timeout_cmd: Override the default parameter (timeout_cmd) in test_case_list.xml. This parameter is in seconds and should be > 120"
print "--skip-oai-install: Skips the openairinterface5g installer"
+ print "--skip-machine-preparation: skipp the whole system preparation -> direct to test cases"
+ print "--skip-sanity-check: skipp the machine sanity checks"
print "--test-suite: Select a XML test-suite file"
+ print "--generate-html-report: Generate an HTML report of the test campaign (supported only for noS1 testsuite !!)"
sys.exit()
else :
print "Unrecongnized Option: <" + arg + ">. Use -h to see valid options"
sys.exit()
i= i + 1
-try:
- os.environ["OPENAIR1_DIR"]
-except KeyError:
- print "Please set the environment variable OPENAIR1_DIR in the .bashrc"
- sys.exit(1)
-
-try:
- os.environ["OPENAIR2_DIR"]
-except KeyError:
- print "Please set the environment variable OPENAIR2_DIR in the .bashrc"
- sys.exit(1)
-
-try:
- os.environ["OPENAIR_TARGETS"]
-except KeyError:
- print "Please set the environment variable OPENAIR_TARGETS in the .bashrc"
- sys.exit(1)
-
-print "Killing zombie ssh sessions from earlier sessions..."
-cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"| awk \'{print $2}\' | sudo xargs kill -9 '
-
-os.system(cmd)
-
-try:
- analyser = __import__("lib_autotest_analyser")
-except ImportError as err:
- print('Import error: ' + str(err))
- exit(0)
-
-
-if flag_start_testcase == False:
- print "You need to start the testcase by passing option -s. Use -h to see all options. Aborting now..."
- sys.exit(1)
-
-# get the oai object
-host = os.uname()[1]
-#oai = openair('localdomain','calisson')
-oai_list = []
-
-#start_time = time.time() # datetime.datetime.now()
-if user=='':
- user = getpass.getuser()
-if pw=='':
- pw = getpass.getpass()
-
-print "Killing zombie ssh sessions from earlier sessions..."
-cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 '
-cmd = cmd + '; ps aux |grep \"/usr/bin/ssh -q -l ' + user + '\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 '
-os.system(cmd)
-
-print "host = " + host
-print "user = " + user
-if xmlInputFile == '':
- xmlInputFile=os.environ.get('OPENAIR_DIR')+"/cmake_targets/autotests/test_case_list.xml"
-NFSResultsDir = '/mnt/sradio'
-cleanupOldProgramsScript = '$OPENAIR_DIR/cmake_targets/autotests/tools/remove_old_programs.bash'
logdir = '/tmp/' + 'OAITestFrameWork-' + user + '/'
logdirOAI5GRepo = logdir + 'openairinterface5g/'
logdirOpenaircnRepo = logdir + 'openair-cn/'
patchdir = logdirOAI5GRepo + 'cmake_targets/autotests/patches/'
-
-if flag_remove_logdir == True:
- print "Removing directory: " + locallogdir
- os.system(' rm -fr ' + locallogdir + '; mkdir -p ' + locallogdir )
-else:
- os.system('mkdir -p ' + locallogdir)
-
-paramiko_logfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/log/paramiko.log')
-res=os.system(' echo > ' + paramiko_logfile)
-paramiko.util.log_to_file(paramiko_logfile)
-
-#pw=getpass.getpass()
+NFSResultsDir = '/mnt/sradio'
+cleanupOldProgramsScript = '$OPENAIR_DIR/cmake_targets/autotests/tools/remove_old_programs.bash'
#Now we parse the xml file for basic configuration
+if xmlInputFile == '':
+ xmlInputFile=os.environ.get('OPENAIR_DIR')+"/cmake_targets/autotests/test_case_list.xml"
xmlTree = ET.parse(xmlInputFile)
xmlRoot = xmlTree.getroot()
+#
+# Read test session configuration
+# ---------------------------------------------------------------------------------
+print (Fore.YELLOW + '\nStep 0.1 - Read test session configuration')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+test_session_start_time = datetime.datetime.now()
+print (Fore.WHITE + ' - start time : '+ str(test_session_start_time))
+
+host = os.uname()[1]
+print (Fore.WHITE + ' - MTC host : '+host)
+
+
+if user=='':
+ user = getpass.getuser()
+print (Fore.WHITE + ' - user : '+user)
+
+if pw=='':
+ pw = getpass.getpass()
+print (Fore.WHITE + ' - password : '+pw)
+
+print (Fore.WHITE + ' - cmd line flags : ')
+print (Fore.WHITE + ' + -s : '+str(flag_start_testcase))
+print (Fore.WHITE + ' + -r : '+str(flag_remove_logdir))
+print (Fore.WHITE + ' + -c : '+str(cleanUpRemoteMachines))
+print (Fore.WHITE + ' + --skip-git-head-check : '+str(flag_skip_git_head_check))
+print (Fore.WHITE + ' + --skip-oai-install : '+str(flag_skip_oai_install))
+print (Fore.WHITE + ' + --skip-machine-preparation : '+str(flag_skip_machine_preparation))
+print (Fore.WHITE + ' + --skip-sanity-check : '+str(flag_skip_sanity_check))
+
+
+print (Fore.WHITE + ' - Test setup basic config : (* -> overwrite by cmd line parameter)')
+print (Fore.WHITE + ' + test setup config file : '+str(xmlInputFile))
+print (Fore.WHITE + ' + remote setup dir : '+str(logdir))
+print (Fore.WHITE + ' + remote OAI5G repo : '+str(logdirOAI5GRepo))
+print (Fore.WHITE + ' + remote OpenAirCN repo : '+str(logdirOpenaircnRepo))
if MachineList =='':
@@ -1948,6 +2049,8 @@ if GitOAI5GRepo == '':
if GitOAI5GRepoBranch == '':
GitOAI5GRepoBranch = xmlRoot.findtext('GitOAI5GRepoBranch',default='')
+if GitOAI5GHeadVersion == '':
+ GitOAI5GHeadVersion = xmlRoot.findtext('GitOAI5GHeadVersion',default='')
GitOpenaircnRepoBranch = xmlRoot.findtext('GitOpenair-cnRepoBranch',default='')
CleanUpOldProgs = xmlRoot.findtext('CleanUpOldProgs',default='')
@@ -1960,25 +2063,27 @@ ExmimoRfStop = xmlRoot.findtext('ExmimoRfStop',default='')
if nruns_lte_softmodem == '':
nruns_lte_softmodem = xmlRoot.findtext('nruns_lte-softmodem',default='')
-OAI5GpatchFileList=xmlRoot.findall('OAI5GPatchFile')
+print (Fore.WHITE + ' + MachineList : '+ MachineList)
+print (Fore.WHITE + ' + GitOpenair-cnRepo : '+ GitOpenaircnRepo)
+print (Fore.WHITE + ' + GitOAI5GRepo : '+ GitOAI5GRepo)
+print (Fore.WHITE + ' + GitOAI5GBranch : '+ GitOAI5GRepoBranch)
+print (Fore.WHITE + ' + GitOpenaircnRepoBranch : '+ GitOpenaircnRepoBranch)
+print (Fore.WHITE + ' + NFSResultsShare : '+ NFSResultsShare)
+print (Fore.WHITE + ' + nruns_lte_softmodem : '+ nruns_lte_softmodem)
+print (Fore.WHITE + ' + Timeout_cmd : '+ Timeout_cmd)
-print "MachineList = " + MachineList
-print "GitOpenair-cnRepo = " + GitOpenaircnRepo
-print "GitOAI5GRepo = " + GitOAI5GRepo
-print "GitOAI5GBranch = " + GitOAI5GRepoBranch
-print "GitOpenaircnRepoBranch = " + GitOpenaircnRepoBranch
-print "NFSResultsShare = " + NFSResultsShare
-print "nruns_lte_softmodem = " + nruns_lte_softmodem
-print "Timeout_cmd = " + Timeout_cmd
if GitOAI5GHeadVersion == '':
- cmd = "git show-ref --heads -s "+ GitOAI5GRepoBranch
+ cmd = "git log --pretty=format:\'%H\' -n 1" # origin/"+ GitOAI5GRepoBranch
+# cmd = "git show-ref --heads -s "+ GitOAI5GRepoBranch
GitOAI5GHeadVersion = subprocess.check_output ([cmd], shell=True)
GitOAI5GHeadVersion=GitOAI5GHeadVersion.replace("\n","")
-print "GitOAI5GHeadVersion = " + GitOAI5GHeadVersion
-print "CleanUpOldProgs = " + CleanUpOldProgs
-print "Timeout_execution = " + str(Timeout_execution)
+ # Print commiter and date : git log -1 --pretty=format:"%an %ad"
+
+print (Fore.WHITE + ' + GitOAI5GHeadVersion : '+ GitOAI5GHeadVersion)
+#print "CleanUpOldProgs = " + CleanUpOldProgs
+print (Fore.WHITE + ' + Timeout_execution (s) : '+ str(Timeout_execution))
if GitOAI5GHeadVersion == '':
print "Error getting the OAI5GBranch Head version...Exiting"
@@ -1986,214 +2091,401 @@ if GitOAI5GHeadVersion == '':
NFSTestsResultsDir = NFSResultsShare + '/'+ GitOAI5GRepoBranch + '/' + GitOAI5GHeadVersion
-print "NFSTestsResultsDir = " + NFSTestsResultsDir
+#print "NFSTestsResultsDir = " + NFSTestsResultsDir
+
+OAI5GpatchFileList=xmlRoot.findall('OAI5GPatchFile')
+
+
MachineList = MachineList.split()
MachineListGeneric = MachineListGeneric.split()
-#index=0
+
+MachineDescDic
+
+
+#
+# 'Check Mater Test Controller sanity (MTC)'
+# ---------------------------------------------------------------------------------
+print (Fore.YELLOW + '\nStep 0.2 - Check Mater Test Controller sanity (MTC)')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+try:
+ print (Fore.WHITE + ' - check OpenAirInterface environment variable OPENAIR1_DIR... '),
+ os.environ["OPENAIR1_DIR"]
+except KeyError:
+ print (Fore.RED + 'FAILED')
+ print "Please set the environment variable OPENAIR1_DIR in the .bashrc or run 'source oaienv' "
+ exit_prog(1)
+print (Fore.GREEN + 'OK')
+
+try:
+ print (Fore.WHITE + ' - check OpenAirInterface environment variable OPENAIR2_DIR... '),
+ os.environ["OPENAIR2_DIR"]
+except KeyError:
+ print (Fore.RED + 'FAILED')
+ print "Please set the environment variable OPENAIR2_DIR in the .bashrc or run 'source oaienv' "
+ exit_prog(1)
+print (Fore.GREEN + 'OK')
+
+try:
+ os.environ["OPENAIR_TARGETS"]
+except KeyError:
+ print "Please set the environment variable OPENAIR_TARGETS in the .bashrc or run 'source oaienv' "
+ sexit_prog(1)
+
+print (Fore.WHITE + ' - kill zombie ssh sessions from earlier sessions... '),
+cmd='ps aux |grep \"/usr/bin/ssh -q -l ' + user + '\"| tr -s \" \" :| cut -f 2 -d :| xargs kill -9 '
+os.system(cmd)
+print (Fore.GREEN + 'DONE')
+
+if flag_start_testcase == False:
+ print "You need to start the testcase by passing option -s. Use -h to see all options. Aborting now..."
+ exit_prog(1)
+
+
+#print "Killing zombie ssh sessions from earlier sessions..."
+#cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 '
+#cmd = cmd + '; ps aux |grep \"/usr/bin/ssh -q -l ' + user + '\"| tr -s \" \" :| cut -f 2 -d :| xargs kill -9 '
+#os.system(cmd)
+#print cmd
+
+try:
+ analyser = __import__("lib_autotest_analyser")
+except ImportError as err:
+ print('Import error: ' + str(err))
+ exit(0)
+
+if flag_remove_logdir == True:
+ print "Removing directory: " + locallogdir
+ os.system(' rm -fr ' + locallogdir + '; mkdir -p ' + locallogdir )
+
+if not os.path.exists(locallogdir):
+ os.system('mkdir -p ' + locallogdir )
+
+
+paramiko_logfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/log/paramiko.log')
+res=os.system(' echo > ' + paramiko_logfile)
+paramiko.util.log_to_file(paramiko_logfile)
+
+
+#
+# 'REMOTE MACHINE SANITY CHEKS'
+# ---------------------------------------------------------------------------------
+print (Fore.YELLOW + '\nStep 0.3 - REMOTE MACHINE SANITY CHEKS')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+
for machine in MachineList:
oai_list.append( openair('localdomain',machine))
MachineDescDic[machine]={}
- #index = index + 1
-print "\nTesting the sanity of machines used for testing..."
-if localshell == 0:
+if not flag_skip_sanity_check:
+
+ if localshell == 0:
try:
- index=0
- for machine in MachineList:
- print '\n******* Note that the user <'+user+'> should be a sudoer *******\n'
- print '******* Connecting to the machine <'+machine+'> to perform the test *******\n'
- if not pw :
- print "username: " + user
- #pw = getpass.getpass()
- #print "password: " + pw
- else :
- print "username: " + user
- #print "password: " + pw
- # issues in ubuntu 12.04
- oai_list[index].connect(user,pw)
- print '\nChecking for sudo permissions on machine <'+machine+'>...'
- result = oai_list[index].send_expect_false('sudo -S -v','may not run sudo',True)
- print "Sudo permissions..." + result
-
- print '\nCleaning Older running programs : ' + CleanUpOldProgs
- cleanOldPrograms(oai_list[index], CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop, '$HOME', '/tmp')
+ index=0
+ for machine in MachineList:
+ print (Fore.WHITE + " - Check sanity for remote machine "+machine)
- #result = oai_list[index].send('mount ' + NFSResultsDir, True)
- #print "Mounting NFS Share " + NFSResultsDir + "..." + result
+ oai_list[index].connect(user,pw)
+ print (Fore.WHITE + " > Checking for sudo permissions for user "+user+ " : "),
+ result = oai_list[index].send_expect_false('sudo -S -v','may not run sudo',True)
+ if (result == 'OK'):
+ print (Fore.GREEN + result )
+ else:
+ print (Fore.RED + result )
+
+ print (Fore.WHITE + " > Cleaning Older running programs : "),
+ cleanOldPrograms(oai_list[index], CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop, '$HOME', '/tmp')
+ print (Fore.WHITE + " Done")
- # Check if NFS share is mounted correctly.
- #print 'Checking if NFS Share<' + NFSResultsDir + '> is mounted correctly...'
- #cmd = 'if grep -qs '+NFSResultsDir+ ' /proc/mounts; then echo \'' + NFSResultsDir + ' is mounted\' ; fi'
- #search_expr = NFSResultsDir + ' is mounted'
- #print "cmd = " + cmd
- #print "search_expr = " + search_expr
- #result = oai_list[index].send_expect(cmd, search_expr)
- #print "Mount NFS_Results_Dir..." + result
- index = index + 1
-
- #oai.connect2(user,pw)
- #oai.get_shell()
+ #result = oai_list[index].send('mount ' + NFSResultsDir, True)
+ #print "Mounting NFS Share " + NFSResultsDir + "..." + result
+
+ # Check if NFS share is mounted correctly.
+ #print 'Checking if NFS Share<' + NFSResultsDir + '> is mounted correctly...'
+ #cmd = 'if grep -qs '+NFSResultsDir+ ' /proc/mounts; then echo \'' + NFSResultsDir + ' is mounted\' ; fi'
+ #search_expr = NFSResultsDir + ' is mounted'
+ #print "cmd = " + cmd
+ #print "search_expr = " + search_expr
+ #result = oai_list[index].send_expect(cmd, search_expr)
+ #print "Mount NFS_Results_Dir..." + result
+ index = index + 1
+
+ #oai.connect2(user,pw)
+ #oai.get_shell()
except :
print 'Fail to connect to the machine: '+ machine
sys.exit(1)
+ else:
+ pw = ''
+ oai_list[0].connect_localshell()
else:
- pw = ''
- oai_list[0].connect_localshell()
+ print (Fore.RED + " Skipping Machine sanity check...")
-#We now prepare the machines for testing
-index=0
-threads_init_setup=[]
-for oai in oai_list:
- try:
- print "setting up machine: " + MachineList[index]
- #print oai_list[oai].send_recv('echo \''+pw+'\' |sudo -S -v')
- #print oai_list[oai].send_recv('sudo su')
- #print oai_list[oai].send_recv('who am i')
- #cleanUpPrograms(oai_list[oai]
- cmd = 'sudo -S -E rm -fr ' + logdir + ' ; mkdir -p ' + logdir
- result = oai.send_recv(cmd)
+#
+# 'REMOTE MACHINE TEST SETUP CONFIGURATION'
+# ---------------------------------------------------------------------------------
+print (Fore.YELLOW + '\nStep 0.4 - REMOTE MACHINE PREPARATION')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+if not flag_skip_machine_preparation:
+ index=0
+ threads_init_setup=[]
+ for oai in oai_list:
+ try:
+ print "setting up machine: " + MachineList[index]
+ #print oai_list[oai].send_recv('echo \''+pw+'\' |sudo -S -v')
+ #print oai_list[oai].send_recv('sudo su')
+ #print oai_list[oai].send_recv('who am i')
+ #cleanUpPrograms(oai_list[oai]
+ cmd = 'sudo -S -E rm -fr ' + logdir + ' ; mkdir -p ' + logdir
+ result = oai.send_recv(cmd)
+ print cmd
+
+ setuplogfile = logdir + '/setup_log_' + MachineList[index] + '_.txt'
+ setup_script = locallogdir + '/setup_script_' + MachineList[index] + '_.txt'
+
+ #Sometimes git fails so the script below retries in that case
+ localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/tools/git-retry.sh')
+ remotefile = logdir + '/git-retry.sh'
+ paramList=[]
+ port=22
+ paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
+ sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
+ sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
+
+ cmd = ' ( \n'
+ #cmd = cmd + 'rm -fR ' + logdir + '\n'
+ #cmd = cmd + 'mkdir -p ' + logdir + '\n'
+ cmd = cmd + 'cd '+ logdir + '\n'
+ cmd = cmd + 'sudo apt-get install -y git \n'
+ cmd = cmd + 'chmod 700 ' + logdir + '/git-retry.sh \n'
+ cmd = cmd + logdir + '/git-retry.sh clone '+ GitOAI5GRepo +' \n'
+ cmd = cmd + logdir + '/git-retry.sh clone '+ GitOpenaircnRepo + ' \n'
+ cmd = cmd + 'cd ' + logdirOAI5GRepo + '\n'
+ cmd = cmd + 'git checkout ' + GitOAI5GRepoBranch + '\n'
+ if GitOAI5GHeadVersion :
+ cmd = cmd + 'git checkout ' + GitOAI5GHeadVersion + '\n'
+ cmd = cmd + 'git_head=`git ls-remote |grep \'' + GitOAI5GRepoBranch + '\'` \n'
+ cmd = cmd + 'git_head=($git_head) \n'
+ cmd = cmd + 'git_head=${git_head[0]} \n'
+ cmd = cmd + 'echo \"GitOAI5GHeadVersion_remote = $git_head\" \n'
+ cmd = cmd + 'echo \"GitOAI5GHeadVersion_local = ' + GitOAI5GHeadVersion + '\" \n'
+ if flag_skip_git_head_check==True:
+ cmd = cmd + 'echo \"skipping GitHead check...\" \n '
+ else:
+ cmd = cmd + 'if [ \"$git_head\" != \"'+ GitOAI5GHeadVersion + '\" ]; then echo \"error: Git openairinterface5g head version does not match\" ; fi \n'
+ cmd = cmd + 'source oaienv' + '\n'
+ if flag_skip_oai_install == False:
+ cmd = cmd + 'source $OPENAIR_DIR/cmake_targets/tools/build_helper \n'
+ cmd = cmd + 'echo \"Installing core OAI dependencies...Start\" \n'
+ cmd = cmd + '$OPENAIR_DIR/cmake_targets/build_oai -I --install-optional-packages \n'
+ cmd = cmd + 'echo \"Installing core OAI dependencies...Finished\" \n'
+ #cmd = cmd + 'echo \"Installing BLADERF OAI dependencies...Start\" \n'
+ #cmd = cmd + 'check_install_bladerf_driver \n'
+ #cmd = cmd + 'echo \"Installing BLADERF OAI dependencies...Finished\" \n'
+ #cmd = cmd + 'echo \"Installing USRP OAI dependencies...Start\" \n'
+ #cmd = cmd + 'check_install_usrp_uhd_driver \n'
+ #cmd = cmd + 'echo \"Installing USRP OAI dependencies...Finished\" \n'
+ cmd = cmd + 'cd ' + logdirOpenaircnRepo + '\n'
+ cmd = cmd + 'git checkout ' + GitOpenaircnRepoBranch + '\n'
+ cmd = cmd + 'env |grep OPENAIR' + '\n'
+ cmd = cmd + ' cd ' + logdir + '\n'
+ cmd = cmd + 'mkdir -p ' + patchdir + '\n'
+ cmd = cmd + ' ) > ' + setuplogfile + ' 2>&1 \n'
+ #cmd = cmd + 'echo \' ' + cmd + '\' > ' + setup_script + ' 2>&1 \n '
+ #result = oai_list[index].send_recv(cmd, False, 300 )
+ write_file(setup_script, cmd, mode="w")
+ tempThread = oaiThread(index, 'thread_setup_'+str(index)+'_' + MachineList[index] , MachineList[index] , user, pw, cmd, False, 3000)
+ threads_init_setup.append(tempThread )
+ tempThread.start()
+ index = index + 1
+ except Exception, e:
+ print 'There is error in one of the commands to setup the machine '+ MachineList[index]
+ error=''
+ error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e)
+ error = error + traceback.format_exc()
+ print error
+ sys.exit(1)
+
+ #Now we wait for all the threads to complete
+ index = 0
+ for t in threads_init_setup:
+ t.join()
+
+ port = 22
+ paramList=[]
+ sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
+
+ #Now we copy patch files and apply them
+ print( Fore.WHITE + " - Installating patch files on machine " + MachineList[index])
+ for patchFile in OAI5GpatchFileList:
+ localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/patches/')+patchFile.get('name')
+ remotefile = logdirOAI5GRepo + '/cmake_targets/autotests/patches/'+patchFile.get('name')
+ if patchFile.get('machine') == MachineList[index] or patchFile.get('machine') == None:
+ if os.path.isfile(localfile):
+ print( Fore.WHITE + "\t> PATCH FILE :"+localfile)
+ paramList=[]
+ paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
+ sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
+ cmd = ' cd ' + logdirOAI5GRepo + ' ;git apply cmake_targets/autotests/patches/'+patchFile.get('name')
+ res = oai_list[index].send_recv(cmd)
+ #print res
- setuplogfile = logdir + '/setup_log_' + MachineList[index] + '_.txt'
- setup_script = locallogdir + '/setup_script_' + MachineList[index] + '_.txt'
+ paramList=[]
- #Sometimes git fails so the script below retries in that case
- localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/tools/git-retry.sh')
- remotefile = logdir + '/git-retry.sh'
- paramList=[]
- port=22
- paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
- sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
- sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
+ setuplogfile = logdir + '/setup_log_' + MachineList[index] + '_.txt'
+ setup_script = locallogdir + '/setup_script_' + MachineList[index] + '_.txt'
+ localfile = locallogdir + '/setup_log_' + MachineList[index] + '_.txt'
+ remotefile = logdir + '/setup_log_' + MachineList[index] + '_.txt'
+ sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
+ paramList.append ( {"operation":'get', "localfile":localfile, "remotefile":remotefile} )
+ #sftp_module (user, pw, MachineList[index], port, localfile, remotefile, sftp_log, "get")
+
+ #Now we copy test_case_list.xml on the remote machines
+ localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/test_case_list.xml')
+ remotefile = logdirOAI5GRepo + '/cmake_targets/autotests/test_case_list.xml'
+ # paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
+ # sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
+
+ sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
- cmd = ' ( \n'
- #cmd = cmd + 'rm -fR ' + logdir + '\n'
- #cmd = cmd + 'mkdir -p ' + logdir + '\n'
- cmd = cmd + 'cd '+ logdir + '\n'
- cmd = cmd + 'sudo apt-get install -y git \n'
- cmd = cmd + 'chmod 700 ' + logdir + '/git-retry.sh \n'
- cmd = cmd + logdir + '/git-retry.sh clone '+ GitOAI5GRepo +' \n'
- cmd = cmd + logdir + '/git-retry.sh clone '+ GitOpenaircnRepo + ' \n'
- cmd = cmd + 'cd ' + logdirOAI5GRepo + '\n'
- cmd = cmd + 'git checkout ' + GitOAI5GRepoBranch + '\n'
- #cmd = cmd + 'git checkout ' + GitOAI5GHeadVersion + '\n'
- cmd = cmd + 'git_head=`git ls-remote |grep \'' + GitOAI5GRepoBranch + '\'` \n'
- cmd = cmd + 'git_head=($git_head) \n'
- cmd = cmd + 'git_head=${git_head[0]} \n'
- cmd = cmd + 'echo \"GitOAI5GHeadVersion_remote = $git_head\" \n'
- cmd = cmd + 'echo \"GitOAI5GHeadVersion_local = ' + GitOAI5GHeadVersion + '\" \n'
- if flag_skip_git_head_check==True:
- cmd = cmd + 'echo \"skipping GitHead check...\" \n '
- else:
- cmd = cmd + 'if [ \"$git_head\" != \"'+ GitOAI5GHeadVersion + '\" ]; then echo \"error: Git openairinterface5g head version does not match\" ; fi \n'
- cmd = cmd + 'source oaienv' + '\n'
- if flag_skip_oai_install == False:
- cmd = cmd + 'source $OPENAIR_DIR/cmake_targets/tools/build_helper \n'
- cmd = cmd + 'echo \"Installing core OAI dependencies...Start\" \n'
- cmd = cmd + '$OPENAIR_DIR/cmake_targets/build_oai -I --install-optional-packages \n'
- cmd = cmd + 'echo \"Installing core OAI dependencies...Finished\" \n'
- #cmd = cmd + 'echo \"Installing BLADERF OAI dependencies...Start\" \n'
- #cmd = cmd + 'check_install_bladerf_driver \n'
- #cmd = cmd + 'echo \"Installing BLADERF OAI dependencies...Finished\" \n'
- #cmd = cmd + 'echo \"Installing USRP OAI dependencies...Start\" \n'
- #cmd = cmd + 'check_install_usrp_uhd_driver \n'
- #cmd = cmd + 'echo \"Installing USRP OAI dependencies...Finished\" \n'
- cmd = cmd + 'cd ' + logdirOpenaircnRepo + '\n'
- cmd = cmd + 'git checkout ' + GitOpenaircnRepoBranch + '\n'
- cmd = cmd + 'env |grep OPENAIR' + '\n'
- cmd = cmd + ' cd ' + logdir + '\n'
- cmd = cmd + 'mkdir -p ' + patchdir + '\n'
- cmd = cmd + ' ) > ' + setuplogfile + ' 2>&1 \n'
- #cmd = cmd + 'echo \' ' + cmd + '\' > ' + setup_script + ' 2>&1 \n '
- #result = oai_list[index].send_recv(cmd, False, 300 )
- write_file(setup_script, cmd, mode="w")
- tempThread = oaiThread(index, 'thread_setup_'+str(index)+'_' + MachineList[index] , MachineList[index] , user, pw, cmd, False, 3000)
- threads_init_setup.append(tempThread )
- tempThread.start()
- index = index + 1
- except Exception, e:
- print 'There is error in one of the commands to setup the machine '+ MachineList[index]
- error=''
- error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e)
- error = error + traceback.format_exc()
- print error
- sys.exit(1)
-
-#Now we wait for all the threads to complete
-index = 0
-for t in threads_init_setup:
- t.join()
- setuplogfile = logdir + '/setup_log_' + MachineList[index] + '_.txt'
- setup_script = locallogdir + '/setup_script_' + MachineList[index] + '_.txt'
- localfile = locallogdir + '/setup_log_' + MachineList[index] + '_.txt'
- remotefile = logdir + '/setup_log_' + MachineList[index] + '_.txt'
- port = 22
-
- #Now we copy patch files and apply them
- print "Installating patch files on machine " + MachineList[index]
- for patchFile in OAI5GpatchFileList:
- localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/patches/')+patchFile.get('name')
- remotefile = logdirOAI5GRepo + '/cmake_targets/autotests/patches/'+patchFile.get('name')
- if patchFile.get('machine') == MachineList[index] or patchFile.get('machine') == None:
- if os.path.isfile(localfile):
- print "\t> PATCH FILE :"+localfile
- paramList=[]
- paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
- sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
- cmd = ' cd ' + logdirOAI5GRepo + ' ;git apply cmake_targets/autotests/patches/'+patchFile.get('name')
- res = oai_list[index].send_recv(cmd)
-
- paramList=[]
-
- setuplogfile = logdir + '/setup_log_' + MachineList[index] + '_.txt'
- setup_script = locallogdir + '/setup_script_' + MachineList[index] + '_.txt'
- localfile = locallogdir + '/setup_log_' + MachineList[index] + '_.txt'
- remotefile = logdir + '/setup_log_' + MachineList[index] + '_.txt'
- sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
- paramList.append ( {"operation":'get', "localfile":localfile, "remotefile":remotefile} )
- #sftp_module (user, pw, MachineList[index], port, localfile, remotefile, sftp_log, "get")
-
- #Now we copy test_case_list.xml on the remote machines
- localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/test_case_list.xml')
- remotefile = logdirOAI5GRepo + '/cmake_targets/autotests/test_case_list.xml'
- paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
- sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
- sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
-
- cmd = ' cd ' + logdirOAI5GRepo + ' ; source oaienv ; env|grep OPENAIR \n'
- res = oai_list[index].send_recv(cmd)
- index = index +1
- if os.path.exists(localfile) == 0:
+ cmd = ' cd ' + logdirOAI5GRepo + ' ; source oaienv ; env|grep OPENAIR \n'
+ res = oai_list[index].send_recv(cmd)
+ index = index +1
+ if os.path.exists(localfile) == 0:
print "Setup log file <" + localfile + "> missing for machine <" + MachineList[index] + ">. Please check the setup log files. Exiting now"
sys.exit(1)
-#Now we process all the test cases
-#Now we check if there was error in setup files
+ #Now we process all the test cases
+ #Now we check if there was error in setup files
-status, out = commands.getstatusoutput('grep ' + ' -il \'error\' ' + locallogdir + '/setup_log*')
-if (out != '') :
- print "There is error in setup of machines"
- print "status = " + str(status) + "\n Check files for error = " + out
- print "Exiting now..."
- sys.exit(1)
+ status, out = commands.getstatusoutput('grep ' + ' -il \'error\' ' + locallogdir + '/setup_log*')
+ if (out != '') :
+ print "There is error in setup of machines"
+ print "status = " + str(status) + "\n Check files for error = " + out
+ print "Exiting now..."
+ sys.exit(1)
-cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop, '$HOME' , logdirOAI5GRepo)
-if cleanUpRemoteMachines == True:
- sys.exit(0)
+ cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop, '$HOME' , logdirOAI5GRepo)
+ if cleanUpRemoteMachines == True:
+ print "Error while cleaning Remote machines"
+ print "Exiting now..."
+ sys.exit(0)
+
+
+else:
+ print (Fore.RED + " Skipping Machine preparation...")
+
+# **************************************************************************
+# **************************************************************************
+# STEP 2 - TEST SELECTION AND PARAMETRIZATION
+# **************************************************************************
+# **************************************************************************
+
+print (Fore.YELLOW + '\nStep 2 - TEST SELECTION')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+print (Fore.WHITE + " Parsing test case list for test selection...")
+print (Fore.WHITE + " - TestCaseExclusionList : "+TestCaseExclusionList)
+print (Fore.WHITE + " - testcasegroup : "+testcasegroup)
+
+
+testcaseList=xmlRoot.findall('testCase')
+
+nb_total_testcases = 0
+nb_total_testcases_softmodem = 0
+nb_total_testcases_softmodem_noS1 = 0
+nb_total_testcases_compilation = 0
+nb_total_testcases_execution = 0
+
+nb_run_testcases = 0
+nb_run_testcases_softmodem = 0
+nb_run_testcases_softmodem_noS1 = 0
+nb_run_testcases_compilation = 0
+nb_run_testcases_execution = 0
+
+
+for testcase in testcaseList:
+ try:
+ testcasename = testcase.get('id')
+ testcaseclass = testcase.findtext('class',default='')
+ desc = testcase.findtext('desc',default='')
+ nb_total_testcases+=1
+
+ run_flag = search_test_case_group(testcasename, testcasegroup, TestCaseExclusionList)
+ if (run_flag):
+ nb_run_testcases+=1
+
+ if testcaseclass == 'lte-softmodem' :
+ nb_total_testcases_softmodem+=1
+ if (run_flag): nb_run_testcases_softmodem+=1
+ elif testcaseclass == 'lte-softmodem-noS1':
+ nb_total_testcases_softmodem_noS1+=1
+ if (run_flag): nb_run_testcases_softmodem_noS1+=1
+ elif testcaseclass == 'compilation':
+ nb_total_testcases_compilation+=1
+ if (run_flag): nb_run_testcases_compilation+=1
+ elif testcaseclass == 'execution':
+ nb_total_testcases_execution+=1
+ if (run_flag): nb_run_testcases_execution+=1
+ else :
+ print "Unknown test case class: " + testcaseclass
+ sys.exit()
+
+ except Exception, e:
+ error=''
+ error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e)
+ error = error + '\n testcasename = ' + testcasename + '\n testcaseclass = ' + testcaseclass + '\n desc = ' + 'desc' + '\n'
+ error = error + traceback.format_exc()
+ print error
+ print "Continuing to next test case..."
+
+print (Fore.WHITE + " Parsing done...")
+
+print (Fore.WHITE + " - Total number of test cases : "+str(nb_total_testcases))
+print (Fore.WHITE + " - Total number class softmodem : "+str(nb_total_testcases_softmodem))
+print (Fore.WHITE + " - Total number class softmodem-noS1 : "+str(nb_total_testcases_softmodem_noS1))
+print (Fore.WHITE + " - Total number class compilation : "+str(nb_total_testcases_compilation))
+print (Fore.WHITE + " - Total number class execution : "+str(nb_total_testcases_execution))
+print
+print (Fore.WHITE + " - Selected number of test cases : "+str(nb_run_testcases))
+print (Fore.WHITE + " - Selected class softmodem : "+str(nb_run_testcases_softmodem))
+print (Fore.WHITE + " - Selected class softmodem_noS1 : "+str(nb_run_testcases_softmodem_noS1))
+print (Fore.WHITE + " - Selected class compilation : "+str(nb_run_testcases_compilation))
+print (Fore.WHITE + " - Selected class execution : "+str(nb_run_testcases_execution))
+
+
+# **************************************************************************
+# **************************************************************************
+# STEP 3 - TEST CAMPAIGNS
+# **************************************************************************
+# **************************************************************************
+
+test_results = []
+
+
+print (Fore.YELLOW + '\nStep 3 - TEST CAMPAIGNS')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+print (Fore.WHITE + " Start test campaign...")
threadListGlobal=[]
-testcaseList=xmlRoot.findall('testCase')
-#print testcaseList
+run_count = 0
for testcase in testcaseList:
try:
testcasename = testcase.get('id')
testcaseclass = testcase.findtext('class',default='')
desc = testcase.findtext('desc',default='')
#print "Machine list top level = " + ','.join(MachineList)
+
if search_test_case_group(testcasename, testcasegroup, TestCaseExclusionList) == True:
+ run_count+=1
+ print (Fore.WHITE + " ("+str(run_count).zfill(3)+"/"+str(nb_run_testcases).zfill(3)+") - test case "+testcasename+" : "),
if testcaseclass == 'lte-softmodem' :
#First we wait for all the test cases in generic test case class to finish as they are running in parallel
threadListGlobal = wait_testcaseclass_generic_threads(threadListGlobal, Timeout_execution)
@@ -2266,6 +2558,22 @@ for param in threadListGlobal:
thread_id = param["thread_id"]
thread_id.join()
+
+# **************************************************************************
+# **************************************************************************
+# STEP 4 - TEST REPORT PRODUCTION
+# **************************************************************************
+# **************************************************************************
+
+
+
+test_session_stop_time = datetime.datetime.now()
+
+print (Fore.YELLOW + '\nStep 4 - TEST REPORT PRODUCTION')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+# XML test report
+# --------------------------------------------------------------------
print "Creating xml file for overall results..."
cmd = "cat $OPENAIR_DIR/cmake_targets/autotests/log/*/*.xml > $OPENAIR_DIR/cmake_targets/autotests/log/results_autotests.xml "
res=os.system(cmd)
@@ -2284,4 +2592,43 @@ res = oai_localhost.send_recv(cmd)
oai_localhost.disconnect()
+
+# HTML test report
+# --------------------------------------------------------------------
+if flag_generate_html_report:
+
+ print "Creating html test report..."
+
+ report_dir = reportdir + '/'+ test_session_start_time.strftime("%Y-%m-%d_%H-%M")+"_"+host
+
+ cmd = 'mkdir -p ' + report_dir
+ result = os.system(cmd)
+
+ cmd = 'cp -r '+locallogdir+' '+report_dir
+ result = os.system(cmd)
+
+ context = {
+ 'report_path' : report_dir,
+ 'test_session_start_time' : test_session_start_time,
+ 'test_session_stop_time' : test_session_stop_time,
+ 'test_session_duration' : test_session_stop_time-test_session_start_time,
+ 'mtc_host' : host,
+ 'user' : user,
+ 'password' : pw,
+ 'test_results' : test_results,
+ }
+
+ for test_result in test_results:
+ cmd = 'mkdir -p ' + report_dir + '/'+ test_result['testcase_name']
+ result = os.system(cmd)
+
+ report_file = report_dir + '/'+ test_result['testcase_name'] + '/'+ test_result['testcase_name']+ '_report.html'
+
+ analyser.create_test_report_detailed_html(test_result, report_file )
+
+ # print test_result
+
+ analyser.create_report_html(context)
+
+
sys.exit()
diff --git a/cmake_targets/autotests/templates/index.html b/cmake_targets/autotests/templates/index.html
new file mode 100644
index 0000000000..10a15fb53d
--- /dev/null
+++ b/cmake_targets/autotests/templates/index.html
@@ -0,0 +1,87 @@
+
+
+
+
+ OAI5G UE Autotest Report
+
+
+
+
+
+OAI5G UE Autotest Report
+
+
+
+
+ Test session configuration
+ | Start time | {{test_session_start_time}} |
+ | Stop time | {{test_session_stop_time}} |
+ | Duration | {{test_session_duration}} |
+ | MTC host | {{mtc_host}} |
+ | User | {{user}} |
+ | Password | {{password}} |
+
+
+
+
+Test Setup
+To be complete
+
+
+UE phy-test performances tests results
+Objectives
+Checks that OAI UE can achieve at least 75 percent of the theoretical throughput.
+Tests are done for all MCS (0 to 28) for 5MHz and 10MHz bandwidth.
+Results
+
+
+| ID | TAG | VERDICT | NB RUNS | PASS | FAILED | INCON | SKIPPED | SEG FAULT | TC Timeout | Start | Stop | Duration | Details |
+{% for result in test_results|sort(attribute='testcase_name') %}
+
+ | {{result.testcase_name}} |
+ {{result.tags}} |
+ {% if result.testcase_verdict == "PASS" %}
+ {{result.testcase_verdict}} |
+ {% elif result.testcase_verdict == "FAIL" %}
+ {{result.testcase_verdict}} |
+ {% else %}
+ {{result.testcase_verdict}} |
+ {% endif %}
+ {{result.nruns}} |
+ {{result.nb_run_pass}} |
+ {{result.nb_run_failed}} |
+ {{result.nb_run_inc}} |
+ {{result.nb_run_skip}} |
+ {{result.nb_seg_fault}} |
+ {{result.testcase_timeout}} |
+ {{result.testcase_time_start.strftime('%Y-%m-%d %H:%M:%S')}} |
+ {{result.testcase_time_stop.strftime('%Y-%m-%d %H:%M:%S')}} |
+ {{result.testcase_duration}} |
+ {{ result.testcase_name }}_report.html |
+
+{% endfor %}
+
+
+
+
+UE phy-test stability tests results
+Objectives
+To be complete
+Results
+To be complete
+
+
+
+
+
diff --git a/cmake_targets/autotests/templates/testcase_report.html b/cmake_targets/autotests/templates/testcase_report.html
new file mode 100644
index 0000000000..007ab56909
--- /dev/null
+++ b/cmake_targets/autotests/templates/testcase_report.html
@@ -0,0 +1,142 @@
+
+
+
+
+ OAI5G UE test case report
+
+
+
+
+
+OAI5G UE test case report details
+
+
+Test Case description
+
+
+
+ | ID | {{testcase_name}} |
+ | TAG | {{tags}} |
+ | class | {{testcaseclass}} |
+ | description | |
+ | timeout | {{testcase_timeout}} |
+ | number of runs | {{nruns}} |
+ | eNB machine | {{testcase_eNBMachine}} |
+ | UE machine | {{testcase_UEMachine}} |
+
+
+
+
+
+Test Case execution
+
+
+
+ | testcase_time_start | {{testcase_time_start}} |
+ | testcase_time_stop | {{testcase_time_stop}} |
+ | testcase_duration | {{testcase_duration}} |
+ | Nb runs | {{nruns}} |
+ | Nb PASS | {{nb_run_pass}} |
+ | Nb FAILED | {{nb_run_failed}} |
+ | Nb INCONCLUSIVE | {{nb_run_inc}} |
+
+ | testcase_verdict |
+ {% if testcase_verdict == "PASS" %}
+ {{testcase_verdict}} |
+ {% elif testcase_verdict == "FAIL" %}
+ {{testcase_verdict}} |
+ {% else %}
+ {{testcase_verdict}} |
+ {% endif %}
+
+ | Nb Seg Fault | {{nb_seg_fault}} |
+
+
+
+
+
+
+Test Case runs results
+
+{% for run_results in runs_results|sort(attribute='run_id') %}
+RUN {{run_results.run_id}}
+
+ | run_start_time | {{run_results.run_start_time}} |
+ | run_stop_time | {{run_results.run_stop_time}} |
+ | run_duration | {{run_results.run_duration}} |
+
+ | run_verdict |
+ {% if run_results.run_verdict == "PASS" %}
+ {{run_results.run_verdict}} |
+ {% elif run_results.run_verdict == "FAIL" %}
+ {{run_results.run_verdict}} |
+ {% else %}
+ {{run_results.run_verdict}} |
+ {% endif %}
+
+ | Seg Fault Satus |
+ {% if run_results.ue_seg_fault_status == "NO_SEG_FAULT" %}
+ {{run_results.ue_seg_fault_status}} |
+ {% elif run_results.ue_seg_fault_status == "SEG_FAULT" %}
+ {{run_results.ue_seg_fault_status}} |
+ {% else %}
+ unknown |
+ {% endif %}
+
+
+
+ {% for run_metrics in run_results.runs_metrics %}
+
+
+ | metric_id | {{run_metrics.metric_id}} |
+ | Description | {{run_metrics.metric_desc}} |
+ | Unit of measure | {{run_metrics.metric_uom}} |
+ | metric_min | {{run_metrics.metric_min}} |
+ | metric_max | {{run_metrics.metric_max}} |
+ | metric_mean | {{run_metrics.metric_mean}} |
+ | metric_median | {{run_metrics.metric_median}} |
+ |
+ {% if run_metrics.pass_fail_stat is defined %}
+ | Pass/fail stat | {{run_metrics.pass_fail_stat}} |
+ {% endif %}
+ {% if run_metrics.pass_fail_min_limit is defined %}
+ | Pass/fail min limit | {{run_metrics.pass_fail_min_limit}} |
+ {% endif %}
+ {% if run_metrics.pass_fail_max_limit is defined %}
+ | Pass/fail max limit | {{run_metrics.pass_fail_max_limit}} |
+ {% endif %}
+ |
+ | metric_fig |  |
+
+
+ {% endfor %}
+
+ {% if run_results.run_traffic.traffic_count != 0 %}
+
+
+ | Iperf metric | min | max | mean | median |
|---|
+
| Bandwidth | {{run_results.run_traffic.bw_min}} | {{run_results.run_traffic.bw_max}} | {{run_results.run_traffic.bw_mean}} | {{run_results.run_traffic.bw_median}} |
+
| Jitter | {{run_results.run_traffic.jitter_min}} | {{run_results.run_traffic.jitter_max}} | {{run_results.run_traffic.jitter_mean}} | {{run_results.run_traffic.jitter_median}} |
+
| Loss rate | {{run_results.run_traffic.rl_min}} | {{run_results.run_traffic.rl_max}} | {{run_results.run_traffic.rl_mean}} | {{run_results.run_traffic.rl_median}} |
+
|
+ | Iperf duration | {{run_results.run_traffic.iperf_duration}} | | Pass/Fail criteria (min duration) | {{run_results.run_traffic.dur_pass_fail_crit}} |
+
|
+ | traffic_fig |  |
+
+ {% endif %}
+
+{% endfor %}
+
+
+
diff --git a/cmake_targets/autotests/testsuite_ue_noS1.xml b/cmake_targets/autotests/testsuite_ue_noS1.xml
new file mode 100644
index 0000000000..c5403feab2
--- /dev/null
+++ b/cmake_targets/autotests/testsuite_ue_noS1.xml
@@ -0,0 +1,3214 @@
+
+
+imb182-desktop yanbo-M4HM87P-00
+ /mnt/sradio/TEST_RESULTS/
+ https://gitlab.eurecom.fr/oai1B/openairinterface5g.git
+
+
+ https://gitlab.eurecom.fr/oai/openair-cn.git -->
+ develop1B
+ develop1B_integration_w49 -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+ develop
+ oaisim oaisim_nos1 lte-softmodem lte-softmodem-nos1 mme_gw run_epc auth_request run_hss oai_hss mme spgw hss hss_sim configure_cots* wvdial iperf iperf_script iperf_script_phone ping tshark rrh_gw iperf3 iperf3_script iperf3_script_phone pppd
+ sudo -S -E /opt/ltebox/tools/stop_ltebox
+$OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_huaweiE398_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py --stop-ue; uname -a; sudo -E dmesg
+ 36000
+
+
+ yanbo-M4HM87P-00
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 0 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS00
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 0 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS00
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 1 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS01
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 1 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS01
+ 36
+
+
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 9 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS09
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 9 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS09
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 16 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS16
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 16 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS16
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 10 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS10
+
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 10 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS10
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 17 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS17
+
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 17 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS17
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 18 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS18
+
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 18 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS18
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 19 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS19
+
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 19 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS19
+ 36
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 20 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS20
+
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 20 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS20
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 21 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS21
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 21 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS21
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 22 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS22
+
+ 36
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 22 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS22
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 23 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS23
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 23 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS23
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 24 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS24
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 24 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS24
+ 36
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 25 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS25
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 25 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS25
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 26 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS26
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 26 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS26
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS27
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS27
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS28
+ 36
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 3600
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_STAB.BAND7.5MHZ.MCS27
+ 16
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_STAB.BAND7.5MHZ.MCS27
+ 36
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 27 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS27
+ 36
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 27 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r50 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS27
+ 36
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 28 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS28
+ 36
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 19 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r50 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test
+
+
+
+
+
+ False
+ UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS19
+ 36
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 28
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 30M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_USRP.NOS1.DATA_IPERF.BAND7.10MHZ.MCS28
+ 36
+
+
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 0
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 512K
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS00
+ 36
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 9
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS09
+ 36
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 10
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS10
+ 36
+
+
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 16
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS16
+ 36
+
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 17
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS17
+ 36
+
+
+
+
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 19
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 10M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS19
+ 36
+
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 3600
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1 -u
+
+ 2800
+
+ False
+ UE_USRP.NOS1.DATA_IPERF_STAB.BAND7.5MHZ.MCS27
+ 16
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ ued-PRM-130
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w EXMIMO --noS1 --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS27
+ 36
+
+
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 0
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 512K
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS00
+ 36
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 9
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS09
+ 36
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 10
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS10
+ 36
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 16
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS16
+ 36
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 17
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS17
+ 36
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 19
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS19
+ 36
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27
+ sleep 30;iperf -c 10.0.1.9 -i 1 -u -b 15M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 5; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+ UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS27
+ 36
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+
+
+
+ UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS28
+ 36
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 18000
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28 --single-thread-disable --phy-test
+
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S --phy-test
+
+
+
+
+
+ False
+
+
+
+ UE_USRP.NOS1.PHYTEST_STAB.BAND7.5MHZ.MCS28
+ 16
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28
+ sleep 30;iperf -c 10.0.1.9 -i 1 -u -b 13700K
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 5; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1 -u
+
+ 200
+
+ False
+
+
+
+
+ UE_USRP.NOS1.DATA_IPERF_DL.BAND7.5MHZ.MCS28
+ 36
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 3600
+ UE_USRP.NOS1.DATA_IPERF_STAB_DL.BAND7.5MHZ.MCS28
+ 16
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28
+ sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1 -u
+
+ 2800
+
+ False
+
+
+
+
+
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28
+ sleep 30;iperf -c 10.0.1.9 -i 1
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 5; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1
+
+ 200
+
+ False
+
+
+
+
+ UE_USRP.NOS1.DATA_IPERF_TCP_DL.BAND7.5MHZ.MCS28
+ 36
+
+
+
+
+ lte-softmodem-noS1
+
+ imb182-desktop
+ yanbo-M4HM87P-00
+ 300
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c -w USRP --eNB --noS1
+ source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB
+
+ $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1
+ -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 28
+ sleep 80;iperf -c 10.0.1.9 -i 1
+
+
+
+ False
+
+ /tmp
+
+ $OPENAIR_DIR/cmake_targets/build_oai
+ -c --UE -w USRP --noS1 --eNB --ue-autotest-trace
+ source ./targets/bin/init_nas_nos1 UE
+
+ sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S
+
+ iperf -s -i 1
+
+ 200
+
+ False
+ UE_USRP.NOS1.DATA_IPERF_TCP_DL.BAND7.10MHZ.MCS28
+ 36
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cmake_targets/autotests/tools/autotest_analyser.py b/cmake_targets/autotests/tools/autotest_analyser.py
index a75727ad65..61759a1545 100755
--- a/cmake_targets/autotests/tools/autotest_analyser.py
+++ b/cmake_targets/autotests/tools/autotest_analyser.py
@@ -35,12 +35,15 @@ import getopt
import sys
from subprocess import call
+import encoder
+
+sys.path.append(os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/tools/'))
#test_cases = ('030001', '030901', '031001', '031601', '031701', '031801', '031901', '032001', '032101', '032201', '032301', '032501', '032601', '032801')
-test_cases = ('030030' , '030030' )
+test_cases = ('032800' , '032730' )
-nb_run = 3
+nb_run = 2
def error_opt(msg):
print("Option error: " + msg)
@@ -58,14 +61,27 @@ def main(args):
+ # metric = {}
+ # metric['id'] = 'UE_DLSCH_BITRATE'
+ # metric['description'] = 'UE downlink physical throughput'
+ # metric['regex'] = '(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)'
+ # metric['unit_of_meas'] = 'kbps'
+ # metric['min_limit'] = 14668.8
+
+
+#AUTOTEST Metric : RRC Measurments RSRP[0]=-97.60 dBm/RE, RSSI=-72.83 dBm, RSRQ[0] 9.03 dB, N0 -125 dBm/RE, NF 7.2 dB (frame = 4490)
+
metric = {}
- metric['id'] = 'UE_DLSCH_BITRATE'
- metric['description'] = 'UE downlink physical throughput'
- metric['regex'] = '(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)'
+ metric['id'] = 'UE_DL_RRC_MEAS'
+ metric['description'] = 'UE downlink RRC Measurments'
+ metric['nb_metric'] = 5
+# metric['regex'] = 'AUTOTEST Metric : RRC Measurments (RSRP\[0\])=(-?\d+\.?\d*)\s+(.+),\s+(RSRQ\[0\])=(-?\d+\.?\d*)\s+(.+),,\s+(N0)=(-?\d+\.?\d*)\s+(.+),,\s+(NF)=(-?\d+\.?\d*)\s+(.+)\s+\(frame = (\d+)\) '
+ metric['regex'] = 'AUTOTEST Metric : RRC Measurments (RSRP\[0\])=(-?\d+\.?\d*)\s+(.+)\,\s+(RSSI)=(-?\d+\.?\d*)\s+(.+)\,\s+(RSRQ\[0\])=(-?\d+\.?\d*)\s+(.+)\,\s+(N0)=(-?\d+\.?\d*)\s+(.+)\,\s+(NF)=(-?\d+\.?\d*)\s+(.+)\s+\(frame = (\d+)\)'
metric['unit_of_meas'] = 'kbps'
metric['min_limit'] = 14668.8
+
#report_path = log_path+'/report/'
#os.system(' mkdir -p ' + report_path)
@@ -74,58 +90,44 @@ def main(args):
#return(0)
+ test_results = []
+
for test_case in test_cases:
-# print test_case
- if test_case == '030001':
- metric['min_limit'] = 500.0
- if test_case == '030901':
- metric['min_limit'] = 640.0
- if test_case == '031001':
- metric['min_limit'] = 3200.0
- if test_case == '031601':
- metric['min_limit'] = 5920.0
- if test_case == '031701':
- metric['min_limit'] = 6000.0
- if test_case == '031801':
- metric['min_limit'] = 6200.0
- if test_case == '031901':
- metric['min_limit'] = 7000.0
- if test_case == '032001':
- metric['min_limit'] = 7800.0
- if test_case == '032101':
- metric['min_limit'] = 8000.0
- if test_case == '032201':
- metric['min_limit'] = 9000.0
- if test_case == '032301':
- metric['min_limit'] = 10000.0
- if test_case == '032501':
- metric['min_limit'] = 11000.0
- if test_case == '032601':
- metric['min_limit'] = 12000.0
- if test_case == '032801':
- metric['min_limit'] = 12500.0
-
- if test_case == '035201':
- metric['min_limit'] = 14668.8
- if test_case == '036001':
- metric['min_limit'] = 25363.2
-
-
-
for i in range(0, nb_run):
- fname = 'log//'+test_case+'/run_'+str(i)+'/UE_exec_'+str(i)+'_.log'
+ fname = '..//log//'+test_case+'/run_'+str(i)+'/UE_exec_'+str(i)+'_.log'
args = {'metric' : metric,
'file' : fname }
- cell_synch_status = analyser.check_cell_synchro(fname)
- if cell_synch_status == 'CELL_SYNCH':
- print '!!!!!!!!!!!!!! Cell synchronized !!!!!!!!!!!'
- metric_checks_flag = 0
- else :
- print '!!!!!!!!!!!!!! Cell NOT NOT synchronized !!!!!!!!!!!'
+ # cell_synch_status = analyser.check_cell_synchro(fname)
+ # if cell_synch_status == 'CELL_SYNCH':
+ # print '!!!!!!!!!!!!!! Cell synchronized !!!!!!!!!!!'
+ # metric_checks_flag = 0
+ # else :
+ # print '!!!!!!!!!!!!!! Cell NOT NOT synchronized !!!!!!!!!!!'
-# metric_extracted = analyser.do_extract_metrics(args)
+# metrics_extracted = analyser.do_extract_metrics_new(args)
+
+
+ # de-xmlfy test report
+ xml_file = '..//log//'+test_case+'/test.'+test_case+'_ng.xml'
+ print xml_file
+
+ # test_result =
+
+
+ # test_results.append(test_result)
+
+ # xmlFile = logdir_local_testcase + '/test.' + testcasename + '.xml'
+ # xml="\n \n"
+ # write_file(xmlFile, xml, mode="w")
+
+ # xmlFile_ng = logdir_local_testcase + '/test.' + testcasename + '_ng.xml'
+ # xml_ng = xmlify(test_result, wrap=testcasename, indent=" ")
+ # write_file(xmlFile_ng, xml_ng, mode="w")
+
+
+
# print "min = "+ str( metric_extracted['metric_min'] )
# print "min_index = "+ str( metric_extracted['metric_min_index'] )
@@ -143,16 +145,27 @@ def main(args):
# print fname
# analyser.do_img_metrics(metric, metric_extracted, fname)
-# fname = 'log//'+test_case+'/run_'+str(i)+'/UE_traffic_'+str(i)+'_.log'
+ # fname = 'log//'+test_case+'/run_'+str(i)+'/UE_traffic_'+str(i)+'_.log'
-# args = {'file' : fname }
+ # args = {'file' : fname }
-# traffic_metrics = analyser.do_extract_traffic_metrics(args)
+ # traffic_metrics = analyser.do_extract_traffic_metrics(args)
-# fname= 'report/iperf_'+test_case+'_'+str(i)+'.png'
+ # fname= 'report/iperf_'+test_case+'_'+str(i)+'.png'
-# print fname
-# analyser.do_img_traffic(traffic_metrics, fname)
+ # print fname
+ # analyser.do_img_traffic(traffic_metrics, fname)
+
+
+ for test_result in test_results:
+ cmd = 'mkdir -p ' + report_dir + '/'+ test_result['testcase_name']
+ result = os.system(cmd)
+
+ report_file = report_dir + '/'+ test_result['testcase_name'] + '/'+ test_result['testcase_name']+ '_report.html'
+
+ analyser.create_test_report_detailed_html(test_result, report_file )
+
+ print test_result
diff --git a/cmake_targets/autotests/tools/lib_autotest_analyser.py b/cmake_targets/autotests/tools/lib_autotest_analyser.py
index 92dcc31e48..333bbd656e 100644
--- a/cmake_targets/autotests/tools/lib_autotest_analyser.py
+++ b/cmake_targets/autotests/tools/lib_autotest_analyser.py
@@ -41,7 +41,7 @@ from jinja2 import Environment, FileSystemLoader
PATH = os.path.dirname(os.path.abspath(__file__))
TEMPLATE_ENVIRONMENT = Environment(
autoescape=False,
- loader=FileSystemLoader(os.path.join(PATH, 'templates')),
+ loader=FileSystemLoader(os.path.join(PATH, '../templates')),
trim_blocks=False)
@@ -103,6 +103,129 @@ def do_extract_metrics(args):
}
return(ret)
+
+def do_extract_metrics_new(args):
+
+# print ""
+# print "do_extract_metrics ... "
+
+ fname = args['file']
+ metric = args['metric']
+ print(fname)
+ print 'metric id = ' + metric['id']
+ print 'metric regex = ' + metric['regex']
+
+
+
+ count = 0
+ mmin = 0
+ mmin_index = 0
+ mmax = 0
+ mmax_index = 0
+ mean = 0
+ median = 0
+
+ toto = [('id', 'S20'), ('metric', np.float), ('frame', np.int)]
+ print toto
+
+
+ np_format = []
+
+ for x in range(0, metric['nb_metric']):
+ np_format.append( ('id'+str(x), 'S20') )
+ np_format.append( ('metric'+str(x), np.float) )
+ np_format.append( ('uom'+str(x), 'S20') )
+ np_format.append( ('frame', np.int))
+
+ print np_format
+
+ output = np.fromregex(fname,metric['regex'], np_format)
+ print output
+ count = output['frame'].size
+ print count
+ if count > 0:
+
+
+ fontP = FontProperties()
+ fontP.set_size('small')
+
+ fig = plt.figure(1)
+ plt.figure(figsize=(10,10))
+
+ plot_xmax = np.amax(output['frame'])+np.amin(output['frame'])
+
+ for x in range(0, metric['nb_metric']):
+
+ metric_name = output['id'+str(x)][0]
+ metric_uom = output['uom'+str(x)][0]
+
+ mmin = np.amin(output['metric'+str(x)])
+ mmax = np.amax(output['metric'+str(x)])
+ mmean = np.mean(output['metric'+str(x)])
+ mmedian = np.median(output['metric'+str(x)])
+
+ plot_loc = 100*metric['nb_metric']+10+x+1
+
+ sbplt = plt.subplot(plot_loc)
+ sbplt.plot(output['frame'], output['metric'+str(x)], color='b' )
+ sbplt.set_title( metric_name+' ('+metric_uom+')')
+ if mmin < 0:
+ sbplot_ymin=mmin+mmin/10
+ else:
+ sbplot_ymin=0
+ sbplt.set_ylim(ymin=sbplot_ymin)
+ if mmax > 0:
+ sbplot_ymax=mmax+mmax/10
+ else:
+ sbplot_ymax=0
+ sbplt.set_ylim(ymax=sbplot_ymax)
+
+ sbplt.set_xlim(xmax=plot_xmax)
+ sbplt.set_xlim(xmin=0)
+ text='min: '+str(mmin)+'\nmax: '+str(mmax)+'\nmean: '+str(mmean)+'\nmedian: '+str(mmedian)
+ sbplt.text( plot_xmax+10,sbplot_ymin,text)
+ sbplt.set_xlabel('frame')
+ sbplt.set_ylabel(metric_name)
+
+ plt.tight_layout()
+
+ fname = "toto.png"
+
+# lgd = plt.legend(prop=fontP, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
+ mng = plt.get_current_fig_manager()
+ plt.savefig(fname, bbox_inches='tight')
+ plt.close()
+
+
+
+
+
+
+
+
+
+ mmin = np.amin(output['metric']);
+ mmin_index = np.argmin(output['metric']);
+ mmax = np.amax(output['metric']);
+ mmax_index = np.argmax(output['metric']);
+ mean = np.mean(output['metric']);
+ median = np.median(output['metric']);
+
+# print ( ( (metric['min_limit'] > output['metric']).sum() / float(output['metric'].size) ) * 100 )
+
+ ret = { 'metric_count' : count,
+ 'metric_buf' : output,
+
+
+ 'metric_min' : mmin,
+ 'metric_min_index' : mmin_index,
+ 'metric_max' : mmax,
+ 'metric_max_index' : mmax_index,
+ 'metric_mean' : mean,
+ 'metric_median' : median,
+ }
+ return(ret)
+
#
#
#
@@ -182,24 +305,30 @@ def do_img_metrics(metric_def, metric_data, fname):
# print output['metric'].size
plt.scatter(output['frame'], output['metric'], color='b', alpha=0.33, s = 1 , label=metric_def['id'])
- plt.plot([0, output['frame'][metric_data['metric_count']-1]],[ metric_def['min_limit'],metric_def['min_limit']], 'r-', lw=2, label='min limit') # Red straight line
+
+ if 'min_limit' in metric_def:
+ plt.plot([0, output['frame'][metric_data['metric_count']-1]],[ metric_def['min_limit'],metric_def['min_limit']], 'r-', lw=2, label='min limit') # Red straight line
- plt.title('Physical throughput ('+metric_def['unit_of_meas']+')')
+ plt.title(metric_def['id'] +' ('+metric_def['unit_of_meas']+')')
plt.xlabel('frame')
plt.ylabel(metric_def['id'])
# Set graphic minimum Y axis
# -------------------------
- if metric_data['metric_min'] == 0 :
- plt.ylim(ymin=-metric_def['min_limit']/10)
+ if metric_data['metric_min'] < 0:
+ plt.ylim(ymin=metric_data['metric_min']+metric_data['metric_min']/10)
else :
plt.ylim(ymin=0)
y_axis_max = 0
- if metric_data['metric_max'] > metric_def['min_limit']:
- y_axis_max =metric_data['metric_max']+metric_data['metric_max']/10
+ if 'min_limit' in metric_def:
+ if metric_data['metric_max'] > metric_def['min_limit']:
+ y_axis_max =metric_data['metric_max']+metric_data['metric_max']/10
+ else:
+ y_axis_max =metric_def['min_limit']+metric_def['min_limit']/10
else:
- y_axis_max =metric_def['min_limit']+metric_def['min_limit']/10
+ y_axis_max =metric_data['metric_max']+metric_data['metric_max']/10
+
plt.ylim(ymax=y_axis_max)
@@ -219,9 +348,6 @@ def do_img_metrics(metric_def, metric_data, fname):
def do_extract_traffic_metrics(args):
- print ""
- print "do_extract_traffic_metrics ... "
-
fname = args['file']
# print(fname)
@@ -325,7 +451,8 @@ def do_img_traffic(traffic_data, fname):
ax1.set_xlim(xmax=np.amax(output['interval_stop']))
text='min: '+str(traffic_data['bw_min'])+'\nmax: '+str(traffic_data['bw_max'])+'\nmean: '+str(traffic_data['bw_mean'])+'\nmedian: '+str(traffic_data['bw_median'])
ax1.text( np.amax(output['interval_stop'])+10,0,text)
-
+ ax1.set_xlabel('time (s)')
+ ax1.set_ylabel(' ')
ax2=plt.subplot(312)
plt.plot(output['interval_stop'], output['jitter'], color='b' )
@@ -334,6 +461,8 @@ def do_img_traffic(traffic_data, fname):
ax2.set_ylim(ymin=-1)
text='min: '+str(traffic_data['jitter_min'])+'\nmax: '+str(traffic_data['jitter_max'])+'\nmean: '+str(traffic_data['jitter_mean'])+'\nmedian: '+str(traffic_data['jitter_median'])
ax2.text( np.amax(output['interval_stop'])+10,0,text)
+ ax2.set_xlabel('time (s)')
+ ax2.set_ylabel(' ')
ax3=plt.subplot(313)
plt.plot(output['interval_stop'], output['rate_lost'], color='b')
@@ -342,10 +471,11 @@ def do_img_traffic(traffic_data, fname):
ax3.set_ylim(ymin=-1)
text='min: '+str(traffic_data['rl_min'])+'\nmax: '+str(traffic_data['rl_max'])+'\nmean: '+str(traffic_data['rl_mean'])+'\nmedian: '+str(traffic_data['rl_median'])
ax3.text( np.amax(output['interval_stop'])+10,0,text)
-
+ ax3.set_xlabel('time (s)')
+ ax3.set_ylabel(' ')
# plt.title('Physical throughput ('+metric_def['unit_of_meas']+')')
- plt.xlabel('time (s)')
+# plt.xlabel('time (s)')
# plt.ylabel(metric_def['id'])
# Set graphic minimum Y axis
@@ -365,7 +495,7 @@ def do_img_traffic(traffic_data, fname):
plt.tight_layout()
- lgd = plt.legend(prop=fontP, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
+# lgd = plt.legend(prop=fontP, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
mng = plt.get_current_fig_manager()
plt.savefig(fname, bbox_inches='tight')
plt.close()
@@ -395,7 +525,7 @@ def check_cell_synchro(fname):
m = re.search('AUTOTEST Cell Sync \:', line)
if m :
- print line
+ #print line
return 'CELL_SYNCH'
return 'CELL_NOT_SYNCH'
@@ -407,7 +537,7 @@ def check_exec_seg_fault(fname):
for line in f:
m = re.search('Segmentation fault', line)
if m :
- print line
+ #print line
return 'SEG_FAULT'
return 'NO_SEG_FAULT'
diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai
index b77a9baa56..0a64c0a672 100755
--- a/cmake_targets/build_oai
+++ b/cmake_targets/build_oai
@@ -35,6 +35,7 @@ source $THIS_SCRIPT_PATH/tools/build_helper
MSC_GEN="False"
XFORMS="True"
+FLEXRAN_AGENT_SB_IF="True"
PRINT_STATS="False"
VCD_TIMING="False"
DEADLINE_SCHEDULER_FLAG_USER="False"
@@ -53,6 +54,7 @@ BUILD_DOXYGEN=0
T_TRACER="False"
DISABLE_HARDWARE_DEPENDENCY="False"
CMAKE_BUILD_TYPE=""
+UE_AUTOTEST_TRACE="False"
trap handle_ctrl_c INT
function print_help() {
@@ -83,6 +85,8 @@ Options
Makes the UE specific parts (ue_ip, usim, nvram)
--RRH
Makes the RRH
+-a | --agent
+ Enables agent for software-defined control of the eNB
-r | --3gpp-release
default is Rel10,
Rel8 limits the implementation to 3GPP Release 8 version
@@ -127,6 +131,8 @@ Options
Enables the T tracer.
--disable-hardware-dependency
Disable HW dependency during installation
+--ue-autotest-trace
+ Enable specific traces for UE autotest framework
Usage (first build):
oaisim (eNB + UE): ./build_oai -I --oaisim -x --install-system-files
Eurecom EXMIMO + COTS UE : ./build_oai -I --eNB -x --install-system-files
@@ -169,6 +175,10 @@ function main() {
eNB=1
echo_info "Will compile eNB"
shift;;
+ -a | --agent)
+ FLEXRAN_AGENT=1
+ echo_info "Will compile eNB with agent support"
+ shift;;
--UE)
UE=1
echo_info "Will compile UE"
@@ -278,6 +288,10 @@ function main() {
echo_info "Disabling hardware dependency for compiling software"
DISABLE_HARDWARE_DEPENDENCY="True"
shift 1;;
+ --ue-autotest-trace)
+ UE_AUTOTEST_TRACE="True"
+ echo_info "Enabling autotest specific trace for UE"
+ shift 1;;
-h | --help)
print_help
exit 1;;
@@ -321,7 +335,7 @@ function main() {
#By default: EXMIMO: enable
if [ "$FORCE_DEADLINE_SCHEDULER_FLAG_USER" = "" ]; then
if [ "$HW" = "EXMIMO" ] ; then
- DEADLINE_SCHEDULER_FLAG_USER="False"
+ DEADLINE_SCHEDULER_FLAG_USER="True"
elif [ "$HW" = "ETHERNET" ] ; then
DEADLINE_SCHEDULER_FLAG_USER="False"
elif [ "$HW" = "OAI_USRP" ] ; then
@@ -439,6 +453,9 @@ function main() {
echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file
echo "set ( CFLAGS_PROCESSOR_USER \"$CFLAGS_PROCESSOR_USER\" )" >> $cmake_file
echo "set ( XFORMS $XFORMS )" >> $cmake_file
+ if [ "$FLEXRAN_AGENT" = "1" ] ; then
+ echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file
+ fi
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
echo "set ( RF_BOARD \"${HW}\")" >> $cmake_file
@@ -447,6 +464,7 @@ function main() {
echo "set (DEADLINE_SCHEDULER \"${DEADLINE_SCHEDULER_FLAG_USER}\" )" >>$cmake_file
echo "set (CPU_AFFINITY \"${CPU_AFFINITY_FLAG_USER}\" )" >>$cmake_file
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
+ echo "set (UE_AUTOTEST_TRACE $UE_AUTOTEST_TRACE)" >> $cmake_file
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
cd $DIR/$lte_build_dir/build
cmake ..
@@ -581,6 +599,9 @@ function main() {
echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file
echo "set ( CFLAGS_PROCESSOR_USER \"$CFLAGS_PROCESSOR_USER\" )" >> $cmake_file
echo "set ( XFORMS $XFORMS )" >> $cmake_file
+ if [ "$FLEXRAN_AGENT" = "1" ] ; then
+ echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file
+ fi
echo "set ( PRINT_STATS $PRINT_STATS )" >> $cmake_file
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
@@ -649,6 +670,9 @@ function main() {
cp $DIR/oaisim_mme_build_oai/CMakeLists.template $cmake_file
echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file
echo "set ( XFORMS $XFORMS )" >> $cmake_file
+ if [ "$FLEXRAN_AGENT" = "1" ] ; then
+ echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file
+ fi
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
diff --git a/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template b/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
index 6d8fc6d26a..8e1670ea43 100644
--- a/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
+++ b/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
@@ -1,6 +1,5 @@
cmake_minimum_required(VERSION 2.8)
-set ( CMAKE_BUILD_TYPE "RelWithDebInfo" )
set ( ADDR_CONF False )
set ( DEBUG_OMG False )
set ( DISABLE_XER_PRINT False )
@@ -48,7 +47,7 @@ set ( NEW_FFT True )
set ( NO_RRM True )
set ( OAI_EMU True )
set ( OAISIM True )
-set ( OAI_NW_DRIVER_TYPE_ETHERNET True )
+set ( OAI_NW_DRIVER_TYPE_ETHERNET False )
set ( OAI_NW_DRIVER_USE_NETLINK True )
set ( OPENAIR1 True )
set ( OPENAIR2 True )
diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper
index c5f2b87704..448d54f334 100755
--- a/cmake_targets/tools/build_helper
+++ b/cmake_targets/tools/build_helper
@@ -163,6 +163,42 @@ compilations() {
# External packages installers
############################################
+install_protobuf_from_source(){
+ protobuf_install_log=$OPENAIR_DIR/cmake_targets/log/protobuf_install_log.txt
+ echo_info "\nInstalling Google Protobuf from sources. The log file for Protobuf installation is here: $protobuf_install_log "
+ (
+ cd /tmp
+ echo "Downloading protobuf"
+ rm -rf /tmp/protobuf-2.6.1.tar.gz* /tmp/protobuf-2.6.1
+ wget https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz
+ tar -xzvf protobuf-2.6.1.tar.gz
+ cd protobuf-2.6.1/
+ ./configure
+ echo "Compiling protobuf"
+ make -j`nproc`
+ $SUDO make install
+ $SUDO ldconfig
+ ) >& $protobuf_install_log
+}
+
+install_protobuf_c_from_source(){
+ protobuf_c_install_log=$OPENAIR_DIR/cmake_targets/log/protobuf_c_install_log.txt
+ echo_info "\nInstalling Google Protobuf_C from sources. The log file for Protobuf_C installation is here: $protobuf_c_install_log "
+ (
+ cd /tmp
+ echo "Downloading protobuf-c"
+ rm -rf /tmp/protobuf-c
+ git clone https://github.com/protobuf-c/protobuf-c.git
+ cd protobuf-c
+ ./autogen.sh
+ ./configure
+ echo "Compiling protobuf-c"
+ make -j`nproc`
+ $SUDO make install
+ $SUDO ldconfig
+ ) >& $protobuf_c_install_log
+}
+
check_install_usrp_uhd_driver(){
#first we remove old installation
$SUDO apt-get remove -y uhd || true
@@ -324,6 +360,7 @@ check_install_oai_software() {
xmlstarlet \
python-pip \
pydb \
+ libyaml-dev \
wget
$SUDO update-alternatives --set liblapack.so /usr/lib/atlas-base/atlas/liblapack.so
@@ -337,6 +374,10 @@ check_install_oai_software() {
$SUDO apt-get install -y libgnutls-dev
install_asn1c_from_source
+ $SUDO rm -fr /opt/ssh
+ $SUDO git clone https://gist.github.com/2190472.git /opt/ssh
+ install_protobuf_from_source
+ install_protobuf_c_from_source
}
### Remove Nettle installation which was done from sources
@@ -361,6 +402,7 @@ remove_nettle_from_source() {
cd nettle-2.5/
./configure --disable-openssl --enable-shared --prefix=/usr
$SUDO make uninstall || true
+ $SUDO ldconfig
) >& $nettle_uninstall_log
}
@@ -384,6 +426,7 @@ remove_gnutls_from_source(){
cd gnutls-3.1.23/
./configure --prefix=/usr
$SUDO make uninstall || true
+ $SUDO ldconfig
)>& $gnutls_uninstall_log
}
@@ -398,6 +441,7 @@ install_asn1c_from_source(){
make -j`nproc`
$SUDO make install
cd -
+ $SUDO ldconfig
) > $asn1_install_log 2>&1
}
diff --git a/cmake_targets/tools/generate_protobuf b/cmake_targets/tools/generate_protobuf
new file mode 100755
index 0000000000..5c1b523f8c
--- /dev/null
+++ b/cmake_targets/tools/generate_protobuf
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+function main()
+{
+mkdir -p $1
+
+#echo generate protobuf messages inside $1 $2
+
+c_out=$1
+shift
+proto_path=$1
+shift
+
+protoc-c --c_out=$c_out --proto_path=$proto_path $*
+#protoc --cpp_out=$c_out --proto_path=$proto_path $*
+
+}
+
+main "$@"
diff --git a/cmake_targets/tools/make_agent_cache b/cmake_targets/tools/make_agent_cache
new file mode 100755
index 0000000000..d2eab20fc0
--- /dev/null
+++ b/cmake_targets/tools/make_agent_cache
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+CACHE_DIR=/mnt/oai_agent_cache
+
+if [ ! -d $CACHE_DIR ]; then
+ echo "Creating cache dir in $CACHE_DIR"
+ sudo mkdir $CACHE_DIR
+fi
+
+if grep -qs "$CACHE_DIR" /proc/mounts; then
+ echo "Agent cache is already mounted"
+else
+ echo "Agent cache was not mounted"
+ echo "Mounting..."
+ sudo mount -o size=100m -t tmpfs none "$CACHE_DIR"
+ if [ $? -eq 0 ]; then
+ echo "Mount success"
+ else
+ echo "Something went wrong with the mount"
+ fi
+fi
diff --git a/common/utils/Makefile.inc b/common/utils/Makefile.inc
index b7a1c82379..33c126b8d7 100644
--- a/common/utils/Makefile.inc
+++ b/common/utils/Makefile.inc
@@ -5,14 +5,14 @@ linux := $(shell if [ `uname` = "Linux" ] ; then echo "1" ; else echo "0" ; fi)
CFLAGS += -std=gnu99
-#CFLAGS += -Wall -g -ggdb -Wstrict-prototypes -fno-strict-aliasing
+CFLAGS += -Wall -g -ggdb -Wstrict-prototypes -fno-strict-aliasing
# Need to force this option because default kernel module builder is wrong
CFLAGS += $(call cc-option,-mpreferred-stack-boundary=4)
#For performance, if some option doesn't exist in all gcc versions, use $(call cc-option,MY_OPTION)
-CFLAGS += -O2
-CFLAGS += -funroll-loops
+#CFLAGS += -O2
+#CFLAGS += -funroll-loops
CFLAGS += -Wno-packed-bitfield-compat
# This is the minimum CPU faetures for OAI
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index 2d2ee3c489..d1807080bc 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -423,6 +423,27 @@ ID = LEGACY_ENB_APP_TRACE
GROUP = ALL:LEGACY_ENB_APP:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
+ID = LEGACY_FLEXRAN_AGENT_INFO
+ DESC = FLEXRAN_AGENT legacy logs - info level
+ GROUP = ALL:LEGACY_FLEXRAN_AGENT:LEGACY_GROUP_INFO:LEGACY
+ FORMAT = string,log
+ID = LEGACY_FLEXRAN_AGENT_ERROR
+ DESC = FLEXRAN_AGENT legacy logs - error level
+ GROUP = ALL:LEGACY_FLEXRAN_AGENT:LEGACY_GROUP_ERROR:LEGACY
+ FORMAT = string,log
+ID = LEGACY_FLEXRAN_AGENT_WARNING
+ DESC = FLEXRAN_AGENT legacy logs - warning level
+ GROUP = ALL:LEGACY_FLEXRAN_AGENT:LEGACY_GROUP_WARNING:LEGACY
+ FORMAT = string,log
+ID = LEGACY_FLEXRAN_AGENT_DEBUG
+ DESC = FLEXRAN_AGENT legacy logs - debug level
+ GROUP = ALL:LEGACY_FLEXRAN_AGENT:LEGACY_GROUP_DEBUG:LEGACY
+ FORMAT = string,log
+ID = LEGACY_FLEXRAN_AGENT_TRACE
+ DESC = FLEXRAN_AGENT legacy logs - trace level
+ GROUP = ALL:LEGACY_FLEXRAN_AGENT:LEGACY_GROUP_TRACE:LEGACY
+ FORMAT = string,log
+
ID = LEGACY_SCTP_INFO
DESC = SCTP legacy logs - info level
GROUP = ALL:LEGACY_SCTP:LEGACY_GROUP_INFO:LEGACY
@@ -1246,6 +1267,14 @@ ID = VCD_VARIABLE_UE0_SFN7
DESC = VCD variable UE0_SFN7
GROUP = ALL:VCD:ENB:VCD_VARIABLE
FORMAT = ulong,value
+ID = VCD_VARIABLE_UE0_TRX_READ_NS
+ DESC = VCD variable UE0_TRX_READ_NS
+ GROUP = ALL:VCD:ENB:VCD_VARIABLE
+ FORMAT = ulong,value
+ID = VCD_VARIABLE_UE0_TRX_WRITE_NS
+ DESC = VCD variable UE0_TRX_WRITE_NS
+ GROUP = ALL:VCD:ENB:VCD_VARIABLE
+ FORMAT = ulong,value
#functions
@@ -1289,6 +1318,50 @@ ID = VCD_FUNCTION_UE_THREAD_RXTX1
DESC = VCD function UE_THREAD_RXTX1
GROUP = ALL:VCD:UE:VCD_FUNCTION
FORMAT = int,value
+ID = VCD_FUNCTION_TRX_READ_SF9
+ DESC = VCD function TRX_READ_SF9
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_TRX_WRITE_SF9
+ DESC = VCD function TRX_WRITE_SF9
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_UE_SIGNAL_COND_RXTX
+ DESC = VCD function UE_SIGNAL_COND_RXTX
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_UE_WAIT_COND_RXTX0
+ DESC = VCD function UE_WAIT_COND_RXTX0
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_UE_WAIT_COND_RXTX1
+ DESC = VCD function UE_WAIT_COND_RXTX1
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0
+ DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT1
+ DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT1
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0
+ DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT1
+ DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT1
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT0
+ DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT0
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT1
+ DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT1
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
ID = VCD_FUNCTION_eNB_TX
DESC = VCD function eNB_TX
GROUP = ALL:VCD:ENB:VCD_FUNCTION
@@ -1381,8 +1454,8 @@ ID = VCD_FUNCTION_PHY_PROCEDURES_ENB_RX_UESPEC1
DESC = VCD function PHY_PROCEDURES_ENB_RX_UESPEC1
GROUP = ALL:VCD:ENB:VCD_FUNCTION
FORMAT = int,value
-ID = VCD_FUNCTION_PHY_PROCEDURES_ENB_SLOT_FEP
- DESC = VCD function PHY_PROCEDURES_ENB_SLOT_FEP
+ID = VCD_FUNCTION_ENB_SLOT_FEP
+ DESC = VCD function ENB_SLOT_FEP
GROUP = ALL:VCD:ENB:VCD_FUNCTION
FORMAT = int,value
ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX
@@ -1393,6 +1466,26 @@ ID = VCD_FUNCTION_PHY_PROCEDURES_UE_RX
DESC = VCD function PHY_PROCEDURES_UE_RX
GROUP = ALL:VCD:UE:VCD_FUNCTION
FORMAT = int,value
+ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC
+ DESC = VCD function PHY_PROCEDURES_UE_TX_ULSCH_UESPEC
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX_PUCCH
+ DESC = VCD function PHY_PROCEDURES_UE_TX_PUCCH
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX_ULSCH_COMMON
+ DESC = VCD function PHY_PROCEDURES_UE_TX_ULSCH_COMMON
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX_PRACH
+ DESC = VCD function PHY_PROCEDURES_UE_TX_PRACH
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX_ULSCH_RAR
+ DESC = VCD function PHY_PROCEDURES_UE_TX_ULSCH_RAR
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
ID = VCD_FUNCTION_PHY_PROCEDURES_ENB_LTE
DESC = VCD function PHY_PROCEDURES_ENB_LTE
GROUP = ALL:VCD:ENB:VCD_FUNCTION
@@ -1481,6 +1574,22 @@ ID = VCD_FUNCTION_RX_PHICH
DESC = VCD function RX_PHICH
GROUP = ALL:VCD:ENB:VCD_FUNCTION
FORMAT = int,value
+ID = VCD_FUNCTION_PDSCH_PROC
+ DESC = VCD function PDSCH_PROC
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_PDSCH_PROC_SI
+ DESC = VCD function PDSCH_PROC_SI
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_PDSCH_PROC_P
+ DESC = VCD function PDSCH_PROC_P
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_PDSCH_PROC_RA
+ DESC = VCD function PDSCH_PROC_RA
+ GROUP = ALL:VCD:UE:VCD_FUNCTION
+ FORMAT = int,value
ID = VCD_FUNCTION_PHY_UE_CONFIG_SIB2
DESC = VCD function PHY_UE_CONFIG_SIB2
GROUP = ALL:VCD:UE:VCD_FUNCTION
@@ -1585,6 +1694,14 @@ ID = VCD_FUNCTION_ENB_DLSCH_SCRAMBLING
DESC = VCD function ENB_DLSCH_SCRAMBLING
GROUP = ALL:VCD:ENB:VCD_FUNCTION
FORMAT = int,value
+ID = VCD_FUNCTION_ENB_BEAM_PRECODING
+ DESC = VCD function ENB_BEAM_PRECODING
+ GROUP = ALL:VCD:ENB:VCD_FUNCTION
+ FORMAT = int,value
+ID = VCD_FUNCTION_ENB_OFDM_MODULATION
+ DESC = VCD function ENB_OFDM_MODULATION
+ GROUP = ALL:VCD:ENB:VCD_FUNCTION
+ FORMAT = int,value
ID = VCD_FUNCTION_MACPHY_INIT
DESC = VCD function MACPHY_INIT
GROUP = ALL:VCD:ENB:VCD_FUNCTION
@@ -1697,6 +1814,10 @@ ID = VCD_FUNCTION_RLC_DATA_REQ
DESC = VCD function RLC_DATA_REQ
GROUP = ALL:VCD:ENB:VCD_FUNCTION
FORMAT = int,value
+ID = VCD_FUNCTION_RLC_DATA_IND
+ DESC = VCD function RLC_DATA_IND
+ GROUP = ALL:VCD:ENB:VCD_FUNCTION
+ FORMAT = int,value
ID = VCD_FUNCTION_MAC_RLC_STATUS_IND
DESC = VCD function MAC_RLC_STATUS_IND
GROUP = ALL:VCD:ENB:VCD_FUNCTION
diff --git a/common/utils/collection/tree.h b/common/utils/collection/tree.h
index 8e4e35c408..c9df686fbb 100755
--- a/common/utils/collection/tree.h
+++ b/common/utils/collection/tree.h
@@ -1,4 +1,8 @@
-/*
+/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
+/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
+/* $FreeBSD$ */
+
+/*-
* Copyright 2002 Niels Provos
* All rights reserved.
*
@@ -26,6 +30,8 @@
#ifndef _SYS_TREE_H_
#define _SYS_TREE_H_
+#include
+
/*
* This file defines data structures for different types of trees:
* splay trees and red-black trees.
@@ -63,7 +69,7 @@ struct name { \
#define SPLAY_INIT(root) do { \
(root)->sph_root = NULL; \
-} while (0)
+} while (/*CONSTCOND*/ 0)
#define SPLAY_ENTRY(type) \
struct { \
@@ -81,32 +87,32 @@ struct { \
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
-} while (0)
+} while (/*CONSTCOND*/ 0)
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
-} while (0)
+} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKLEFT(head, tmp, field) do { \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
-} while (0)
+} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
-} while (0)
+} while (/*CONSTCOND*/ 0)
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
-} while (0)
+} while (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */
@@ -207,7 +213,7 @@ name##_SPLAY(struct name *head, struct type *elm) \
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
- while ((__comp = (cmp)(elm, (head)->sph_root))) { \
+ while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
@@ -286,7 +292,7 @@ void name##_SPLAY_MINMAX(struct name *head, int __comp) \
(x) != NULL; \
(x) = SPLAY_NEXT(name, head, x))
-/* Macros that define a red-back tree */
+/* Macros that define a red-black tree */
#define RB_HEAD(name, type) \
struct name { \
struct type *rbh_root; /* root of the tree */ \
@@ -297,7 +303,7 @@ struct name { \
#define RB_INIT(root) do { \
(root)->rbh_root = NULL; \
-} while (0)
+} while (/*CONSTCOND*/ 0)
#define RB_BLACK 0
#define RB_RED 1
@@ -320,24 +326,24 @@ struct { \
RB_PARENT(elm, field) = parent; \
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
RB_COLOR(elm, field) = RB_RED; \
-} while (0)
+} while (/*CONSTCOND*/ 0)
#define RB_SET_BLACKRED(black, red, field) do { \
RB_COLOR(black, field) = RB_BLACK; \
RB_COLOR(red, field) = RB_RED; \
-} while (0)
+} while (/*CONSTCOND*/ 0)
#ifndef RB_AUGMENT
-#define RB_AUGMENT(x)
+#define RB_AUGMENT(x) do {} while (0)
#endif
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
(tmp) = RB_RIGHT(elm, field); \
- if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \
+ if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
- if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
+ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
@@ -349,15 +355,15 @@ struct { \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
-} while (0)
+} while (/*CONSTCOND*/ 0)
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
(tmp) = RB_LEFT(elm, field); \
- if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \
+ if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
- if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
+ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
@@ -369,28 +375,66 @@ struct { \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
-} while (0)
+} while (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */
-#define RB_PROTOTYPE(name, type, field, cmp) \
-void name##_RB_INSERT_COLOR(struct name *, struct type *); \
-void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
-struct type *name##_RB_REMOVE(struct name *, struct type *); \
-struct type *name##_RB_INSERT(struct name *, struct type *); \
-struct type *name##_RB_FIND(struct name *, struct type *); \
-struct type *name##_RB_NEXT(struct type *); \
-struct type *name##_RB_MINMAX(struct name *, int); \
- \
+#define RB_PROTOTYPE(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
+#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
+#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
+ RB_PROTOTYPE_INSERT_COLOR(name, type, attr); \
+ RB_PROTOTYPE_REMOVE_COLOR(name, type, attr); \
+ RB_PROTOTYPE_INSERT(name, type, attr); \
+ RB_PROTOTYPE_REMOVE(name, type, attr); \
+ RB_PROTOTYPE_FIND(name, type, attr); \
+ RB_PROTOTYPE_NFIND(name, type, attr); \
+ RB_PROTOTYPE_NEXT(name, type, attr); \
+ RB_PROTOTYPE_PREV(name, type, attr); \
+ RB_PROTOTYPE_MINMAX(name, type, attr);
+#define RB_PROTOTYPE_INSERT_COLOR(name, type, attr) \
+ attr void name##_RB_INSERT_COLOR(struct name *, struct type *)
+#define RB_PROTOTYPE_REMOVE_COLOR(name, type, attr) \
+ attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *)
+#define RB_PROTOTYPE_REMOVE(name, type, attr) \
+ attr struct type *name##_RB_REMOVE(struct name *, struct type *)
+#define RB_PROTOTYPE_INSERT(name, type, attr) \
+ attr struct type *name##_RB_INSERT(struct name *, struct type *)
+#define RB_PROTOTYPE_FIND(name, type, attr) \
+ attr struct type *name##_RB_FIND(struct name *, struct type *)
+#define RB_PROTOTYPE_NFIND(name, type, attr) \
+ attr struct type *name##_RB_NFIND(struct name *, struct type *)
+#define RB_PROTOTYPE_NEXT(name, type, attr) \
+ attr struct type *name##_RB_NEXT(struct type *)
+#define RB_PROTOTYPE_PREV(name, type, attr) \
+ attr struct type *name##_RB_PREV(struct type *)
+#define RB_PROTOTYPE_MINMAX(name, type, attr) \
+ attr struct type *name##_RB_MINMAX(struct name *, int)
/* Main rb operation.
* Moves node close to the key of elm to top
*/
-#define RB_GENERATE(name, type, field, cmp) \
-void \
+#define RB_GENERATE(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp,)
+#define RB_GENERATE_STATIC(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
+#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
+ RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
+ RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
+ RB_GENERATE_INSERT(name, type, field, cmp, attr) \
+ RB_GENERATE_REMOVE(name, type, field, attr) \
+ RB_GENERATE_FIND(name, type, field, cmp, attr) \
+ RB_GENERATE_NFIND(name, type, field, cmp, attr) \
+ RB_GENERATE_NEXT(name, type, field, attr) \
+ RB_GENERATE_PREV(name, type, field, attr) \
+ RB_GENERATE_MINMAX(name, type, field, attr)
+
+#define RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
+attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
struct type *parent, *gparent, *tmp; \
- while ((parent = RB_PARENT(elm, field)) && \
+ while ((parent = RB_PARENT(elm, field)) != NULL && \
RB_COLOR(parent, field) == RB_RED) { \
gparent = RB_PARENT(parent, field); \
if (parent == RB_LEFT(gparent, field)) { \
@@ -428,9 +472,10 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
} \
} \
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
-} \
- \
-void \
+}
+
+#define RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
+attr void \
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
{ \
struct type *tmp; \
@@ -454,7 +499,8 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
if (RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
struct type *oleft; \
- if ((oleft = RB_LEFT(tmp, field)))\
+ if ((oleft = RB_LEFT(tmp, field)) \
+ != NULL) \
RB_COLOR(oleft, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
@@ -486,7 +532,8 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
if (RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
struct type *oright; \
- if ((oright = RB_RIGHT(tmp, field)))\
+ if ((oright = RB_RIGHT(tmp, field)) \
+ != NULL) \
RB_COLOR(oright, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_LEFT(head, tmp, oright, field);\
@@ -504,9 +551,10 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
} \
if (elm) \
RB_COLOR(elm, field) = RB_BLACK; \
-} \
- \
-struct type * \
+}
+
+#define RB_GENERATE_REMOVE(name, type, field, attr) \
+attr struct type * \
name##_RB_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *child, *parent, *old = elm; \
@@ -518,7 +566,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
else { \
struct type *left; \
elm = RB_RIGHT(elm, field); \
- while ((left = RB_LEFT(elm, field))) \
+ while ((left = RB_LEFT(elm, field)) != NULL) \
elm = left; \
child = RB_RIGHT(elm, field); \
parent = RB_PARENT(elm, field); \
@@ -551,7 +599,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
left = parent; \
do { \
RB_AUGMENT(left); \
- } while ((left = RB_PARENT(left, field))); \
+ } while ((left = RB_PARENT(left, field)) != NULL); \
} \
goto color; \
} \
@@ -572,9 +620,10 @@ color: \
name##_RB_REMOVE_COLOR(head, parent, child); \
return (old); \
} \
- \
+
+#define RB_GENERATE_INSERT(name, type, field, cmp, attr) \
/* Inserts a node into the RB tree */ \
-struct type * \
+attr struct type * \
name##_RB_INSERT(struct name *head, struct type *elm) \
{ \
struct type *tmp; \
@@ -599,15 +648,14 @@ name##_RB_INSERT(struct name *head, struct type *elm) \
RB_RIGHT(parent, field) = elm; \
RB_AUGMENT(parent); \
} else \
- { \
RB_ROOT(head) = elm; \
- } \
name##_RB_INSERT_COLOR(head, elm); \
return (NULL); \
-} \
- \
+}
+
+#define RB_GENERATE_FIND(name, type, field, cmp, attr) \
/* Finds the node with the same key as elm */ \
-struct type * \
+attr struct type * \
name##_RB_FIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
@@ -622,9 +670,33 @@ name##_RB_FIND(struct name *head, struct type *elm) \
return (tmp); \
} \
return (NULL); \
-} \
- \
-struct type * \
+}
+
+#define RB_GENERATE_NFIND(name, type, field, cmp, attr) \
+/* Finds the first node greater than or equal to the search key */ \
+attr struct type * \
+name##_RB_NFIND(struct name *head, struct type *elm) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ struct type *res = NULL; \
+ int comp; \
+ while (tmp) { \
+ comp = cmp(elm, tmp); \
+ if (comp < 0) { \
+ res = tmp; \
+ tmp = RB_LEFT(tmp, field); \
+ } \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ return (res); \
+}
+
+#define RB_GENERATE_NEXT(name, type, field, attr) \
+/* ARGSUSED */ \
+attr struct type * \
name##_RB_NEXT(struct type *elm) \
{ \
if (RB_RIGHT(elm, field)) { \
@@ -643,9 +715,33 @@ name##_RB_NEXT(struct type *elm) \
} \
} \
return (elm); \
-} \
- \
-struct type * \
+}
+
+#define RB_GENERATE_PREV(name, type, field, attr) \
+/* ARGSUSED */ \
+attr struct type * \
+name##_RB_PREV(struct type *elm) \
+{ \
+ if (RB_LEFT(elm, field)) { \
+ elm = RB_LEFT(elm, field); \
+ while (RB_RIGHT(elm, field)) \
+ elm = RB_RIGHT(elm, field); \
+ } else { \
+ if (RB_PARENT(elm, field) && \
+ (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
+ elm = RB_PARENT(elm, field); \
+ else { \
+ while (RB_PARENT(elm, field) && \
+ (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
+ elm = RB_PARENT(elm, field); \
+ elm = RB_PARENT(elm, field); \
+ } \
+ } \
+ return (elm); \
+}
+
+#define RB_GENERATE_MINMAX(name, type, field, attr) \
+attr struct type * \
name##_RB_MINMAX(struct name *head, int val) \
{ \
struct type *tmp = RB_ROOT(head); \
@@ -666,7 +762,9 @@ name##_RB_MINMAX(struct name *head, int val) \
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
+#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
+#define RB_PREV(name, x, y) name##_RB_PREV(y)
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
@@ -675,4 +773,29 @@ name##_RB_MINMAX(struct name *head, int val) \
(x) != NULL; \
(x) = name##_RB_NEXT(x))
+#define RB_FOREACH_FROM(x, name, y) \
+ for ((x) = (y); \
+ ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_SAFE(x, name, head, y) \
+ for ((x) = RB_MIN(name, head); \
+ ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_REVERSE(x, name, head) \
+ for ((x) = RB_MAX(name, head); \
+ (x) != NULL; \
+ (x) = name##_RB_PREV(x))
+
+#define RB_FOREACH_REVERSE_FROM(x, name, y) \
+ for ((x) = (y); \
+ ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
+ for ((x) = RB_MAX(name, head); \
+ ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
+ (x) = (y))
+
#endif /* _SYS_TREE_H_ */
diff --git a/common/utils/itti/timer.c b/common/utils/itti/timer.c
index 5486c76d83..c180cfcda4 100644
--- a/common/utils/itti/timer.c
+++ b/common/utils/itti/timer.c
@@ -86,8 +86,8 @@ int timer_handle_signal(siginfo_t *info)
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);
-
+ 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);
@@ -120,6 +120,10 @@ int timer_handle_signal(siginfo_t *info)
return -1;
}
+#if defined(ENB_AGENT_SB_IF)
+
+#endif
+
return 0;
}
diff --git a/maketags b/maketags
index 4dff87bf76..361adc5d67 100755
--- a/maketags
+++ b/maketags
@@ -1,3 +1,4 @@
#!/bin/sh
echo "building ctags for openair1 and openair2 ..."
ctags -e -R --exclude=openair1/DOCS/ --exclude=openair2/DOCS/ --exclude=openair2/RRC/CELLULAR/ --exclude=openair2/NAS/DRIVER/CELLULAR/ --exclude=openair2/SIMULATION/ --exclude=targets/DOCS/ --exclude=targets/PROJECTS/ openair1 openair2 openair3 targets cmake_targets common
+
diff --git a/openair1/PHY/CODING/lte_segmentation.c b/openair1/PHY/CODING/lte_segmentation.c
index 746344a6ac..04056c4c9e 100644
--- a/openair1/PHY/CODING/lte_segmentation.c
+++ b/openair1/PHY/CODING/lte_segmentation.c
@@ -60,7 +60,7 @@ int lte_segmentation(unsigned char *input_buffer,
}
if ((*C)>MAX_NUM_DLSCH_SEGMENTS) {
- msg("lte_segmentation.c: too many segments %d\n",*C);
+ LOG_E(PHY,"lte_segmentation.c: too many segments %d, B %d, L %d, Bprime %d\n",*C,B,L,Bprime);
return(-1);
}
diff --git a/openair1/PHY/INIT/defs.h b/openair1/PHY/INIT/defs.h
index 1874c4e8c7..27303cb57d 100644
--- a/openair1/PHY/INIT/defs.h
+++ b/openair1/PHY/INIT/defs.h
@@ -206,7 +206,19 @@ void phy_config_dedicated_ue(module_id_t Mod_id,
uint8_t CH_index,
struct PhysicalConfigDedicated *physicalConfigDedicated);
+/*!
+\fn void phy_config_harq_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t CH_index,
+ uint16_t max_harq_tx)
+\brief Configure UE UL max harq Tx.
+\details Invoked upon reception of RRCConnectionSetup or RRCConnectionReconfiguration from eNB.
+@param Mod_id Instance ID for eNB
+@param CC_id Component Carrier index
+@param CH_index Index of eNB for this configuration
+@param max_harq_tx max harq tx information
+ */
+void phy_config_harq_ue(module_id_t Mod_id,int CC_id,uint8_t CH_index,
+ uint16_t max_harq_tx);
/**
\brief Configure UE MBSFN common parameters.
\details Invoked upon reception of SIB13 from eNB.
@@ -292,7 +304,8 @@ void phy_init_lte_top(LTE_DL_FRAME_PARMS *lte_frame_parms);
//void copy_lte_parms_to_phy_framing(LTE_DL_FRAME_PARMS *frame_parm, PHY_FRAMING *phy_framing);
-void lte_param_init(unsigned char N_tx,
+void lte_param_init(unsigned char N_tx_port_eNB,
+ unsigned char N_tx,
unsigned char N_rx,
unsigned char transmission_mode,
uint8_t extended_prefix_flag,
@@ -327,7 +340,8 @@ void phy_cleanup(void);
int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf);
void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms);
-void lte_param_init(unsigned char N_tx,
+void lte_param_init(unsigned char N_tx_port_eNB,
+ unsigned char N_tx_phy,
unsigned char N_rx,
unsigned char transmission_mode,
uint8_t extended_prefix_flag,
@@ -338,7 +352,6 @@ void lte_param_init(unsigned char N_tx,
uint8_t threequarter_fs,
uint8_t osf,
uint32_t perfect_ce);
-
/** @} */
#endif
diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c
index 3fb1d0c26b..17338d85b5 100644
--- a/openair1/PHY/INIT/lte_init.c
+++ b/openair1/PHY/INIT/lte_init.c
@@ -46,13 +46,12 @@ void phy_config_mib(LTE_DL_FRAME_PARMS *fp,
uint8_t p_eNB,
PHICH_CONFIG_COMMON *phich_config)
{
-
fp->N_RB_DL = N_RB_DL;
fp->Nid_cell = Nid_cell;
fp->nushift = Nid_cell%6;
fp->Ncp = Ncp;
fp->frame_type = frame_type;
- fp->nb_antennas_tx_eNB = p_eNB;
+ fp->nb_antenna_ports_eNB = p_eNB;
fp->phich_config_common.phich_resource = phich_config->phich_resource;
fp->phich_config_common.phich_duration = phich_config->phich_duration;
}
@@ -482,6 +481,26 @@ void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *eNB)
}
+ if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated) {
+ if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
+
+ eNB->soundingrs_ul_config_dedicated[UE_id].duration = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.duration;
+ eNB->soundingrs_ul_config_dedicated[UE_id].cyclicShift = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;
+ eNB->soundingrs_ul_config_dedicated[UE_id].freqDomainPosition = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
+ eNB->soundingrs_ul_config_dedicated[UE_id].srs_Bandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
+ eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
+ eNB->soundingrs_ul_config_dedicated[UE_id].srs_HoppingBandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;
+ eNB->soundingrs_ul_config_dedicated[UE_id].transmissionComb = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
+
+
+ LOG_D(PHY,"soundingrs_ul_config_dedicated.srs_ConfigIndex %d\n",eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex);
+
+ }
+
+ LOG_D(PHY,"------------------------------------------------------------\n");
+
+ }
+
eNB->physicalConfigDedicated[UE_id] = NULL;
}
}
@@ -664,6 +683,7 @@ void phy_config_dedicated_eNB(uint8_t Mod_id,
eNB->transmission_mode[UE_id] = 6;
break;
case AntennaInfoDedicated__transmissionMode_tm7:
+ lte_gold_ue_spec_port5(eNB->lte_gold_uespec_port5_table[0],eNB->frame_parms.Nid_cell,rnti);
eNB->transmission_mode[UE_id] = 7;
break;
default:
@@ -726,6 +746,14 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id,
}
#endif
+void phy_config_harq_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
+ uint16_t max_harq_tx )
+{
+
+ PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id];
+ phy_vars_ue->ulsch[eNB_id]->Mlimit = max_harq_tx;
+}
+
void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
struct PhysicalConfigDedicated *physicalConfigDedicated )
{
@@ -742,7 +770,8 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
phy_vars_ue->dlsch_received_last[eNB_id]=0;
phy_vars_ue->dlsch_fer[eNB_id]=0;
-
+ phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = -1;
+ phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = -1;
if (physicalConfigDedicated) {
LOG_D(PHY,"[UE %d] Received physicalConfigDedicated from eNB %d\n",Mod_id, eNB_id);
@@ -806,7 +835,6 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
if (physicalConfigDedicated->antennaInfo) {
phy_vars_ue->transmission_mode[eNB_id] = 1+(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode);
LOG_D(PHY,"Transmission Mode %d\n",phy_vars_ue->transmission_mode[eNB_id]);
- LOG_D(PHY,"\n");
switch(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode) {
case AntennaInfoDedicated__transmissionMode_tm1:
phy_vars_ue->transmission_mode[eNB_id] = 1;
@@ -827,6 +855,7 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
phy_vars_ue->transmission_mode[eNB_id] = 6;
break;
case AntennaInfoDedicated__transmissionMode_tm7:
+ lte_gold_ue_spec_port5(phy_vars_ue->lte_gold_uespec_port5_table, phy_vars_ue->frame_parms.Nid_cell, phy_vars_ue->pdcch_vars[eNB_id]->crnti);
phy_vars_ue->transmission_mode[eNB_id] = 7;
break;
default:
@@ -852,6 +881,53 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
}
+ if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated) {
+
+ phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srsConfigDedicatedSetup = 0;
+ if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
+ phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srsConfigDedicatedSetup = 1;
+ phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].duration = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.duration;
+ phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].cyclicShift = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;
+ phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].freqDomainPosition = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
+ phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_Bandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
+ phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_ConfigIndex = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
+ phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_HoppingBandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;
+ phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].transmissionComb = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
+
+
+ LOG_D(PHY,"soundingrs_ul_config_dedicated.srs_ConfigIndex %d\n",phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_ConfigIndex);
+ }
+
+ LOG_D(PHY,"------------------------------------------------------------\n");
+
+ }
+
+
+ if (physicalConfigDedicated->cqi_ReportConfig) {
+ if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic) {
+ // configure PUSCH CQI reporting
+ phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic;
+ if ((phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm12) &&
+ (phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm30) &&
+ (phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm31))
+ LOG_E(PHY,"Unsupported Aperiodic CQI Feedback Mode : %d\n",phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic);
+ }
+ if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic) {
+ if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_setup) {
+ // configure PUCCH CQI reporting
+ phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PUCCH_ResourceIndex = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
+ phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_pmi_ConfigIndex;
+ if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex)
+ phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex;
+ }
+ else if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_release) {
+ // handle release
+ phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = -1;
+ phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = -1;
+ }
+ }
+ }
+
#ifdef CBA
if (physicalConfigDedicated->pusch_CBAConfigDedicated_vlola) {
@@ -868,6 +944,9 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
return;
}
+ // fill cqi parameters for periodic CQI reporting
+ get_cqipmiri_params(phy_vars_ue,eNB_id);
+
}
void phy_config_cba_rnti (module_id_t Mod_id,int CC_id,eNB_flag_t eNB_flag, uint8_t index, rnti_t cba_rnti, uint8_t cba_group_id, uint8_t num_active_cba_groups)
@@ -939,14 +1018,17 @@ void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS
pdsch->llr128_2ndstream = (int16_t**)malloc16_clear( sizeof(int16_t*) );
// FIXME! no further allocation for (int16_t*)pdsch->llr128 !!! expect SIGSEGV
- pdsch->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
- pdsch->rxdataF_comp0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
- pdsch->rho = (int32_t**)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t*) );
- pdsch->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
- pdsch->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
- pdsch->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
- pdsch->dl_ch_mag0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
- pdsch->dl_ch_magb0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+ pdsch->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+ pdsch->rxdataF_uespec_pilots = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+ pdsch->rxdataF_comp0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+ pdsch->rho = (int32_t**)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t*) );
+ pdsch->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+ pdsch->dl_bf_ch_estimates = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+ pdsch->dl_bf_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+ pdsch->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+ pdsch->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+ pdsch->dl_ch_mag0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+ pdsch->dl_ch_magb0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
// the allocated memory size is fixed:
AssertFatal( fp->nb_antennas_rx <= 2, "nb_antennas_rx > 2" );
@@ -957,13 +1039,16 @@ void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS
for (int j=0; j<4; j++) { //fp->nb_antennas_tx; j++)
const int idx = (j<<1)+i;
const size_t num = 7*2*fp->N_RB_DL*12;
- pdsch->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
- pdsch->rxdataF_comp0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
- pdsch->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
- pdsch->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
- pdsch->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
- pdsch->dl_ch_mag0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
- pdsch->dl_ch_magb0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+ pdsch->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+ pdsch->rxdataF_uespec_pilots[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * fp->N_RB_DL*12);
+ pdsch->rxdataF_comp0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+ pdsch->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+ pdsch->dl_bf_ch_estimates[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * fp->ofdm_symbol_size*7*2);
+ pdsch->dl_bf_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+ pdsch->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+ pdsch->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+ pdsch->dl_ch_mag0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+ pdsch->dl_ch_magb0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
}
}
}
@@ -1178,6 +1263,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
LTE_eNB_SRS* const srs_vars = eNB->srs_vars;
LTE_eNB_PRACH* const prach_vars = &eNB->prach_vars;
int i, j, eNB_id, UE_id;
+ int re;
eNB->total_dlsch_bitrate = 0;
eNB->total_transmitted_bits = 0;
@@ -1204,9 +1290,9 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
eNB->physicalConfigDedicated[UE_id] = NULL;
}
- eNB->first_run_I0_measurements =
- 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here.
+ eNB->first_run_I0_measurements = 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here.
}
+
// for (eNB_id=0; eNB_id<3; eNB_id++) {
{
eNB_id=0;
@@ -1214,39 +1300,72 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
// TX vars
if (eNB->node_function != NGFI_RCC_IF4p5)
- common_vars->txdata[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_tx*sizeof(int32_t*) );
- common_vars->txdataF[eNB_id] = (int32_t **)malloc16( fp->nb_antennas_tx*sizeof(int32_t*) );
-
- for (i=0; inb_antennas_tx; i++) {
- if (eNB->node_function != NGFI_RCC_IF4p5)
- common_vars->txdata[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) );
- common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear( fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) );
+ common_vars->txdata[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_tx*sizeof(int32_t*));
+ common_vars->txdataF[eNB_id] = (int32_t **)malloc16(NB_ANTENNA_PORTS_ENB*sizeof(int32_t*));
+ common_vars->txdataF_BF[eNB_id] = (int32_t **)malloc16(fp->nb_antennas_tx*sizeof(int32_t*));
+
+ for (i=0; i<14; i++) {
+ common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) );
#ifdef DEBUG_PHY
- printf("[openair][LTE_PHY][INIT] common_vars->txdata[%d][%d] = %p\n",eNB_id,i,common_vars->txdata[eNB_id][i]);
- printf("[openair][LTE_PHY][INIT] common_vars->txdataF[%d][%d] = %p (%d bytes)\n",
- eNB_id,i,common_vars->txdataF[eNB_id][i],
- fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t));
+ msg("[openair][LTE_PHY][INIT] lte_common_vars->txdataF[%d][%d] = %p (%d bytes)\n",
+ eNB_id,i,common_vars->txdataF[eNB_id][i],
+ fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t));
+#endif
+ }
+
+ for (i=0; inb_antennas_tx; i++) {
+ common_vars->txdataF_BF[eNB_id][i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t) );
+ if (eNB->node_function != NGFI_RCC_IF4p5)
+ common_vars->txdata[eNB_id][i] = (int32_t*)malloc16_clear(fp->samples_per_tti*10*sizeof(int32_t) );
+
+#ifdef DEBUG_PHY
+ msg("[openair][LTE_PHY][INIT] lte_common_vars->txdataF_BF[%d][%d] = %p (%d bytes)\n",
+ eNB_id,i,common_vars->txdataF_BF[eNB_id][i],
+ fp->ofdm_symbol_size*sizeof(int32_t));
+ msg("[openair][LTE_PHY][INIT] lte_common_vars->txdata[%d][%d] = %p\n",eNB_id,i,common_vars->txdata[eNB_id][i]);
#endif
}
+ for (i=0; i<14; i++) { // 14 is the total number of antenna ports
+ common_vars->beam_weights[eNB_id][i] = (int32_t **)malloc16_clear(fp->nb_antennas_tx*sizeof(int32_t*));
+ for (j=0; jnb_antennas_tx; j++) {
+ common_vars->beam_weights[eNB_id][i][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t));
+ // antenna ports 0-3 are mapped on antennas 0-3
+ // antenna port 4 is mapped on antenna 0
+ // antenna ports 5-14 are mapped on all antennas
+ if (((i<4) && (i==j)) || ((i==4) && (j==0))) {
+ for (re=0; reofdm_symbol_size; re++)
+ common_vars->beam_weights[eNB_id][i][j][re] = 0x00007fff;
+ }
+ else if (i>4) {
+ for (re=0; reofdm_symbol_size; re++)
+ common_vars->beam_weights[eNB_id][i][j][re] = 0x00007fff/fp->nb_antennas_tx;
+ }
+#ifdef DEBUG_PHY
+ msg("[openair][LTE_PHY][INIT] lte_common_vars->beam_weights[%d][%d][%d] = %p (%d bytes)\n",
+ eNB_id,i,j,common_vars->beam_weights[eNB_id][i][j],
+ fp->ofdm_symbol_size*sizeof(int32_t));
+#endif
+ }
+ }
+
// RX vars
if (eNB->node_function != NGFI_RCC_IF4p5) {
- common_vars->rxdata[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
- common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
+ common_vars->rxdata[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) );
+ common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) );
}
- common_vars->rxdataF[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
-
+ common_vars->rxdataF[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) );
+
for (i=0; inb_antennas_rx; i++) {
if (eNB->node_function != NGFI_RCC_IF4p5) {
common_vars->rxdata[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) );
common_vars->rxdata_7_5kHz[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*sizeof(int32_t) );
- }
-
- common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(fp->ofdm_symbol_size*fp->symbols_per_tti) );
#ifdef DEBUG_PHY
- printf("[openair][LTE_PHY][INIT] common_vars->rxdata[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata[eNB_id][i]);
- printf("[openair][LTE_PHY][INIT] common_vars->rxdata_7_5kHz[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata_7_5kHz[eNB_id][i]);
+ printf("[openair][LTE_PHY][INIT] common_vars->rxdata[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata[eNB_id][i]);
+ printf("[openair][LTE_PHY][INIT] common_vars->rxdata_7_5kHz[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata_7_5kHz[eNB_id][i]);
#endif
+ }
+ common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(fp->ofdm_symbol_size*fp->symbols_per_tti) );
}
if (eNB->node_function != NGFI_RRU_IF4p5) {
@@ -1386,5 +1505,5 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
} // node_function != NGFI_RRU_IF4p5
return (0);
-}
+}
diff --git a/openair1/PHY/INIT/lte_param_init.c b/openair1/PHY/INIT/lte_param_init.c
index 9aca71612c..4625eba430 100644
--- a/openair1/PHY/INIT/lte_param_init.c
+++ b/openair1/PHY/INIT/lte_param_init.c
@@ -33,7 +33,8 @@
extern PHY_VARS_eNB *eNB;
extern PHY_VARS_UE *UE;
-void lte_param_init(unsigned char N_tx,
+void lte_param_init(unsigned char N_tx_port_eNB,
+ unsigned char N_tx_phy,
unsigned char N_rx,
unsigned char transmission_mode,
uint8_t extended_prefix_flag,
@@ -70,9 +71,9 @@ void lte_param_init(unsigned char N_tx,
frame_parms->Ncp_UL = extended_prefix_flag;
frame_parms->Nid_cell = Nid_cell;
frame_parms->nushift = Nid_cell%6;
- frame_parms->nb_antennas_tx = N_tx;
+ frame_parms->nb_antennas_tx = N_tx_phy;
frame_parms->nb_antennas_rx = N_rx;
- frame_parms->nb_antennas_tx_eNB = N_tx;
+ frame_parms->nb_antenna_ports_eNB = N_tx_port_eNB;
frame_parms->phich_config_common.phich_resource = oneSixth;
frame_parms->phich_config_common.phich_duration = normal;
frame_parms->tdd_config = tdd_config;
@@ -81,7 +82,7 @@ void lte_param_init(unsigned char N_tx,
// frame_parms->Bsrs = 0;
// frame_parms->kTC = 0;44
// frame_parms->n_RRC = 0;
- frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0;
+ frame_parms->mode1_flag = (transmission_mode == 1 || transmission_mode ==7)? 1 : 0;
init_frame_parms(frame_parms,osf);
@@ -93,6 +94,9 @@ void lte_param_init(unsigned char N_tx,
UE->frame_parms = *frame_parms;
eNB->frame_parms = *frame_parms;
+ eNB->transmission_mode[0] = transmission_mode;
+ UE->transmission_mode[0] = transmission_mode;
+
phy_init_lte_top(frame_parms);
dump_frame_parms(frame_parms);
@@ -110,7 +114,8 @@ void lte_param_init(unsigned char N_tx,
generate_phich_reg_mapping(&UE->frame_parms);
// DL power control init
- if (transmission_mode == 1) {
+ //if (transmission_mode == 1) {
+ if (transmission_mode == 1 || transmission_mode ==7) {
eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB
((eNB->frame_parms).pdsch_config_common).p_b = 0;
UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB
diff --git a/openair1/PHY/INIT/lte_parms.c b/openair1/PHY/INIT/lte_parms.c
index 611a141656..cd879b1a90 100644
--- a/openair1/PHY/INIT/lte_parms.c
+++ b/openair1/PHY/INIT/lte_parms.c
@@ -184,7 +184,7 @@ void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms)
printf("frame_parms->tdd_config=%d\n",frame_parms->tdd_config);
printf("frame_parms->tdd_config_S=%d\n",frame_parms->tdd_config_S);
printf("frame_parms->mode1_flag=%d\n",frame_parms->mode1_flag);
- printf("frame_parms->nb_antennas_tx_eNB(nb_antenna_ports)=%d\n",frame_parms->nb_antennas_tx_eNB);
+ printf("frame_parms->nb_antenna_ports_eNB=%d\n",frame_parms->nb_antenna_ports_eNB);
printf("frame_parms->nb_antennas_tx=%d\n",frame_parms->nb_antennas_tx);
printf("frame_parms->nb_antennas_rx=%d\n",frame_parms->nb_antennas_rx);
printf("frame_parms->ofdm_symbol_size=%d\n",frame_parms->ofdm_symbol_size);
diff --git a/openair1/PHY/LTE_ESTIMATION/bf_freq_domain_filters.m b/openair1/PHY/LTE_ESTIMATION/bf_freq_domain_filters.m
new file mode 100644
index 0000000000..e0c0a0f18f
--- /dev/null
+++ b/openair1/PHY/LTE_ESTIMATION/bf_freq_domain_filters.m
@@ -0,0 +1,59 @@
+filt_len = 16;
+
+F = -3/4:1/4:7/4;
+F_l = zeros(8,filt_len);
+F_r = zeros(8,filt_len);
+F_m = zeros(8,filt_len);
+
+F2 =-3/5:1/5:8/5;
+
+for i=0:3
+ F_l(i+1,:) = floor(16384*[F(8+i:-1:4) zeros(1,7-i) zeros(1,4)]);
+ F_r(i+1,:) = floor(16384*[zeros(1,4+i) F(4:end-i) zeros(1,4)]);
+ F_m(i+1,:) = floor(16384*[F(4-i:8) F(7:-1:1+i) zeros(1,4)]);
+end
+
+for i=0:1
+ F_l(i+5,:) = floor(16384*[F(8:-1:4-i) zeros(1,7-i) zeros(1,4)]);
+ F_r(i+5,:) = floor(16384*[zeros(1,5+i) F2(5+i) F2(7:end-i) zeros(1,4)]);
+ F_m(i+5,:) = floor(16384*[F(4-i:8) F2(8-i) F2(6:-1:1+i) zeros(1,4)]);
+end
+
+for i=2:3
+ F_l(i+5,:) = floor(16384*[F2(end:-1:7) F2(8-i) zeros(1,5) zeros(1,4)]);
+ F_r(i+5,:) = floor(16384*[zeros(1,4+i) F(4:end-i) zeros(1,4)]);
+ F_m(i+5,:) = floor(16384*[F2(4-i:6) F2(4+i) F(8:-1:1+i) zeros(1,4)]);
+end
+
+
+fd = fopen("filt16_32.h","w");
+
+for i=0:3
+ fprintf(fd,"short filt%d_l%d[%d] = {\n",filt_len,i,filt_len);
+ fprintf(fd,"%d,",F_l(i+1,1:end-1));
+ fprintf(fd,"%d};\n\n",F_l(i+1,end));
+
+ fprintf(fd,"short filt%d_r%d[%d] = {\n",filt_len,i,filt_len);
+ fprintf(fd,"%d,",F_r(i+1,1:end-1));
+ fprintf(fd,"%d};\n\n",F_r(i+1,end));
+
+ fprintf(fd,"short filt%d_m%d[%d] = {\n",filt_len,i,filt_len);
+ fprintf(fd,"%d,",F_m(i+1,1:end-1));
+ fprintf(fd,"%d};\n\n",F_m(i+1,end));
+end
+
+for i=0:3
+ fprintf(fd,"short filt%d_l%d_dc[%d] = {\n",filt_len,i,filt_len);
+ fprintf(fd,"%d,",F_l(i+5,1:end-1));
+ fprintf(fd,"%d};\n\n",F_l(i+5,end));
+
+ fprintf(fd,"short filt%d_r%d_dc[%d] = {\n",filt_len,i,filt_len);
+ fprintf(fd,"%d,",F_r(i+5,1:end-1));
+ fprintf(fd,"%d};\n\n",F_r(i+5,end));
+
+ fprintf(fd,"short filt%d_m%d_dc[%d] = {\n",filt_len,i,filt_len);
+ fprintf(fd,"%d,",F_m(i+5,1:end-1));
+ fprintf(fd,"%d};\n\n",F_m(i+5,end));
+end
+
+fclose(fd);
diff --git a/openair1/PHY/LTE_ESTIMATION/defs.h b/openair1/PHY/LTE_ESTIMATION/defs.h
index 0a38265461..3af9c2471f 100644
--- a/openair1/PHY/LTE_ESTIMATION/defs.h
+++ b/openair1/PHY/LTE_ESTIMATION/defs.h
@@ -116,6 +116,12 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue,
uint8_t l,
uint8_t symbol);
+int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue,
+ module_id_t eNB_id,
+ uint8_t eNB_offset,
+ uint8_t Ns,
+ uint8_t p,
+ uint8_t symbol);
int lte_dl_msbfn_channel_estimation(PHY_VARS_UE *phy_vars_ue,
module_id_t eNB_id,
diff --git a/openair1/PHY/LTE_ESTIMATION/filt16_32.h b/openair1/PHY/LTE_ESTIMATION/filt16_32.h
new file mode 100644
index 0000000000..3487fd3466
--- /dev/null
+++ b/openair1/PHY/LTE_ESTIMATION/filt16_32.h
@@ -0,0 +1,86 @@
+short filt16_l0[16] = {
+16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_r0[16] = {
+0,0,0,0,0,4096,8192,12288,16384,20480,24576,28672,0,0,0,0};
+
+short filt16_m0[16] = {
+0,4096,8192,12288,16384,12288,8192,4096,0,-4096,-8192,-12288,0,0,0,0};
+
+short filt16_l1[16] = {
+20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_r1[16] = {
+0,0,0,0,0,0,4096,8192,12288,16384,20480,24576,0,0,0,0};
+
+short filt16_m1[16] = {
+-4096,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,-8192,0,0,0,0};
+
+short filt16_l2[16] = {
+24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_r2[16] = {
+0,0,0,0,0,0,0,4096,8192,12288,16384,20480,0,0,0,0};
+
+short filt16_m2[16] = {
+-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,0,0,0,0};
+
+short filt16_l3[16] = {
+28672,24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0};
+
+short filt16_r3[16] = {
+0,0,0,0,0,0,0,0,4096,8192,12288,16384,0,0,0,0};
+
+short filt16_m3[16] = {
+-12288,-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0};
+
+short filt16_l0_dc[16] = {
+16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_r0_dc[16] = {
+0,0,0,0,0,3276,9830,13107,16384,19660,22937,26214,0,0,0,0};
+
+short filt16_m0_dc[16] = {
+0,4096,8192,12288,16384,13107,6553,3276,0,-3277,-6554,-9831,0,0,0,0};
+
+short filt16_l1_dc[16] = {
+16384,12288,8192,4096,0,-4096,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_r1_dc[16] = {
+0,0,0,0,0,0,6553,9830,13107,16384,19660,22937,0,0,0,0};
+
+short filt16_m1_dc[16] = {
+-4096,0,4096,8192,12288,16384,9830,6553,3276,0,-3277,-6554,0,0,0,0};
+
+short filt16_l2_dc[16] = {
+26214,22937,19660,16384,13107,9830,6553,0,0,0,0,0,0,0,0,0};
+
+short filt16_r2_dc[16] = {
+0,0,0,0,0,0,0,4096,8192,12288,16384,20480,0,0,0,0};
+
+short filt16_m2_dc[16] = {
+-6554,-3277,0,3276,6553,6553,16384,12288,8192,4096,0,-4096,0,0,0,0};
+
+short filt16_l3_dc[16] = {
+26214,22937,19660,16384,13107,9830,3276,0,0,0,0,0,0,0,0,0};
+
+short filt16_r3_dc[16] = {
+0,0,0,0,0,0,0,0,4096,8192,12288,16384,0,0,0,0};
+
+short filt16_m3_dc[16] = {
+-9831,-6554,-3277,0,3276,6553,9830,16384,12288,8192,4096,0,0,0,0,0};
+
+short filt16_1[16] = {
+16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384};
+
+short filt16_2l0[16] = {
+16384,12288,8192,4096,-4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_2r0[16] = {
+0,4096,8192,12288,16384,20480,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_2l1[16] = {
+20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_2r1[16] = {
+-4096,0,4096,8192,12288,16384,0,0,0,0,0,0,0,0,0,0};
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c
new file mode 100644
index 0000000000..0b220c2c39
--- /dev/null
+++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c
@@ -0,0 +1,750 @@
+/*******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@eurecom.fr
+
+ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+ *******************************************************************************/
+#ifdef USER_MODE
+#include
+#endif
+#include "defs.h"
+#include "PHY/defs.h"
+#include "filt16_32.h"
+//#define DEBUG_BF_CH
+
+int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue,
+ uint8_t eNB_id,
+ uint8_t eNB_offset,
+ unsigned char Ns,
+ unsigned char p,
+ unsigned char symbol)
+{
+
+ unsigned short rb,nb_rb=0;
+ unsigned char aarx,l,lprime,nsymb,skip_half=0,sss_symb,pss_symb=0,rb_alloc_ind,harq_pid,uespec_pilots=0;
+ int beamforming_mode, ch_offset;
+ uint8_t subframe;
+ int8_t uespec_nushift, uespec_poffset=0, pil_offset=0;
+ uint8_t pilot0,pilot1,pilot2,pilot3;
+
+ short ch[2], *pil, *rxF, *dl_bf_ch, *dl_bf_ch_prev;
+ short *fl, *fm, *fr, *fl_dc, *fm_dc, *fr_dc, *f1, *f2l, *f2r;
+
+ unsigned int *rballoc;
+ int **rxdataF;
+ int32_t **dl_bf_ch_estimates;
+ int uespec_pilot[300];
+
+ LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms;
+ LTE_UE_DLSCH_t **dlsch_ue = phy_vars_ue->dlsch[eNB_id];
+ LTE_DL_UE_HARQ_t *dlsch0_harq;
+
+ harq_pid = dlsch_ue[0]->current_harq_pid;
+ dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid];
+
+ if (((frame_parms->Ncp == NORMAL) && (symbol>=7)) ||
+ ((frame_parms->Ncp == EXTENDED) && (symbol>=6)))
+ rballoc = dlsch0_harq->rb_alloc_odd;
+ else
+ rballoc = dlsch0_harq->rb_alloc_even;
+
+ rxdataF = phy_vars_ue->common_vars.rxdataF;
+
+ dl_bf_ch_estimates = phy_vars_ue->pdsch_vars[eNB_id]->dl_bf_ch_estimates;
+ beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0;
+
+ if (phy_vars_ue->high_speed_flag == 0) // use second channel estimate position for temporary storage
+ ch_offset = frame_parms->ofdm_symbol_size;
+ else
+ ch_offset = frame_parms->ofdm_symbol_size*symbol;
+
+
+ uespec_nushift = frame_parms->Nid_cell%3;
+ subframe = Ns>>1;
+
+
+ //generate ue specific pilots
+ lprime = symbol/3-1;
+ lte_dl_ue_spec_rx(phy_vars_ue,uespec_pilot,Ns,5,lprime,0,dlsch0_harq->nb_rb);
+ //write_output("uespec_pilot_rx.m","uespec_pilot",uespec_pilot,300,1,1);
+
+ if (frame_parms->Ncp==0){
+ if (symbol==3 || symbol==6 || symbol==9 || symbol==12)
+ uespec_pilots = 1;
+ } else{
+ if (symbol==4 || symbol==7 || symbol==10)
+ uespec_pilots = 1;
+ }
+
+ if ((frame_parms->Ncp==0 && (symbol==6 ||symbol ==12)) || (frame_parms->Ncp==1 && symbol==7))
+ uespec_poffset = 2;
+
+ if (phy_vars_ue->frame_parms.Ncp == 0) { // normal prefix
+ pilot0 = 3;
+ pilot1 = 6;
+ pilot2 = 9;
+ pilot3 = 12;
+ } else { // extended prefix
+ pilot0 = 4;
+ pilot1 = 7;
+ pilot2 = 10;
+ }
+
+ //define the filter
+ pil_offset = (uespec_nushift+uespec_poffset)%3;
+ // printf("symbol=%d,pil_offset=%d\n",symbol,pil_offset);
+ switch (pil_offset) {
+ case 0:
+ fl = filt16_l0;
+ fm = filt16_m0;
+ fr = filt16_r0;
+ fl_dc = filt16_l0;
+ fm_dc = filt16_m0;
+ fr_dc = filt16_r0;
+ f1 = filt16_1;
+ f2l = filt16_2l0;
+ f2r = filt16_2r0;
+ break;
+
+ case 1:
+ fl = filt16_l1;
+ fm = filt16_m1;
+ fr = filt16_r1;
+ fl_dc = filt16_l1;
+ fm_dc = filt16_m1;
+ fr_dc = filt16_r1;
+ f1 = filt16_1;
+ f2l = filt16_2l1;
+ f2r = filt16_2r1;
+ break;
+
+ case 2:
+ fl = filt16_l2;
+ fm = filt16_m2;
+ fr = filt16_r2;
+ fl_dc = filt16_l2;
+ fm_dc = filt16_m2;
+ fr_dc = filt16_r2;
+ f1 = filt16_1;
+ f2l = filt16_2l0;
+ f2r = filt16_2r0;
+ break;
+
+ case 3:
+ fl = filt16_l3;
+ fm = filt16_m3;
+ fr = filt16_r3;
+ fl_dc = filt16_l3;
+ fm_dc = filt16_m3;
+ fr_dc = filt16_r3;
+ f1 = filt16_1;
+ f2l = filt16_2l1;
+ f2r = filt16_2r1;
+ break;
+ }
+ // beamforming mode extension
+ /* }
+ else if (beamforming_mode==0)
+ msg("lte_dl_bf_channel_estimation:No beamforming is performed.\n");
+ else
+ msg("lte_dl_bf_channel_estimation:Beamforming mode not supported yet.\n");*/
+
+
+ l=symbol;
+ nsymb = (frame_parms->Ncp==NORMAL) ? 14:12;
+
+ if (frame_parms->frame_type == TDD) { //TDD
+ sss_symb = nsymb-1;
+ pss_symb = 2;
+ } else {
+ sss_symb = (nsymb>>1)-2;
+ pss_symb = (nsymb>>1)-1;
+ }
+
+
+ for (aarx=0; aarxnb_antennas_rx; aarx++) {
+
+ rxF = (short *)&rxdataF[aarx][pil_offset + frame_parms->first_carrier_offset + symbol*frame_parms->ofdm_symbol_size];
+ pil = (short *)uespec_pilot;
+ dl_bf_ch = (short *)&dl_bf_ch_estimates[aarx][ch_offset];
+
+ memset(dl_bf_ch,0,4*(frame_parms->ofdm_symbol_size));
+ //memset(dl_bf_ch,0,2*(frame_parms->ofdm_symbol_size));
+
+ if (phy_vars_ue->high_speed_flag==0) {
+ // multiply previous channel estimate by ch_est_alpha
+ if (frame_parms->Ncp==0){
+ multadd_complex_vector_real_scalar(dl_bf_ch-(frame_parms->ofdm_symbol_size<<1),
+ phy_vars_ue->ch_est_alpha,dl_bf_ch-(frame_parms->ofdm_symbol_size<<1),
+ 1,frame_parms->ofdm_symbol_size);
+ } else {
+ msg("lte_dl_bf_channel_estimation: beamforming channel estimation not supported for TM7 Extended CP.\n"); // phy_vars_ue->ch_est_beta should be defined equaling 1/3
+ }
+ }
+ //estimation and interpolation
+
+ if ((frame_parms->N_RB_DL&1) == 0) { // even number of RBs
+ for (rb=0; rbN_RB_DL; rb++) {
+
+ if (rb < 32)
+ rb_alloc_ind = (rballoc[0]>>rb) & 1;
+ else if (rb < 64)
+ rb_alloc_ind = (rballoc[1]>>(rb-32)) & 1;
+ else if (rb < 96)
+ rb_alloc_ind = (rballoc[2]>>(rb-64)) & 1;
+ else if (rb < 100)
+ rb_alloc_ind = (rballoc[3]>>(rb-96)) & 1;
+ else
+ rb_alloc_ind = 0;
+
+ // For second half of RBs skip DC carrier
+ if (rb==(frame_parms->N_RB_DL>>1)) {
+ rxF = (short *)&rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))];
+ }
+
+ if (rb_alloc_ind==1) {
+ if (uespec_pilots==1) {
+ if (beamforming_mode==7) {
+ if (frame_parms->Ncp==0) {
+
+ ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+ multadd_real_vector_complex_scalar(fl,ch,dl_bf_ch,16);
+
+ ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+ multadd_real_vector_complex_scalar(fm,ch,dl_bf_ch,16);
+
+ ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+ multadd_real_vector_complex_scalar(fr,ch,dl_bf_ch,16);
+ } else {
+ msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c):TM7 beamgforming channel estimation not supported for extented CP\n");
+ exit(-1);
+ }
+ } else {
+ msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c): transmission mode not supported.\n");
+ }
+ }
+ nb_rb++;
+ }
+
+ rxF+=24;
+ dl_bf_ch+=24;
+ }
+ } else { // Odd number of RBs
+ for (rb=0; rbN_RB_DL>>1; rb++) {
+ skip_half=0;
+
+ if (rb < 32)
+ rb_alloc_ind = (rballoc[0]>>rb) & 1;
+ else if (rb < 64)
+ rb_alloc_ind = (rballoc[1]>>(rb-32)) & 1;
+ else if (rb < 96)
+ rb_alloc_ind = (rballoc[2]>>(rb-64)) & 1;
+ else if (rb < 100)
+ rb_alloc_ind = (rballoc[3]>>(rb-96)) & 1;
+ else
+ rb_alloc_ind = 0;
+
+ // PBCH
+ if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) {
+ rb_alloc_ind = 0;
+ }
+
+ //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3
+ if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+ skip_half=1;
+ else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+ skip_half=2;
+
+ //SSS
+ if (((subframe==0)||(subframe==5)) &&
+ (rb>((frame_parms->N_RB_DL>>1)-3)) &&
+ (rb<((frame_parms->N_RB_DL>>1)+3)) &&
+ (l==sss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ //SSS
+ if (((subframe==0)||(subframe==5)) &&
+ (rb==((frame_parms->N_RB_DL>>1)-3)) &&
+ (l==sss_symb))
+ skip_half=1;
+ else if (((subframe==0)||(subframe==5)) &&
+ (rb==((frame_parms->N_RB_DL>>1)+3)) &&
+ (l==sss_symb))
+ skip_half=2;
+
+ //PSS in subframe 0/5 if FDD
+ if (frame_parms->frame_type == FDD) { //FDD
+ if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+ skip_half=1;
+ else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+ skip_half=2;
+ }
+
+ if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) { //TDD Subframe 1 and 6
+ if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+ skip_half=1;
+ else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+ skip_half=2;
+ }
+
+ //printf("symbol=%d,pil_offset=%d\ni,rb_alloc_ind=%d,uespec_pilots=%d,beamforming_mode=%d,Ncp=%d,skip_half=%d\n",symbol,pil_offset,rb_alloc_ind,uespec_pilots,beamforming_mode,frame_parms->Ncp,skip_half);
+ if (rb_alloc_ind==1) {
+ if (uespec_pilots==1) {
+ if (beamforming_mode==7) {
+ if (frame_parms->Ncp==0) {
+ if (skip_half==1) {
+ if (pil_offset<2) {
+
+ ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+ multadd_real_vector_complex_scalar(f2l,ch,dl_bf_ch,16);
+ pil+=2;
+
+ ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+ multadd_real_vector_complex_scalar(f2r,ch,dl_bf_ch,16);
+ pil+=2;
+
+ } else {
+
+ ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+ multadd_real_vector_complex_scalar(f1,ch,dl_bf_ch,16);
+ pil+=2;
+ }
+ } else if (skip_half==2) {
+ if (pil_offset<2) {
+
+ ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+ multadd_real_vector_complex_scalar(f1,ch,dl_bf_ch,16);
+ pil+=2;
+
+ } else {
+
+ ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+ multadd_real_vector_complex_scalar(f2l,ch,dl_bf_ch,16);
+ pil+=2;
+
+ ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+ multadd_real_vector_complex_scalar(f2r,ch,dl_bf_ch,16);
+ pil+=2;
+
+ }
+ } else {
+
+ ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+ multadd_real_vector_complex_scalar(fl,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ printf("symbol=%d,rxF[0]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[0],rxF[1],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;
+
+ ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+ multadd_real_vector_complex_scalar(fm,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ printf("symbol=%d,rxF[4]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[8],rxF[9],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;
+
+ ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+ multadd_real_vector_complex_scalar(fr,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ printf("symbol=%d,rxF[8]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[16],rxF[17],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;
+
+ }
+ } else {
+ msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c):TM7 beamgforming channel estimation not supported for extented CP\n");
+ exit(-1);
+ }
+
+ } else {
+ msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c):transmission mode not supported.\n");
+ }
+ }
+ nb_rb++;
+ }
+
+ rxF+=24;
+ dl_bf_ch+=24;
+ } // first half loop
+
+ // Do middle RB (around DC)
+ if (rb < 32)
+ rb_alloc_ind = (rballoc[0]>>rb) & 1;
+ else if (rb < 64)
+ rb_alloc_ind = (rballoc[1]>>(rb-32)) & 1;
+ else if (rb < 96)
+ rb_alloc_ind = (rballoc[2]>>(rb-64)) & 1;
+ else if (rb < 100)
+ rb_alloc_ind = (rballoc[3]>>(rb-96)) & 1;
+ else
+ rb_alloc_ind = 0;
+
+ // PBCH
+ if ((subframe==0) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) {
+ rb_alloc_ind = 0;
+ }
+
+ //SSS
+ if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ if (frame_parms->frame_type == FDD) {
+ //PSS
+ if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+ }
+
+ if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) {
+ //PSS
+ if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+ }
+
+ //printf("DC rb %d (%p)\n",rb,rxF);
+ if (rb_alloc_ind==1) {
+ if (pil_offset<2) {
+ ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+ multadd_real_vector_complex_scalar(fl_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ //printf("symbol=%d,rxF[0]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[0],rxF[1],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;;
+
+ ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+ multadd_real_vector_complex_scalar(fm_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ //printf("symbol=%d,rxF[4]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[8],rxF[9],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;;
+
+ rxF = (short *)&rxdataF[aarx][symbol*(frame_parms->ofdm_symbol_size)];
+
+ ch[0] = (short)(((int)pil[0]*rxF[6] - (int)pil[1]*rxF[7])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[7] + (int)pil[1]*rxF[6])>>15);
+ multadd_real_vector_complex_scalar(fr_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ //printf("symbol=%d,rxF[3]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[6],rxF[7],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;;
+ } else {
+ ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+ multadd_real_vector_complex_scalar(fl_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ //printf("symbol=%d,rxF[0]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[0],rxF[1],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;;
+
+ rxF = (short *)&rxdataF[aarx][symbol*(frame_parms->ofdm_symbol_size)];
+
+ ch[0] = (short)(((int)pil[0]*rxF[2] - (int)pil[1]*rxF[3])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[3] + (int)pil[1]*rxF[2])>>15);
+ multadd_real_vector_complex_scalar(fm_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ //printf("symbol=%d,rxF[1]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[2],rxF[3],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;;
+
+ ch[0] = (short)(((int)pil[0]*rxF[10] - (int)pil[1]*rxF[11])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[11] + (int)pil[1]*rxF[10])>>15);
+ multadd_real_vector_complex_scalar(fr_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ //printf("symbol=%d,rxF[5]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[10],rxF[11],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;;
+ }
+ } // rballoc==1
+ else {
+ rxF = (short *)&rxdataF[aarx][pil_offset+((symbol*(frame_parms->ofdm_symbol_size)))];
+ }
+
+ rxF+=14+2*pil_offset;
+ dl_bf_ch+=24;
+ rb++;
+
+ for (; rbN_RB_DL; rb++) {
+ skip_half=0;
+
+ if (rb < 32)
+ rb_alloc_ind = (rballoc[0]>>rb) & 1;
+ else if (rb < 64)
+ rb_alloc_ind = (rballoc[1]>>(rb-32)) & 1;
+ else if (rb < 96)
+ rb_alloc_ind = (rballoc[2]>>(rb-64)) & 1;
+ else if (rb < 100)
+ rb_alloc_ind = (rballoc[3]>>(rb-96)) & 1;
+ else
+ rb_alloc_ind = 0;
+
+ // PBCH
+ if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) {
+ rb_alloc_ind = 0;
+ }
+
+ //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3
+ if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+ skip_half=1;
+ else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+ skip_half=2;
+
+ //SSS
+ if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ //SSS
+ if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb))
+ skip_half=1;
+ else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb))
+ skip_half=2;
+
+ if (frame_parms->frame_type == FDD) {
+ //PSS
+ if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ //PSS
+ if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+ skip_half=1;
+ else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+ skip_half=2;
+ }
+
+ if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) { //TDD Subframe 1 and 6
+ if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+ skip_half=1;
+ else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+ skip_half=2;
+ }
+
+ if (rb_alloc_ind==1) {
+ if (uespec_pilots==1) {
+ if (beamforming_mode==7) {
+ if (frame_parms->Ncp==0) {
+ if (skip_half==1) {
+ if (pil_offset<2) {
+
+ ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+ multadd_real_vector_complex_scalar(f2l,ch,dl_bf_ch,16);
+ pil+=2;
+
+ ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+ multadd_real_vector_complex_scalar(f2r,ch,dl_bf_ch,16);
+ pil+=2;
+
+
+ } else {
+
+ ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+ multadd_real_vector_complex_scalar(f1,ch,dl_bf_ch,16);
+ pil+=2;
+ }
+ } else if (skip_half==2) {
+ if (pil_offset<2) {
+
+ ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+ multadd_real_vector_complex_scalar(f1,ch,dl_bf_ch,16);
+ pil+=2;
+
+ } else {
+
+ ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+ multadd_real_vector_complex_scalar(f2l,ch,dl_bf_ch,16);
+ pil+=2;
+
+ ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+ multadd_real_vector_complex_scalar(f2r,ch,dl_bf_ch,16);
+ pil+=2;
+
+ }
+ } else {
+
+ ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+ multadd_real_vector_complex_scalar(fl,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ printf("symbol=%d,rxF[0]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[0],rxF[1],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;
+
+ ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+ multadd_real_vector_complex_scalar(fm,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ printf("symbol=%d,rxF[4]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[8],rxF[9],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;
+
+ ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+ ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+ multadd_real_vector_complex_scalar(fr,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+ printf("symbol=%d,rxF[8]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[16],rxF[17],pil[0],pil[1],ch[0],ch[1]);
+#endif
+ pil+=2;
+
+ }
+ } else {
+ msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c):TM7 beamgforming channel estimation not supported for extented CP\n");
+ exit(-1);
+ }
+
+ } else {
+ msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c):transmission mode not supported.\n");
+ }
+ }
+ nb_rb++;
+ }
+
+ rxF+=24;
+ dl_bf_ch+=24;
+ } // second half of RBs
+ } // odd number of RBs
+
+ // Temporal Interpolation
+ if (phy_vars_ue->perfect_ce == 0) {
+
+ dl_bf_ch = (short *)&dl_bf_ch_estimates[aarx][ch_offset];
+#ifdef DEBUG_BF_CH
+ printf("[dlsch_bf_ch_est.c]:symbol %d, dl_bf_ch (%d,%d)\n",symbol,dl_bf_ch[0],dl_bf_ch[1]);
+#endif
+
+ if (phy_vars_ue->high_speed_flag == 0) {
+ multadd_complex_vector_real_scalar(dl_bf_ch,
+ 32767-phy_vars_ue->ch_est_alpha,
+ dl_bf_ch-(frame_parms->ofdm_symbol_size<<1),0,frame_parms->ofdm_symbol_size);
+ //printf("dlsch_bf_ch_est.c:symbol %d,dl_bf_ch (%d,%d)\n",symbol,*(dl_bf_ch-512*2),*(dl_bf_ch-512*2+1));
+ } else { // high_speed_flag == 1
+ if (beamforming_mode==7) {
+ if (frame_parms->Ncp==0) {
+ if (symbol == pilot0) {
+ // printf("Interpolating %d->0\n",4-phy_vars_ue->lte_frame_parms.Ncp);
+ // dl_bf_ch_prev = (short *)&dl_bf_ch_estimates[aarx][(4-phy_vars_ue->lte_frame_parms.Ncp)*(frame_parms->ofdm_symbol_size)];
+ dl_bf_ch_prev = (short *)&dl_bf_ch_estimates[aarx][pilot3*(frame_parms->ofdm_symbol_size)];
+#ifdef DEBUG_BF_CH
+ printf("[dlsch_bf_ch_est.c] symbol=%d, dl_bf_ch_prev=(%d,%d), dl_bf_ch=(%d,%d)\n", symbol, dl_bf_ch_prev[0], dl_bf_ch_prev[1], dl_bf_ch[0], dl_bf_ch[1]);
+#endif
+ // pilot spacing 5 symbols (1/5,2/5,3/5,4/5 combination)
+ multadd_complex_vector_real_scalar(dl_bf_ch_prev,26214,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+ multadd_complex_vector_real_scalar(dl_bf_ch,6554,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+
+ multadd_complex_vector_real_scalar(dl_bf_ch_prev,19661,dl_bf_ch-(3*2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+ multadd_complex_vector_real_scalar(dl_bf_ch,13107,dl_bf_ch-(3*2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+
+ multadd_complex_vector_real_scalar(dl_bf_ch_prev,13107,dl_bf_ch-(2*((frame_parms->ofdm_symbol_size)<<1)),1,frame_parms->ofdm_symbol_size);
+ multadd_complex_vector_real_scalar(dl_bf_ch,19661,dl_bf_ch-(2*((frame_parms->ofdm_symbol_size)<<1)),0,frame_parms->ofdm_symbol_size);
+
+ multadd_complex_vector_real_scalar(dl_bf_ch_prev,6554,dl_bf_ch-(2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+ multadd_complex_vector_real_scalar(dl_bf_ch,26214,dl_bf_ch-(2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+ } else if (symbol == pilot1) {
+ dl_bf_ch_prev = (short *)&dl_bf_ch_estimates[aarx][pilot0*(frame_parms->ofdm_symbol_size)];
+#ifdef DEBUG_BF_CH
+ printf("[dlsch_bf_ch_est.c] symbol=%d, dl_bf_ch_prev=(%d,%d), dl_bf_ch=(%d,%d)\n", symbol, dl_bf_ch_prev[0], dl_bf_ch_prev[1], dl_bf_ch[0], dl_bf_ch[1]);
+#endif
+
+ // pilot spacing 3 symbols (1/3,2/3 combination)
+ multadd_complex_vector_real_scalar(dl_bf_ch_prev,21845,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+ multadd_complex_vector_real_scalar(dl_bf_ch,10923,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+
+ multadd_complex_vector_real_scalar(dl_bf_ch_prev,10923,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),1,frame_parms->ofdm_symbol_size);
+ multadd_complex_vector_real_scalar(dl_bf_ch,21845,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),0,frame_parms->ofdm_symbol_size);
+
+ } else if (symbol == pilot2) {
+ dl_bf_ch_prev = (short *)&dl_bf_ch_estimates[aarx][pilot1*(frame_parms->ofdm_symbol_size)];
+#ifdef DEBUG_BF_CH
+ printf("[dlsch_bf_ch_est.c] symbol=%d, dl_bf_ch_prev=(%d,%d), dl_bf_ch=(%d,%d)\n", symbol, dl_bf_ch_prev[0], dl_bf_ch_prev[1], dl_bf_ch[0], dl_bf_ch[1]);
+#endif
+
+ multadd_complex_vector_real_scalar(dl_bf_ch_prev,21845,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+ multadd_complex_vector_real_scalar(dl_bf_ch,10923,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+
+ multadd_complex_vector_real_scalar(dl_bf_ch_prev,10923,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),1,frame_parms->ofdm_symbol_size);
+ multadd_complex_vector_real_scalar(dl_bf_ch,21845,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),0,frame_parms->ofdm_symbol_size);
+ } else { // symbol == pilot3
+ // printf("Interpolating 0->%d\n",4-phy_vars_ue->lte_frame_parms.Ncp);
+ dl_bf_ch_prev = (short *)&dl_bf_ch_estimates[aarx][pilot2*(frame_parms->ofdm_symbol_size)];
+
+ // pilot spacing 3 symbols (1/3,2/3 combination)
+ multadd_complex_vector_real_scalar(dl_bf_ch_prev,21845,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+ multadd_complex_vector_real_scalar(dl_bf_ch,10923,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+
+ multadd_complex_vector_real_scalar(dl_bf_ch_prev,10923,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),1,frame_parms->ofdm_symbol_size);
+ multadd_complex_vector_real_scalar(dl_bf_ch,21845,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),0,frame_parms->ofdm_symbol_size);
+ }
+
+ } else {
+ msg("lte_dl_bf_channel_estimation:temporal interpolation not supported for TM7 extented CP.\n");
+ }
+ } else {
+ msg("lte_dl_bf_channel_estimation:temporal interpolation not supported for this beamforming mode.\n");
+ }
+ }
+ }
+ } //aarx
+
+#ifdef DEBUG_BF_CH
+ printf("[dlsch_bf_ch_est.c]: dl_bf_estimates[0][600] %d, %d \n",*(short *)&dl_bf_ch_estimates[0][600],*(short*)&phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_bf_ch_estimates[0][600]);
+#endif
+
+ return(0);
+
+}
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c
index 65e2101d99..45ed0f11c0 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c
@@ -35,9 +35,6 @@ int lte_dl_channel_estimation(PHY_VARS_UE *ue,
unsigned char l,
unsigned char symbol)
{
-
-
-
int pilot[2][200] __attribute__((aligned(16)));
unsigned char nu,aarx;
unsigned short k;
@@ -735,7 +732,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *ue,
// do ifft of channel estimate
for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++)
- for (p=0; pframe_parms.nb_antennas_tx_eNB; p++) {
+ for (p=0; pframe_parms.nb_antenna_ports_eNB; p++) {
if (ue->common_vars.dl_ch_estimates[eNB_offset][(p<<1)+aarx])
idft((int16_t*) &ue->common_vars.dl_ch_estimates[eNB_offset][(p<<1)+aarx][8],
(int16_t*) ue->common_vars.dl_ch_estimates_time[eNB_offset][(p<<1)+aarx],1);
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_est_freq_offset.c b/openair1/PHY/LTE_ESTIMATION/lte_est_freq_offset.c
index 6ebd8948cf..d713cc0163 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_est_freq_offset.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_est_freq_offset.c
@@ -102,7 +102,7 @@ int lte_est_freq_offset(int **dl_ch_estimates,
{
int ch_offset, omega, dl_ch_shift;
- struct complex16 *omega_cpx;
+ struct complex16 omega_cpx;
double phase_offset;
int freq_offset_est;
unsigned char aa;
@@ -142,9 +142,8 @@ int lte_est_freq_offset(int **dl_ch_estimates,
// printf("Computing freq_offset\n");
omega = dot_product(dl_ch,dl_ch_prev,(frame_parms->N_RB_DL/2 - 1)*12,dl_ch_shift);
//omega = dot_product(dl_ch,dl_ch_prev,frame_parms->ofdm_symbol_size,15);
- omega_cpx = (struct complex16*) ω
-
- // printf("omega (%d,%d)\n",omega_cpx->r,omega_cpx->i);
+ omega_cpx.r = ((struct complex16*) &omega)->r;
+ omega_cpx.i = ((struct complex16*) &omega)->i;
dl_ch = (int16_t *)&dl_ch_estimates[aa][(((frame_parms->N_RB_DL/2) + 1)*12) + ch_offset];
@@ -155,10 +154,12 @@ int lte_est_freq_offset(int **dl_ch_estimates,
// calculate omega = angle(conj(dl_ch)*dl_ch_prev))
omega = dot_product(dl_ch,dl_ch_prev,((frame_parms->N_RB_DL/2) - 1)*12,dl_ch_shift);
- omega_cpx->r += ((struct complex16*) &omega)->r;
- omega_cpx->i += ((struct complex16*) &omega)->i;
+
+ omega_cpx.r += ((struct complex16*) &omega)->r;
+ omega_cpx.i += ((struct complex16*) &omega)->i;
+
// phase_offset += atan2((double)omega_cpx->i,(double)omega_cpx->r);
- phase_offset += atan2((double)omega_cpx->i,(double)omega_cpx->r);
+ phase_offset += atan2((double)omega_cpx.i,(double)omega_cpx.r);
// LOG_I(PHY,"omega (%d,%d) -> %f\n",omega_cpx->r,omega_cpx->i,phase_offset);
}
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c
index b7b36efa0b..90ebd07f60 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c
@@ -446,7 +446,7 @@ void lte_ue_measurements(PHY_VARS_UE *ue,
// signal measurements
for (eNB_id=0; eNB_idn_connected_eNB; eNB_id++) {
for (aarx=0; aarxnb_antennas_rx; aarx++) {
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++) {
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++) {
ue->measurements.rx_spatial_power[eNB_id][aatx][aarx] =
(signal_energy_nodc(&ue->common_vars.dl_ch_estimates[eNB_id][(aatx<<1) + aarx][0],
(N_RB_DL*12)));
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
index d8a627020d..d2bc2e27c0 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
@@ -78,7 +78,7 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
int16_t ul_ch_estimates_re,ul_ch_estimates_im;
int32_t rx_power_correction;
- //uint8_t nb_antennas_rx = frame_parms->nb_antennas_tx_eNB;
+ //uint8_t nb_antennas_rx = frame_parms->nb_antenna_ports_eNB;
uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
uint8_t cyclic_shift;
@@ -679,7 +679,7 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms,
int T_SFC,aa;
int N_symb,symbol;
- uint8_t nb_antennas_rx = frame_parms->nb_antennas_tx_eNB;
+ uint8_t nb_antennas_rx = frame_parms->nb_antenna_ports_eNB;
#ifdef DEBUG_SRS
char fname[40], vname[40];
#endif
diff --git a/openair1/PHY/LTE_REFSIG/defs.h b/openair1/PHY/LTE_REFSIG/defs.h
index a1d2d3aaf8..9c12458ff0 100644
--- a/openair1/PHY/LTE_REFSIG/defs.h
+++ b/openair1/PHY/LTE_REFSIG/defs.h
@@ -45,12 +45,15 @@ unsigned int lte_gold_generic(unsigned int *x1, unsigned int *x2, unsigned char
void lte_gold(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_table[20][2][14],uint16_t Nid_cell);
+void lte_gold_ue_spec(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_uespec_table[2][20][2][21],uint16_t Nid_cell, uint16_t *n_idDMRS);
+
+void lte_gold_ue_spec_port5(uint32_t lte_gold_uespec_port5_table[20][38],uint16_t Nid_cell, uint16_t n_rnti);
+
/*!\brief This function generates the LTE Gold sequence (36-211, Sec 7.2), specifically for DL UE-specific reference signals for antenna ports 7..14.
@param frame_parms LTE DL Frame parameters
@param lte_gold_uespec_table pointer to table where sequences are stored
@param Nid_cell Cell Id (to compute sequences for local and adjacent cells)
@param n_idDMRS Scrambling identity for TM10*/
-void lte_gold_ue_spec(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_uespec_table[2][20][2][21],uint16_t Nid_cell, uint16_t *n_idDMRS);
void lte_gold_mbsfn(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_mbsfn_table[10][3][42],uint16_t Nid_MBSFN);
@@ -77,16 +80,18 @@ int lte_dl_cell_spec(PHY_VARS_eNB *phy_vars_eNB,
@param output Output vector for OFDM symbol (Frequency Domain)
@param amp Q15 amplitude
@param Ns Slot number (0..19)
+@param lprime symbol (0,1)
@param p antenna index
@param SS_flag Flag to indicate special subframe
*/
-int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB,
+/*int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB,
uint8_t UE_id,
int32_t *output,
short amp,
uint8_t Ns,
+ uint8_t lprime,
uint8_t p,
- int SS_flag );
+ int SS_flag);*/
/*! \brief This function generates the MBSFN reference signal sequence (36-211, Sec 6.10.1.2)
@param phy_vars_eNB Pointer to eNB variables
@@ -116,6 +121,24 @@ int lte_dl_cell_spec_rx(PHY_VARS_UE *phy_vars_ue,
unsigned char l,
unsigned char p);
+/*!\brief This function generates the ue-specific reference signal
+ * sequence (36-211, Sec 6.10.3.1) for beamforming channel estimation upon reception
+@param phy_vars_ue Pointer to UE variables
+@param output Output vector for OFDM symbol (Frequency Domain)
+@param Ns Slot number (0..19)
+@param p antenna port intex
+@param lprime symbol (0,1)
+@param SS_flag Flag to indicate special subframe
+@param nRB_PDSCH number of allocated PDSCH RBs
+*/
+int lte_dl_ue_spec_rx(PHY_VARS_UE *phy_vars_ue,
+ int32_t *output,
+ unsigned char Ns,
+ unsigned char p,
+ int lprime,
+ int SS_flag,
+ uint16_t nRB_PDSCH);
+
int lte_dl_mbsfn_rx(PHY_VARS_UE *phy_vars_ue,
int *output,
int subframe,
diff --git a/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c b/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c
index fba122eef4..3cf88fbb76 100644
--- a/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c
+++ b/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c
@@ -19,13 +19,13 @@
* contact@openairinterface.org
*/
-/*! \file PHY/LTE_REFSIG/lte_dl_uespec.c
+/*! \file PHY/LTE_REFSIG/lte_dl_ue_spec.c
* \brief Top-level routines for generating UE-specific Reference signals from 36-211, V11.3.0 2013-06
-* \author R. Knopp
-* \date 2014
+* \author R. Knopp X. Jiang
+* \date 2015
* \version 0.1
* \company Eurecom
-* \email: knopp@eurecom.fr
+* \email: knopp@eurecom.fr xiwen.jiang@eurecom.fr
* \note
* \warning
*/
@@ -44,18 +44,21 @@
int Wbar_NCP[8][4] = {{1,1,1,1},{1,-1,1,-1},{1,1,1,1},{1,-1,1,-1},{1,1,-1,-1},{-1,-1,1,1},{1,-1,-1,1},{-1,1,1,-1}};
+/*
int lte_dl_ue_spec(PHY_VARS_eNB *eNB,
uint8_t UE_id,
int32_t *output,
short amp,
uint8_t Ns,
+ uint8_t lprime,
uint8_t p,
- int SS_flag )
+ int SS_flag)
{
- int32_t qpsk[4],nqpsk[4],*qpsk_p,*output_p;
- int16_t a;
- int w,lprime,ind,l,ind_dword,ind_qpsk_symb,nPRB;
+ int32_t qpsk[4],nqpsk[4];
+ int16_t k=0,a;
+ int mprime,ind,ind_dword,ind_qpsk_symb;
+ unsigned nushift,kprime;
// LTE_eNB_DLSCH_t *dlsch = eNB->dlsch_eNB[UE_id][0];
a = (amp*ONE_OVER_SQRT2_Q15)>>15;
@@ -77,172 +80,66 @@ int lte_dl_ue_spec(PHY_VARS_eNB *eNB,
((short *)&nqpsk[3])[0] = a;
((short *)&nqpsk[3])[1] = a;
- if (p>=7) {
+ if (p==5) {
if (SS_flag==0) {
if (eNB->frame_parms.Ncp == NORMAL) {
- // this is 3GPP 36-211 6.10.3.2, NORMAL CP, p>=7
+ // this is 3GPP 36-211 6.10.3.2, NORMAL CP, p=5
+
+ nushift = eNB->frame_parms.Nid_cell%3;
+ if(lprime==0){
+ kprime=nushift;
+ }else{
+ kprime=(nushift+2*lprime)%4;
+ }
+ k = kprime+eNB->frame_parms.first_carrier_offset;
+ printf("lte_dl_ue_spec:k=%d\n",k);
+
+ for (mprime=0;mprime<3*nRB_PDSCH-1;mprime++) {
+ ind = 3*lprime*nRB_PDSCH+mprime;
+ ind_dword = ind>>4;
+ ind_qpsk_symb = ind&0xf;
- // position output pointer to 5th symbol in slot
- output_p = output+(60*eNB->frame_parms.N_RB_DL);
+ output[k] = qpsk[(phy_vars_UE->lte_gold_uespec_port5_table[Ns][ind_dword]>>(2*ind_qpsk_symb))&3];
+ //output[k] = 0xffffffff;
- // shift to 2nd RE in PRB for p=7,8,11,13
- if ((p==7) || (p==8) || (p==11) || (p==13)) output_p++;
-
-
- for (lprime=0; lprime<2; lprime++) {
-
- ind = 3*lprime*eNB->frame_parms.N_RB_DL;
- l = lprime + ((Ns&1)<<1);
-
- // loop over pairs of PRBs, this is the periodicity of the W_bar_NCP sequence
- // unroll the computations for the 6 pilots, select qpsk or nqpsk as function of W_bar_NCP
- for (nPRB=0; nPRBframe_parms.N_RB_DL; nPRB+=2) {
-
- // First pilot
- w = Wbar_NCP[p-7][l];
- qpsk_p = (w==1) ? qpsk : nqpsk;
-
-
- ind_dword = ind>>4;
- ind_qpsk_symb = ind&0xf;
-
- *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
-
-
-#ifdef DEBUG_DL_UESPEC
- LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
- Ns,l,m,mprime_dword,mprime_qpsk_symb);
- LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
-#endif
-
- output_p+=5;
- ind++;
-
- w = Wbar_NCP[p-7][3-l];
- qpsk_p = (w==1) ? qpsk : nqpsk;
-
- // Second pilot
- ind_dword = ind>>4;
- ind_qpsk_symb = ind&0xf;
-
- *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
-
-#ifdef DEBUG_DL_UESPEC
- LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
- Ns,l,m,mprime_dword,mprime_qpsk_symb);
- LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
-#endif
-
- output_p+=5;
- ind++;
-
- w = Wbar_NCP[p-7][l];
- qpsk_p = (w==1) ? qpsk : nqpsk;
- // Third pilot
- ind_dword = ind>>4;
- ind_qpsk_symb = ind&0xf;
-
- *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
-
-#ifdef DEBUG_DL_UESPEC
- LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
- Ns,l,m,mprime_dword,mprime_qpsk_symb);
- LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
-#endif
-
- output_p+=2;
- ind++;
-
- // Fourth pilot
- w = Wbar_NCP[p-7][3-l];
- qpsk_p = (w==1) ? qpsk : nqpsk;
-
-
- ind_dword = ind>>4;
- ind_qpsk_symb = ind&0xf;
-
- *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
-
-
-#ifdef DEBUG_DL_UESPEC
- LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
- Ns,l,m,mprime_dword,mprime_qpsk_symb);
- LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
-#endif
-
- output_p+=5;
- ind++;
-
- w = Wbar_NCP[p-7][l];
- qpsk_p = (w==1) ? qpsk : nqpsk;
-
- // Fifth pilot
- ind_dword = ind>>4;
- ind_qpsk_symb = ind&0xf;
-
- *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
-
-#ifdef DEBUG_DL_UESPEC
- LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
- Ns,l,m,mprime_dword,mprime_qpsk_symb);
- LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
-#endif
-
- output_p+=5;
- ind++;
-
- w = Wbar_NCP[p-7][3-l];
- qpsk_p = (w==1) ? qpsk : nqpsk;
- // Sixth pilot
- ind_dword = ind>>4;
- ind_qpsk_symb = ind&0xf;
-
- *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
-
-#ifdef DEBUG_DL_UESPEC
- LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
- Ns,l,m,mprime_dword,mprime_qpsk_symb);
- LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
-#endif
-
- output_p+=2;
- ind++;
- }
+ k += 4;
+ if (k >= eNB->frame_parms.ofdm_symbol_size) {
+ k++; // skip DC carrier
+ k-=eNB->frame_parms.ofdm_symbol_size;
}
- } else {
- LOG_E(PHY,"Special subframe not supported for UE specific pilots yet\n");
+
+ }
}
}
- } else if (p==5) {
- LOG_E(PHY,"p=5 not supported for UE specific pilots yet\n");
+ } else if (p>=7) {
+ printf("lte_dl_ue_spec:antenna ports >=7 not supported yet!\n");
} else {
LOG_E(PHY,"Illegal p %d UE specific pilots\n",p);
}
return(0);
}
-
-/*
-int lte_dl_cell_spec_rx(PHY_VARS_UE *phy_vars_ue,
- uint8_t eNB_offset,
- int *output,
- unsigned char Ns,
- unsigned char l,
- unsigned char p) {
+*/
- unsigned char mprime,mprime_dword,mprime_qpsk_symb,m;
- unsigned short k=0;
- unsigned int qpsk[4];
+int lte_dl_ue_spec_rx(PHY_VARS_UE *ue,
+ int32_t *output,
+ unsigned char Ns,
+ unsigned char p,
+ int lprime,
+ int SS_flag,
+ uint16_t nRB_PDSCH)
+{
+ int32_t qpsk[4],nqpsk[4],*qpsk_p,*output_p;
+ int w,mprime,ind,l,ind_dword,ind_qpsk_symb,nPRB;
short pamp;
// Compute the correct pilot amplitude, sqrt_rho_b = Q3.13
pamp = ONE_OVER_SQRT2_Q15;
// This includes complex conjugate for channel estimation
-
((short *)&qpsk[0])[0] = pamp;
((short *)&qpsk[0])[1] = -pamp;
((short *)&qpsk[1])[0] = -pamp;
@@ -252,32 +149,169 @@ int lte_dl_cell_spec_rx(PHY_VARS_UE *phy_vars_ue,
((short *)&qpsk[3])[0] = -pamp;
((short *)&qpsk[3])[1] = pamp;
- mprime = 110 - phy_vars_ue->frame_parms.N_RB_DL;
+ ((short *)&nqpsk[0])[0] = -pamp;
+ ((short *)&nqpsk[0])[1] = pamp;
+ ((short *)&nqpsk[1])[0] = pamp;
+ ((short *)&nqpsk[1])[1] = pamp;
+ ((short *)&nqpsk[2])[0] = -pamp;
+ ((short *)&nqpsk[2])[1] = -pamp;
+ ((short *)&nqpsk[3])[0] = pamp;
+ ((short *)&nqpsk[3])[1] = -pamp;
- for (m=0;mframe_parms.N_RB_DL<<1;m++) {
+ if (p>=7) {
+ if (SS_flag==0) {
+ if (ue->frame_parms.Ncp == NORMAL) {
+ // this is 3GPP 36-211 6.10.3.2, NORMAL CP, p>=7
- mprime_dword = mprime>>4;
- mprime_qpsk_symb = mprime&0xf;
+ output_p = output;
- // this is r_mprime from 3GPP 36-211 6.10.1.2
- output[k] = qpsk[(phy_vars_ue->lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3];
-#ifdef DEBUG_DL_CELL_SPEC
- printf("Ns %d, l %d, m %d,mprime_dword %d, mprime_qpsk_symbol %d\n",
- Ns,l,m,mprime_dword,mprime_qpsk_symb);
- printf("index = %d (k %d)\n",(phy_vars_ue->lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k);
+ ind = 3*lprime*ue->frame_parms.N_RB_DL;
+ l = lprime + ((Ns&1)<<1);
+
+ // loop over pairs of PRBs, this is the periodicity of the W_bar_NCP sequence
+ // unroll the computations for the 6 pilots, select qpsk or nqpsk as function of W_bar_NCP
+ for (nPRB=0; nPRBframe_parms.N_RB_DL; nPRB+=2) {
+
+ // First pilot
+ w = Wbar_NCP[p-7][l];
+ qpsk_p = (w==1) ? qpsk : nqpsk;
+
+
+ ind_dword = ind>>4;
+ ind_qpsk_symb = ind&0xf;
+
+ *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+
+
+#ifdef DEBUG_DL_UESPEC
+ LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+ Ns,l,m,ind_dword,ind_qpsk_symb);
+ LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
#endif
- mprime++;
-#ifdef DEBUG_DL_CELL_SPEC
- if (m<4)
- printf("Ns %d l %d output[%d] = (%d,%d)\n",Ns,l,k,((short *)&output[k])[0],((short *)&output[k])[1]);
+ output_p++;
+ ind++;
+
+ w = Wbar_NCP[p-7][3-l];
+ qpsk_p = (w==1) ? qpsk : nqpsk;
+
+ // Second pilot
+ ind_dword = ind>>4;
+ ind_qpsk_symb = ind&0xf;
+
+ *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+
+#ifdef DEBUG_DL_UESPEC
+ LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+ Ns,l,m,ind_dword,ind_qpsk_symb);
+ LOG_D(PHY,"index = %d\n",(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
#endif
- k++;
+
+ output_p++;
+ ind++;
+
+ w = Wbar_NCP[p-7][l];
+ qpsk_p = (w==1) ? qpsk : nqpsk;
+ // Third pilot
+ ind_dword = ind>>4;
+ ind_qpsk_symb = ind&0xf;
+
+ *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+
+#ifdef DEBUG_DL_UESPEC
+ LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+ Ns,l,m,ind_dword,ind_qpsk_symb);
+ LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+#endif
+
+ output_p++;
+ ind++;
+
+ // Fourth pilot
+ w = Wbar_NCP[p-7][3-l];
+ qpsk_p = (w==1) ? qpsk : nqpsk;
+
+
+ ind_dword = ind>>4;
+ ind_qpsk_symb = ind&0xf;
+
+ *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+
+
+#ifdef DEBUG_DL_UESPEC
+ LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+ Ns,l,m,ind_dword,ind_qpsk_symb);
+ LOG_D(PHY,"index = %d\n",(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+#endif
+
+ output_p++;
+ ind++;
+
+ w = Wbar_NCP[p-7][l];
+ qpsk_p = (w==1) ? qpsk : nqpsk;
+
+ // Fifth pilot
+ ind_dword = ind>>4;
+ ind_qpsk_symb = ind&0xf;
+
+ *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+
+#ifdef DEBUG_DL_UESPEC
+ LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+ Ns,l,m,ind_dword,ind_qpsk_symb);
+ LOG_D(PHY,"index = %d\n",(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+#endif
+
+ output_p++;
+ ind++;
+
+ w = Wbar_NCP[p-7][3-l];
+ qpsk_p = (w==1) ? qpsk : nqpsk;
+ // Sixth pilot
+ ind_dword = ind>>4;
+ ind_qpsk_symb = ind&0xf;
+
+ *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+
+#ifdef DEBUG_DL_UESPEC
+ LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+ Ns,l,m,ind_dword,ind_qpsk_symb);
+ LOG_D(PHY,"index = %d\n",(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+#endif
+
+ output_p++;
+ ind++;
+ }
+ } else {
+ LOG_E(PHY,"Special subframe not supported for UE specific pilots yet\n");
+ }
+ }
+ } else if (p==5) {
+ if (SS_flag==0) {
+ output_p = output;
+
+ if (ue->frame_parms.Ncp == NORMAL) {
+ for (mprime=0;mprime<3*nRB_PDSCH;mprime++) {
+
+ ind = 3*lprime*nRB_PDSCH+mprime;
+ ind_dword = ind>>4;
+ ind_qpsk_symb = ind&0xf;
+
+ *output_p = qpsk[(ue->lte_gold_uespec_port5_table[Ns][ind_dword]>>(2*ind_qpsk_symb))&3];
+ //printf("lprime=%d,ind=%d,Ns=%d,output_p=(%d,%d)\n",lprime,ind,Ns,((short *)&output_p[0])[0],((short *)&output_p[0])[1]);
+ output_p++;
+
+ }
+ }
+ }
+ } else {
+ LOG_E(PHY,"Illegal p %d UE specific pilots\n",p);
}
+
return(0);
}
-*/
+
#ifdef LTE_DL_CELL_SPEC_MAIN
@@ -303,51 +337,51 @@ main()
lte_gold(Nid_cell,Ncp);
- lte_dl_cell_spec(output00,
- ONE_OVER_SQRT2_Q15,
- 50,
- Nid_cell,
- Ncp,
- 0,
- 0,
- 0,
- 0);
+ lte_dl_ue_spec(output00,
+ ONE_OVER_SQRT2_Q15,
+ 50,
+ Nid_cell,
+ Ncp,
+ 0,
+ 0,
+ 0,
+ 0);
- lte_dl_cell_spec(output10,
- ONE_OVER_SQRT2_Q15,
- 50,
- Nid_cell,
- Ncp,
- 0,
- 1,
- 0,
- 0);
+ lte_dl_ue_spec(output10,
+ ONE_OVER_SQRT2_Q15,
+ 50,
+ Nid_cell,
+ Ncp,
+ 0,
+ 1,
+ 0,
+ 0);
- lte_dl_cell_spec(output01,
- ONE_OVER_SQRT2_Q15,
- 50,
- Nid_cell,
- Ncp,
- 0,
- 0,
- 1,
- 0);
+ lte_dl_ue_spec(output01,
+ ONE_OVER_SQRT2_Q15,
+ 50,
+ Nid_cell,
+ Ncp,
+ 0,
+ 0,
+ 1,
+ 0);
- lte_dl_cell_spec(output11,
- ONE_OVER_SQRT2_Q15,
- 50,
- Nid_cell,
- Ncp,
- 0,
- 1,
- 1,
- 0);
+ lte_dl_ue_spec(output11,
+ ONE_OVER_SQRT2_Q15,
+ 50,
+ Nid_cell,
+ Ncp,
+ 0,
+ 1,
+ 1,
+ 0);
- write_output("dl_cell_spec00.m","dl_cs00",output00,1024,1,1);
- write_output("dl_cell_spec01.m","dl_cs01",output01,1024,1,1);
- write_output("dl_cell_spec10.m","dl_cs10",output10,1024,1,1);
- write_output("dl_cell_spec11.m","dl_cs11",output11,1024,1,1);
+ write_output("dl_ue_spec00.m","dl_cs00",output00,1024,1,1);
+ write_output("dl_ue_spec01.m","dl_cs01",output01,1024,1,1);
+ write_output("dl_ue_spec10.m","dl_cs10",output10,1024,1,1);
+ write_output("dl_ue_spec11.m","dl_cs11",output11,1024,1,1);
}
diff --git a/openair1/PHY/LTE_REFSIG/lte_gold.c b/openair1/PHY/LTE_REFSIG/lte_gold.c
index 3f0a09a27e..b15bc06cbd 100644
--- a/openair1/PHY/LTE_REFSIG/lte_gold.c
+++ b/openair1/PHY/LTE_REFSIG/lte_gold.c
@@ -131,6 +131,44 @@ void lte_gold_ue_spec(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_uespec_t
}
}
+void lte_gold_ue_spec_port5(uint32_t lte_gold_uespec_port5_table[20][38],uint16_t Nid_cell, uint16_t n_rnti)
+{
+
+ unsigned char ns;
+ unsigned int n,x1,x2;
+
+
+ for (ns=0; ns<20; ns++) {
+
+ x2 = ((((ns>>1)+1)*((Nid_cell<<1)+1))<<16) + n_rnti;
+ //x2 = frame_parms->Ncp + (Nid_cell<<1) + (1+(Nid_cell<<1))*(1 + (3*l) + (7*(1+ns))); //cinit
+ //n = 0
+ //printf("cinit (ns %d, l %d) => %d\n",ns,l,x2);
+ x1 = 1+ (1<<31);
+ x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31);
+
+ //skip first 50 double words (1600 bits)
+ //printf("n=0 : x1 %x, x2 %x\n",x1,x2);
+ for (n=1; n<50; n++) {
+ x1 = (x1>>1) ^ (x1>>4);
+ x1 = x1 ^ (x1<<31) ^ (x1<<28);
+ x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+ x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+ //printf("x1 : %x, x2 : %x\n",x1,x2);
+ }
+
+ for (n=0; n<38; n++) {
+ x1 = (x1>>1) ^ (x1>>4);
+ x1 = x1 ^ (x1<<31) ^ (x1<<28);
+ x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+ x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+ lte_gold_uespec_port5_table[ns][n] = x1^x2;
+ //printf("n=%d : c %x\n",n,x1^x2);
+ }
+
+ }
+}
+
/*! \brief gold sequenquence generator
\param x1
\param x2 this should be set to c_init if reset=1
diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c
index 24d533506c..7558367817 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci.c
@@ -66,7 +66,7 @@ uint32_t check_phich_reg(LTE_DL_FRAME_PARMS *frame_parms,uint32_t kprime,uint8_t
// compute REG based on symbol
if ((lprime == 0)||
- ((lprime==1)&&(frame_parms->nb_antennas_tx_eNB == 4)))
+ ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4)))
mprime = kprime/6;
else
mprime = kprime>>2;
@@ -293,7 +293,7 @@ void pdcch_interleaving(LTE_DL_FRAME_PARMS *frame_parms,int32_t **z, int32_t **w
for (row=0; row=ND) {
- for (a=0; anb_antennas_tx_eNB; a++) {
+ for (a=0; anb_antenna_ports_eNB; a++) {
//printf("a %d k %d\n",a,k);
wptr = &wtemp[a][k<<2];
@@ -317,7 +317,7 @@ void pdcch_interleaving(LTE_DL_FRAME_PARMS *frame_parms,int32_t **z, int32_t **w
// permutation
for (i=0; inb_antennas_tx_eNB; a++) {
+ for (a=0; anb_antenna_ports_eNB; a++) {
//wptr = &wtemp[a][i<<2];
//wptr2 = &wbar[a][((i+frame_parms->Nid_cell)%Mquad)<<2];
@@ -409,7 +409,7 @@ void pdcch_demapping(uint16_t *llr,uint16_t *wbar,LTE_DL_FRAME_PARMS *frame_parm
re_offset0++;
}
}
- } else if ((lprime==1)&&(frame_parms->nb_antennas_tx_eNB == 4)) {
+ } else if ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4)) {
// LATER!!!!
} else { // no pilots in this symbol
kprime_mod12 = kprime%12;
@@ -647,7 +647,7 @@ void pdcch_channel_level(int32_t **dl_ch_estimates_ext,
int16x8_t *dl_ch128;
int32x4_t *avg128P;
#endif
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++)
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++)
for (aarx=0; aarxnb_antennas_rx; aarx++) {
//clear average level
#if defined(__x86_64__) || defined(__i386__)
@@ -825,7 +825,7 @@ void pdcch_detection_mrc_i(LTE_DL_FRAME_PARMS *frame_parms,
int32_t i;
if (frame_parms->nb_antennas_rx>1) {
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++) {
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++) {
//if (frame_parms->mode1_flag && (aatx>0)) break;
#if defined(__x86_64__) || defined(__i386__)
@@ -1126,6 +1126,9 @@ void pdcch_extract_rbs_dual(int32_t **rxdataF,
int nushiftmod3 = frame_parms->nushift%3;
symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
+#ifdef DEBUG_DCI_DECODING
+ LOG_I(PHY, "extract_rbs_dual: symbol_mod %d\n",symbol_mod);
+#endif
for (aarx=0; aarxnb_antennas_rx; aarx++) {
@@ -1388,8 +1391,8 @@ void pdcch_channel_compensation(int32_t **rxdataF_ext,
if (symbol==0)
pilots=1;
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++) {
- //if (frame_parms->mode1_flag && aatx>0) break; //if mode1_flag is set then there is only one stream to extract, independent of nb_antennas_tx_eNB
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++) {
+ //if (frame_parms->mode1_flag && aatx>0) break; //if mode1_flag is set then there is only one stream to extract, independent of nb_antenna_ports_eNB
for (aarx=0; aarxnb_antennas_rx; aarx++) {
@@ -1595,7 +1598,7 @@ void pdcch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms,
int32_t i;
if (frame_parms->nb_antennas_rx>1) {
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++) {
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++) {
#if defined(__x86_64__) || defined(__i386__)
rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12];
rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12];
@@ -1716,7 +1719,7 @@ int32_t rx_pdcch(LTE_UE_COMMON *common_vars,
high_speed_flag,
frame_parms);
#endif //MU_RECEIVER
- } else if (frame_parms->nb_antennas_tx_eNB>1) {
+ } else if (frame_parms->nb_antenna_ports_eNB>1) {
pdcch_extract_rbs_dual(common_vars->rxdataF,
common_vars->dl_ch_estimates[eNB_id],
pdcch_vars[eNB_id]->rxdataF_ext,
@@ -1742,7 +1745,7 @@ int32_t rx_pdcch(LTE_UE_COMMON *common_vars,
avgs = 0;
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++)
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++)
for (aarx=0; aarxnb_antennas_rx; aarx++)
avgs = cmax(avgs,avgP[(aarx<<1)+aatx]);
@@ -1983,10 +1986,10 @@ uint8_t get_num_pdcch_symbols(uint8_t num_dci,
//if ((9*numCCE) <= (frame_parms->N_RB_DL*2))
if (numCCE <= get_nCCE(1, frame_parms, get_mi(frame_parms, subframe)))
return(cmax(1,nCCEmin));
- //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 4 : 5)))
+ //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 4 : 5)))
else if (numCCE <= get_nCCE(2, frame_parms, get_mi(frame_parms, subframe)))
return(cmax(2,nCCEmin));
- //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 7 : 8)))
+ //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 7 : 8)))
else if (numCCE <= get_nCCE(3, frame_parms, get_mi(frame_parms, subframe)))
return(cmax(3,nCCEmin));
else if (frame_parms->N_RB_DL<=10) {
@@ -1996,10 +1999,10 @@ uint8_t get_num_pdcch_symbols(uint8_t num_dci,
get_nCCE(2, frame_parms, get_mi(frame_parms, subframe)),
get_nCCE(3, frame_parms, get_mi(frame_parms, subframe)));
- if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 10 : 11)))
+ if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 10 : 11)))
return(4);
} else { // extended CP
- if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 9 : 10)))
+ if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 9 : 10)))
return(4);
}
}
@@ -2244,7 +2247,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
// Copy REG to TX buffer
if ((lprime == 0)||
- ((lprime==1)&&(frame_parms->nb_antennas_tx_eNB == 4))) {
+ ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4))) {
// first symbol, or second symbol+4 TX antennas skip pilots
kprime_mod12 = kprime%12;
@@ -2256,7 +2259,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
if ((i!=(nushiftmod3))&&(i!=(nushiftmod3+3))) {
txdataF[0][tti_offset+i] = wbar[0][mprime];
- if (frame_parms->nb_antennas_tx_eNB > 1)
+ if (frame_parms->nb_antenna_ports_eNB > 1)
txdataF[1][tti_offset+i] = wbar[1][mprime];
#ifdef DEBUG_DCI_ENCODING
@@ -2276,7 +2279,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
for (i=0; i<4; i++) {
txdataF[0][tti_offset+i] = wbar[0][mprime];
- if (frame_parms->nb_antennas_tx_eNB > 1)
+ if (frame_parms->nb_antenna_ports_eNB > 1)
txdataF[1][tti_offset+i] = wbar[1][mprime];
#ifdef DEBUG_DCI_ENCODING
@@ -2287,7 +2290,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
} else {
txdataF[0][tti_offset+0] = wbar[0][mprime];
- if (frame_parms->nb_antennas_tx_eNB > 1)
+ if (frame_parms->nb_antenna_ports_eNB > 1)
txdataF[1][tti_offset+0] = wbar[1][mprime];
#ifdef DEBUG_DCI_ENCODING
@@ -2296,7 +2299,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
mprime++;
txdataF[0][tti_offset+1] = wbar[0][mprime];
- if (frame_parms->nb_antennas_tx_eNB > 1)
+ if (frame_parms->nb_antenna_ports_eNB > 1)
txdataF[1][tti_offset+1] = wbar[1][mprime];
#ifdef DEBUG_DCI_ENCODING
@@ -2305,7 +2308,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
mprime++;
txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[0][mprime];
- if (frame_parms->nb_antennas_tx_eNB > 1)
+ if (frame_parms->nb_antenna_ports_eNB > 1)
txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[1][mprime];
#ifdef DEBUG_DCI_ENCODING
@@ -2315,7 +2318,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
mprime++;
txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[0][mprime];
- if (frame_parms->nb_antennas_tx_eNB > 1)
+ if (frame_parms->nb_antenna_ports_eNB > 1)
txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[1][mprime];
#ifdef DEBUG_DCI_ENCODING
@@ -2679,11 +2682,15 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars,
nCCE = get_nCCE(pdcch_vars[eNB_id]->num_pdcch_symbols,frame_parms,mi);
- if (nCCE > get_nCCE(3,frame_parms,1))
+ if (nCCE > get_nCCE(3,frame_parms,1)) {
+ LOG_D(PHY,"skip DCI decoding: nCCE=%d > get_nCCE(3,frame_parms,1)=%d\n", nCCE, get_nCCE(3,frame_parms,1));
return;
+ }
- if (nCCEnCCE[subframe]);
+ LOG_D(PHY,"DCI decoding CRNTI [format: %d, nCCE[subframe: %d]: %d ], AggregationLevel %d \n",format_c, subframe, pdcch_vars[eNB_id]->nCCE[subframe],L2);
// memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_decoded_output,sizeof_bytes);
@@ -2929,12 +2936,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
format1_size_bits = sizeof_DCI1_1_5MHz_TDD_t;
format1_size_bytes = sizeof(DCI1_1_5MHz_TDD_t);
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
format2_size_bits = sizeof_DCI2_1_5MHz_2A_TDD_t;
format2_size_bytes = sizeof(DCI2_1_5MHz_2A_TDD_t);
format2A_size_bits = sizeof_DCI2A_1_5MHz_2A_TDD_t;
format2A_size_bytes = sizeof(DCI2A_1_5MHz_2A_TDD_t);
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
format2_size_bits = sizeof_DCI2_1_5MHz_4A_TDD_t;
format2_size_bytes = sizeof(DCI2_1_5MHz_4A_TDD_t);
format2A_size_bits = sizeof_DCI2A_1_5MHz_4A_TDD_t;
@@ -2950,12 +2957,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
format1_size_bits = sizeof_DCI1_1_5MHz_FDD_t;
format1_size_bytes = sizeof(DCI1_1_5MHz_FDD_t);
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
format2_size_bits = sizeof_DCI2_1_5MHz_2A_FDD_t;
format2_size_bytes = sizeof(DCI2_1_5MHz_2A_FDD_t);
format2A_size_bits = sizeof_DCI2A_1_5MHz_2A_FDD_t;
format2A_size_bytes = sizeof(DCI2A_1_5MHz_2A_FDD_t);
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
format2_size_bits = sizeof_DCI2_1_5MHz_4A_FDD_t;
format2_size_bytes = sizeof(DCI2_1_5MHz_4A_FDD_t);
format2A_size_bits = sizeof_DCI2A_1_5MHz_4A_FDD_t;
@@ -2977,12 +2984,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
format1_size_bits = sizeof_DCI1_5MHz_TDD_t;
format1_size_bytes = sizeof(DCI1_5MHz_TDD_t);
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
format2_size_bits = sizeof_DCI2_5MHz_2A_TDD_t;
format2_size_bytes = sizeof(DCI2_5MHz_2A_TDD_t);
format2A_size_bits = sizeof_DCI2A_5MHz_2A_TDD_t;
format2A_size_bytes = sizeof(DCI2A_5MHz_2A_TDD_t);
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
format2_size_bits = sizeof_DCI2_5MHz_4A_TDD_t;
format2_size_bytes = sizeof(DCI2_5MHz_4A_TDD_t);
format2A_size_bits = sizeof_DCI2A_5MHz_4A_TDD_t;
@@ -2998,12 +3005,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
format1_size_bits = sizeof_DCI1_5MHz_FDD_t;
format1_size_bytes = sizeof(DCI1_5MHz_FDD_t);
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
format2_size_bits = sizeof_DCI2_5MHz_2A_FDD_t;
format2_size_bytes = sizeof(DCI2_5MHz_2A_FDD_t);
format2A_size_bits = sizeof_DCI2A_5MHz_2A_FDD_t;
format2A_size_bytes = sizeof(DCI2A_5MHz_2A_FDD_t);
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
format2_size_bits = sizeof_DCI2_5MHz_4A_FDD_t;
format2_size_bytes = sizeof(DCI2_5MHz_4A_FDD_t);
format2A_size_bits = sizeof_DCI2A_5MHz_4A_FDD_t;
@@ -3024,12 +3031,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
format1_size_bits = sizeof_DCI1_10MHz_TDD_t;
format1_size_bytes = sizeof(DCI1_10MHz_TDD_t);
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
format2_size_bits = sizeof_DCI2_10MHz_2A_TDD_t;
format2_size_bytes = sizeof(DCI2_10MHz_2A_TDD_t);
format2A_size_bits = sizeof_DCI2A_10MHz_2A_TDD_t;
format2A_size_bytes = sizeof(DCI2A_10MHz_2A_TDD_t);
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
format2_size_bits = sizeof_DCI2_10MHz_4A_TDD_t;
format2_size_bytes = sizeof(DCI2_10MHz_4A_TDD_t);
format2A_size_bits = sizeof_DCI2A_10MHz_4A_TDD_t;
@@ -3045,12 +3052,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
format1_size_bits = sizeof_DCI1_10MHz_FDD_t;
format1_size_bytes = sizeof(DCI1_10MHz_FDD_t);
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
format2_size_bits = sizeof_DCI2_10MHz_2A_FDD_t;
format2_size_bytes = sizeof(DCI2_10MHz_2A_FDD_t);
format2A_size_bits = sizeof_DCI2A_10MHz_2A_FDD_t;
format2A_size_bytes = sizeof(DCI2A_10MHz_2A_FDD_t);
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
format2_size_bits = sizeof_DCI2_10MHz_4A_FDD_t;
format2_size_bytes = sizeof(DCI2_10MHz_4A_FDD_t);
format2A_size_bits = sizeof_DCI2A_10MHz_4A_FDD_t;
@@ -3071,12 +3078,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
format1_size_bits = sizeof_DCI1_20MHz_TDD_t;
format1_size_bytes = sizeof(DCI1_20MHz_TDD_t);
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
format2_size_bits = sizeof_DCI2_20MHz_2A_TDD_t;
format2_size_bytes = sizeof(DCI2_20MHz_2A_TDD_t);
format2A_size_bits = sizeof_DCI2A_20MHz_2A_TDD_t;
format2A_size_bytes = sizeof(DCI2A_20MHz_2A_TDD_t);
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
format2_size_bits = sizeof_DCI2_20MHz_4A_TDD_t;
format2_size_bytes = sizeof(DCI2_20MHz_4A_TDD_t);
format2A_size_bits = sizeof_DCI2A_20MHz_4A_TDD_t;
@@ -3092,12 +3099,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
format1_size_bits = sizeof_DCI1_20MHz_FDD_t;
format1_size_bytes = sizeof(DCI1_20MHz_FDD_t);
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
format2_size_bits = sizeof_DCI2_20MHz_2A_FDD_t;
format2_size_bytes = sizeof(DCI2_20MHz_2A_FDD_t);
format2A_size_bits = sizeof_DCI2A_20MHz_2A_FDD_t;
format2A_size_bytes = sizeof(DCI2A_20MHz_2A_FDD_t);
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
format2_size_bits = sizeof_DCI2_20MHz_4A_FDD_t;
format2_size_bytes = sizeof(DCI2_20MHz_4A_FDD_t);
format2A_size_bits = sizeof_DCI2A_20MHz_4A_FDD_t;
@@ -3248,7 +3255,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
SI_RNTI,
ra_rnti,
P_RNTI,
- 3,
+ 0,
format1A,
format1A,
format1A,
@@ -3277,7 +3284,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
SI_RNTI,
ra_rnti,
P_RNTI,
- 2,
+ 1,
format1A,
format1A,
format1A,
@@ -3310,7 +3317,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
SI_RNTI,
ra_rnti,
P_RNTI,
- 1,
+ 2,
format1A,
format1A,
format1A,
@@ -3339,7 +3346,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
SI_RNTI,
ra_rnti,
P_RNTI,
- 0,
+ 3,
format1A,
format1A,
format1A,
@@ -3361,7 +3368,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
// These are for CRNTI based on transmission mode
- if (tmode < 3) {
+ if ((tmode < 3) || (tmode == 7)) {
// Now check UE_SPEC format 1 search spaces at aggregation 1
old_dci_cnt=dci_cnt;
dci_decoding_procedure0(pdcch_vars,0,subframe,
@@ -3730,7 +3737,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
&CCEmap1,
&CCEmap2);
//#endif
- } else if (tmode >=5) { // This is MU-MIMO
+ } else if ((tmode==5) || (tmode==6)) { // This is MU-MIMO
// Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 1
#ifdef DEBUG_DCI_DECODING
diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
index f66ec5fe4b..1dfbc9d7df 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
@@ -36,7 +36,10 @@
#include "PHY/vars.h"
#endif
#include "assertions.h"
-
+
+#include "LAYER2/MAC/extern.h"
+#include "LAYER2/MAC/defs.h"
+
//#define DEBUG_DCI
uint32_t localRIV2alloc_LUT6[32];
@@ -862,7 +865,8 @@ int generate_eNB_dlsch_params_from_dci(int frame,
uint16_t si_rnti,
uint16_t ra_rnti,
uint16_t p_rnti,
- uint16_t DL_pmi_single)
+ uint16_t DL_pmi_single,
+ uint8_t beamforming_mode)
{
uint8_t harq_pid = UINT8_MAX;
@@ -1230,7 +1234,13 @@ int generate_eNB_dlsch_params_from_dci(int frame,
dlsch0_harq->Nl = 1;
// dlsch[0]->layer_index = 0;
- dlsch0_harq->mimo_mode = (frame_parms->mode1_flag == 1) ? SISO : ALAMOUTI;
+ if (beamforming_mode == 0)
+ dlsch0_harq->mimo_mode = (frame_parms->mode1_flag == 1) ? SISO : ALAMOUTI;
+ else if (beamforming_mode == 7)
+ dlsch0_harq->mimo_mode = TM7;
+ else
+ LOG_E(PHY,"Invalid beamforming mode %dL\n", beamforming_mode);
+
dlsch0_harq->dl_power_off = 1;
/*
if (dlsch[0]->harq_processes[harq_pid]->first_tx == 1) {
@@ -1260,6 +1270,11 @@ int generate_eNB_dlsch_params_from_dci(int frame,
dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][NPRB-1];
}
+ else
+ {
+ LOG_E(PHY,"DL Received HarqReTx round=%d mcs=%d rballoc=%d rv=%d \n",
+ dlsch0_harq->round,mcs,rballoc,rv);
+ }
dlsch[0]->current_harq_pid = harq_pid;
@@ -2674,7 +2689,7 @@ int generate_eNB_dlsch_params_from_dci(int frame,
// compute DL power control parameters
computeRhoA_eNB(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off);
- computeRhoB_eNB(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antennas_tx_eNB,dlsch[0],dlsch0_harq->dl_power_off);
+ computeRhoB_eNB(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antenna_ports_eNB,dlsch[0],dlsch0_harq->dl_power_off);
return(0);
}
@@ -3440,7 +3455,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci)
if ((frame_parms->frame_type == TDD) &&
(frame_parms->tdd_config>0)) {
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
switch(frame_parms->N_RB_DL) {
case 6:
LOG_D(PHY,"DCI format2A 2 antennas (FDD 1.5 MHz), rnti %x (%x): rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d\n",
@@ -3519,7 +3534,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci)
DevParam (frame_parms->N_RB_DL, 0, 0);
break;
}
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
switch(frame_parms->N_RB_DL) {
case 6:
LOG_D(PHY,"DCI format2A 4 antennas (TDD 1.5 MHz), rnti %x (%llx): rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d, tpmi %d\n",
@@ -3604,7 +3619,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci)
}
}
} else if (frame_parms->frame_type == FDD) {
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
switch(frame_parms->N_RB_DL) {
case 6:
LOG_D(PHY,"DCI format2A 2 antennas (FDD, 1.5 MHz), rnti %x (%x): rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, TPC %d\n",
@@ -3678,7 +3693,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci)
DevParam (frame_parms->N_RB_DL, 0, 0);
break;
}
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
switch(frame_parms->N_RB_DL) {
case 6:
@@ -3802,7 +3817,8 @@ int generate_ue_dlsch_params_from_dci(int frame,
PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated,
uint16_t si_rnti,
uint16_t ra_rnti,
- uint16_t p_rnti)
+ uint16_t p_rnti,
+ uint8_t beamforming_mode)
{
uint8_t harq_pid=0;
@@ -3917,10 +3933,10 @@ int generate_ue_dlsch_params_from_dci(int frame,
dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
} else {
- if (harq_pid>1) {
- LOG_E(PHY,"Format 1A: harq_pid > 1\n");
- return(-1);
- }
+ //if (harq_pid>1) {
+ // LOG_E(PHY,"Format 1A: harq_pid > 1\n");
+ // return(-1);
+ //}
dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
NPRB = RIV2nb_rb_LUT25[rballoc];
@@ -4119,6 +4135,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
dlsch0_harq->rvidx = rv;
dlsch0_harq->Nl = 1;
// dlsch[0]->layer_index = 0;
+
dlsch0_harq->mimo_mode = frame_parms->mode1_flag == 1 ?SISO : ALAMOUTI;
dlsch0_harq->dl_power_off = 1; //no power offset
@@ -4143,6 +4160,20 @@ int generate_ue_dlsch_params_from_dci(int frame,
dlsch0_harq->DCINdi = ndi;
+ // this a retransmission
+ if(dlsch0_harq->round)
+ {
+ // compare old TBS to new TBS
+ if(dlsch0_harq->TBS != TBStable[get_I_TBS(mcs)][NPRB-1])
+ {
+ // this is an eNB issue
+ // retransmisison but old and new TBS are different !!!
+ // work around, consider it as a new transmission
+ LOG_E(PHY,"Format1A Retransmission but TBS are different: consider it as new transmission !!! \n");
+ dlsch0_harq->round = 0;
+ }
+ }
+
dlsch0_harq->mcs = mcs;
if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) {
dlsch0_harq->TBS = TBStable[mcs][NPRB-1];
@@ -4434,6 +4465,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
dlsch0_harq->status = ACTIVE;
dlsch0_harq->DCINdi = ndi;
+ dlsch[0]->harq_ack[subframe].send_harq_status = 1;
if (dlsch0_harq->first_tx==1) {
LOG_D(PHY,"[PDSCH %x/%d] Format 1 DCI First TX: Clearing flag\n");
dlsch0_harq->first_tx = 0;
@@ -4452,6 +4484,20 @@ int generate_ue_dlsch_params_from_dci(int frame,
dlsch0_harq->mcs = mcs;
+ // this a retransmission
+ if(dlsch0_harq->round)
+ {
+ // compare old TBS to new TBS
+ if(dlsch0_harq->TBS != TBStable[get_I_TBS(mcs)][NPRB-1])
+ {
+ // this is an eNB issue
+ // retransmisison but old and new TBS are different !!!
+ // work around, consider it as a new transmission
+ LOG_E(PHY,"Format1 Retransmission but TBS are different: consider it as new transmission !!! \n");
+ dlsch0_harq->round = 0;
+ }
+ }
+
dlsch0_harq->TBS = TBStable[get_I_TBS(mcs)][NPRB-1];
if (mcs <= 28)
dlsch0_harq->Qm = get_Qm(mcs);
@@ -4466,7 +4512,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
dlsch[0]->rnti = rnti;
- dlsch0_harq->mimo_mode = (frame_parms->mode1_flag == 1) ? SISO : ALAMOUTI;
+ if (beamforming_mode == 0)
+ dlsch0_harq->mimo_mode = (frame_parms->mode1_flag == 1) ? SISO : ALAMOUTI;
+ else if (beamforming_mode == 7)
+ dlsch0_harq->mimo_mode = TM7;
+ else
+ LOG_E(PHY,"Not supported beamforming mode %d\n",beamforming_mode);
+
dlsch0 = dlsch[0];
@@ -4476,7 +4528,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
switch (frame_parms->N_RB_DL) {
case 6:
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
if (frame_type == TDD) {
mcs1 = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4496,7 +4548,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
tbswap = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->tb_swap;
tpmi = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->tpmi;
}
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
if (frame_type == TDD) {
mcs1 = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4517,13 +4569,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
tpmi = ((DCI2_1_5MHz_4A_FDD_t *)dci_pdu)->tpmi;
}
} else {
- LOG_E(PHY,"UE: subframe %d Format2 DCI: unsupported number of TX antennas %d\n",subframe,frame_parms->nb_antennas_tx_eNB);
+ LOG_E(PHY,"UE: subframe %d Format2 DCI: unsupported number of TX antennas %d\n",subframe,frame_parms->nb_antenna_ports_eNB);
}
break;
case 25:
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
if (frame_type == TDD) {
mcs1 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4545,7 +4597,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
tbswap = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tb_swap;
tpmi = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tpmi;
}
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
if (frame_type == TDD) {
mcs1 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4568,13 +4620,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
tpmi = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->tpmi;
}
} else {
- LOG_E(PHY,"UE: Format2 DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antennas_tx_eNB);
+ LOG_E(PHY,"UE: Format2 DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antenna_ports_eNB);
}
break;
case 50:
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
if (frame_type == TDD) {
mcs1 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4596,7 +4648,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
tbswap = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tb_swap;
tpmi = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tpmi;
}
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
if (frame_type == TDD) {
mcs1 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4619,13 +4671,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
tpmi = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->tpmi;
}
} else {
- LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antennas_tx_eNB);
+ LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antenna_ports_eNB);
}
break;
case 100:
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
if (frame_type == TDD) {
mcs1 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4647,7 +4699,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
tbswap = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tb_swap;
tpmi = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tpmi;
}
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
if (frame_type == TDD) {
mcs1 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4670,7 +4722,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
tpmi = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->tpmi;
}
} else {
- LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antennas_tx_eNB);
+ LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antenna_ports_eNB);
}
break;
@@ -4865,7 +4917,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
switch (frame_parms->N_RB_DL) {
case 6:
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
if (frame_type == TDD) {
mcs1 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4887,7 +4939,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
harq_pid = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->harq_pid;
tbswap = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->tb_swap;
}
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
if (frame_type == TDD) {
mcs1 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4912,13 +4964,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
tpmi = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->tpmi;
}
} else {
- LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antennas_tx_eNB);
+ LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB);
}
break;
case 25:
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
if (frame_type == TDD) {
mcs1 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4942,7 +4994,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
harq_pid = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->harq_pid;
tbswap = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->tb_swap;
}
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
if (frame_type == TDD) {
mcs1 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4969,13 +5021,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
tpmi = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->tpmi;
}
} else {
- LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antennas_tx_eNB);
+ LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB);
}
break;
case 50:
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
if (frame_type == TDD) {
mcs1 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4999,7 +5051,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
harq_pid = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->harq_pid;
tbswap = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->tb_swap;
}
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
if (frame_type == TDD) {
mcs1 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -5026,13 +5078,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
tpmi = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->tpmi;
}
} else {
- LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antennas_tx_eNB);
+ LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB);
}
break;
case 100:
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
if (frame_type == TDD) {
mcs1 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -5056,7 +5108,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
harq_pid = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->harq_pid;
tbswap = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->tb_swap;
}
- } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) {
if (frame_type == TDD) {
mcs1 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->mcs1;
mcs2 = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -5083,7 +5135,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
tpmi = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->tpmi;
}
} else {
- LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antennas_tx_eNB);
+ LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB);
}
break;
@@ -5226,7 +5278,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
}
}
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
dlsch0_harq->TBS = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1];
dlsch1_harq->TBS = TBStable[get_I_TBS(dlsch1_harq->mcs)][dlsch0_harq->nb_rb-1];
@@ -5241,7 +5293,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
dlsch0_harq->mimo_mode = ALAMOUTI;
dlsch1_harq->mimo_mode = ALAMOUTI;
}
- } else if (frame_parms->nb_antennas_tx_eNB == 4) { // 4 antenna case
+ } else if (frame_parms->nb_antenna_ports_eNB == 4) { // 4 antenna case
if ((dlsch0->active==1) && (dlsch1->active==1)) {
switch (tpmi) {
case 0: // one layer per transport block
@@ -5325,7 +5377,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
}
}
} else {
- LOG_E(PHY,"Illegal number of antennas for eNB %d\n",frame_parms->nb_antennas_tx_eNB);
+ LOG_E(PHY,"Illegal number of antennas for eNB %d\n",frame_parms->nb_antenna_ports_eNB);
}
if (mcs1 <= 28)
@@ -5519,7 +5571,8 @@ int generate_ue_dlsch_params_from_dci(int frame,
#ifdef DEBUG_DCI
- if (dlsch[0]) {
+ if (dlsch[0] && (dlsch[0]->rnti != 0xffff)) {
+ printf("dci_format:%d Abssubframe: %d.%d \n",dci_format,frame,subframe);
printf("PDSCH dlsch0 UE: rnti %x\n",dlsch[0]->rnti);
printf("PDSCH dlsch0 UE: NBRB %d\n",dlsch0_harq->nb_rb);
printf("PDSCH dlsch0 UE: rballoc %x\n",dlsch0_harq->rb_alloc_even[0]);
@@ -5537,7 +5590,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
// compute DL power control parameters
computeRhoA_UE(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off);
- computeRhoB_UE(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antennas_tx_eNB,dlsch[0],dlsch0_harq->dl_power_off);
+ computeRhoB_UE(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antenna_ports_eNB,dlsch[0],dlsch0_harq->dl_power_off);
return(0);
}
@@ -6194,13 +6247,22 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
uint8_t harq_pid;
uint8_t transmission_mode = ue->transmission_mode[eNB_id];
- ANFBmode_t AckNackFBMode = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode;
+ ANFBmode_t AckNackFBMode;
LTE_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id];
// LTE_UE_DLSCH_t **dlsch = ue->dlsch[0];
PHY_MEASUREMENTS *meas = &ue->measurements;
LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
// uint32_t current_dlsch_cqi = ue->current_dlsch_cqi[eNB_id];
+ if(frame_parms->frame_type == TDD)
+ {
+ AckNackFBMode = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode;
+ }
+ else
+ {
+ AckNackFBMode = 1; // 1: multiplexing for FDD
+ }
+
uint32_t cqi_req;
uint32_t dai=0;
uint32_t cshift;
@@ -6351,8 +6413,10 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
if (rballoc > RIV_max) {
- LOG_E(PHY,"frame %d, subframe %d, rnti %x, format %d: FATAL ERROR: generate_ue_ulsch_params_from_dci, rb_alloc > RIV_max\n",
- proc->frame_rx, subframe, rnti, dci_format);
+ LOG_E(PHY,"frame %d, subframe %d, rnti %x, format %d: FATAL ERROR: generate_ue_ulsch_params_from_dci, rb_alloc[%d] > RIV_max[%d]\n",
+ proc->frame_rx, subframe, rnti, dci_format,rballoc,RIV_max);
+ LOG_E(PHY,"Wrong DCI0 detection, do not transmit PUSCH for HARQID: %d\n",harq_pid);
+ ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
return(-1);
}
@@ -6361,7 +6425,11 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
if ((rnti >= cba_rnti) && (rnti < p_rnti))
ulsch->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1; //+=1 this indicates the number of dci / cba group: not supported in the data struct
else
- ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
+ {
+ ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
+ //LOG_I(PHY,"[HARQ-UL harqId: %d] DCI0 ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, ulsch->harq_processes[harq_pid]->round);
+
+ }
ulsch->harq_processes[harq_pid]->TPC = TPC;
@@ -6391,7 +6459,42 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
ulsch->harq_processes[harq_pid]->round = 0;
} else {
// ulsch->harq_processes[harq_pid]->Ndi = 0;
- // ulsch->harq_processes[harq_pid]->round++; // This is done in phich RX
+ //ulsch->harq_processes[harq_pid]->round++; // This is done in phich RX
+
+ //#ifdef DEBUG_PHICH
+ //LOG_I(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d Adaptative Retrans, NDI not toggled => Nack. maxHARQ_Tx %d \n",
+ // ue->Mod_id,harq_pid,
+ // proc->frame_rx,
+ // subframe,
+ // ulsch->Mlimit);
+ //#endif
+/*
+ if (ulsch->harq_processes[harq_pid]->round > 0) // NACK detected on phich
+ {
+ // ulsch->harq_processes[harq_pid]->round++; already done on phich_rx
+ // ulsch->harq_processes[harq_pid] = ulsch->harq_processes[8];
+ // LOG_I(PHY," Adaptative retransmission - copy temporary harq Process to current harq process. [harqId %d round %d] \n",harq_pid, ulsch->harq_processes[8]->round);
+
+ if (ulsch->harq_processes[harq_pid]->round >= ulsch->Mlimit) //UE_mac_inst[eNB_id].scheduling_info.maxHARQ_Tx)
+ {
+ ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
+ ulsch->harq_processes[harq_pid]->round = 0;
+ ulsch->harq_processes[harq_pid]->status = IDLE;
+ //LOG_I(PHY," PUSCH MAX Retransmission acheived ==> flush harq buff (%d) \n",harq_pid);
+ //LOG_I(PHY," [HARQ-UL harqId: %d] Adaptative retransmission NACK MAX RETRANS(%d) ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, UE_mac_inst[eNB_id].scheduling_info.maxHARQ_Tx, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, ulsch->harq_processes[harq_pid]->round);
+ }
+ else
+ {
+ // ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
+ uint8_t rv_table[4] = {0, 2, 3, 1};
+ ulsch->harq_processes[harq_pid]->rvidx = rv_table[ulsch->harq_processes[harq_pid]->round&3];
+ ulsch->O_RI = 0;
+ ulsch->O = 0;
+ ulsch->uci_format = HLC_subband_cqi_nopmi;
+ //LOG_I(PHY," [HARQ-UL harqId: %d] Adaptative retransmission NACK ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag,ulsch->harq_processes[harq_pid]->round);
+ }
+ }
+*/
}
}
@@ -6441,7 +6544,16 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
if (cqi_req == 1) {
- ulsch->O_RI = 1; //we only support 2 antenna ports, so this is always 1 according to 3GPP 36.213 Table
+
+ if( (AntennaInfoDedicated__transmissionMode_tm3 == transmission_mode) || (AntennaInfoDedicated__transmissionMode_tm4 == transmission_mode) )
+ {
+ ulsch->O_RI = 1;
+ }
+ else
+ {
+ ulsch->O_RI = 0;
+ }
+ //ulsch->O_RI = 0; //we only support 2 antenna ports, so this is always 1 according to 3GPP 36.213 Table
switch(transmission_mode) {
// The aperiodic CQI reporting mode is fixed for every transmission mode instead of being configured by higher layer signaling
@@ -7001,15 +7113,19 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
// ulsch->n_DMRS2 = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift;
-#ifdef DEBUG_DCI
+ #ifdef DEBUG_DCI
+ printf("Format 0 DCI : ulsch (ue): AbsSubframe %d.%d\n",proc->frame_rx,subframe);
printf("Format 0 DCI : ulsch (ue): NBRB %d\n",ulsch->harq_processes[harq_pid]->nb_rb);
printf("Format 0 DCI :ulsch (ue): first_rb %d\n",ulsch->harq_processes[harq_pid]->first_rb);
+ printf("Format 0 DCI :ulsch (ue): rballoc %d\n",rballoc);
printf("Format 0 DCI :ulsch (ue): harq_pid %d\n",harq_pid);
+ printf("Format 0 DCI :ulsch (ue): first_tx %d\n",ulsch->harq_processes[harq_pid]->first_tx);
+ printf("Format 0 DCI :ulsch (ue): DCINdi %d\n",ulsch->harq_processes[harq_pid]->DCINdi);
printf("Format 0 DCI :ulsch (ue): round %d\n",ulsch->harq_processes[harq_pid]->round);
printf("Format 0 DCI :ulsch (ue): TBS %d\n",ulsch->harq_processes[harq_pid]->TBS);
printf("Format 0 DCI :ulsch (ue): mcs %d\n",ulsch->harq_processes[harq_pid]->mcs);
printf("Format 0 DCI :ulsch (ue): O %d\n",ulsch->O);
-
+ printf("Format 0 DCI :ulsch (ue): cqiReq %d\n",cqi_req);
if (frame_parms->frame_type == TDD)
printf("Format 0 DCI :ulsch (ue): O_ACK/DAI %d/%d\n",ulsch->harq_processes[harq_pid]->O_ACK,dai);
else
@@ -7017,6 +7133,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
printf("Format 0 DCI :ulsch (ue): Nsymb_pusch %d\n",ulsch->Nsymb_pusch);
printf("Format 0 DCI :ulsch (ue): cshift %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2);
+ printf("Format 0 DCI :ulsch (ue): phich status %d\n",ulsch->harq_processes[harq_pid]->status);
#else
UNUSED_VARIABLE(dai);
#endif
@@ -7689,7 +7806,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
switch(transmission_mode) {
case 1:
for (count=0; countN_RB_DL*12; count++) {
- for(a_tx=0; a_txnb_antennas_tx_eNB; a_tx++) {
+ for(a_tx=0; a_txnb_antenna_ports_eNB; a_tx++) {
for (a_rx=0; a_rxnb_antennas_rx; a_rx++) {
s_dB[count] = 10*log10(pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2],2) + pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2],
2)) - meas->n0_power_avg_dB;
@@ -7703,7 +7820,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
for (count=0; countN_RB_DL*12; count++) {
abs_channel=0;
- for(a_tx=0; a_txnb_antennas_tx_eNB; a_tx++) {
+ for(a_tx=0; a_txnb_antenna_ports_eNB; a_tx++) {
for (a_rx=0; a_rxnb_antennas_rx; a_rx++) {
abs_channel += (pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2],2) + pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2],2));
}
@@ -7723,7 +7840,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
qq = (q>>(((count/12)>>2)<<1))&3;
//printf("pmi_alloc %d: rb %d, pmi %d\n",q,count/12,qq);
- for(a_tx=0; a_txnb_antennas_tx_eNB; a_tx++) {
+ for(a_tx=0; a_txnb_antenna_ports_eNB; a_tx++) {
for (a_rx=0; a_rxnb_antennas_rx; a_rx++) {
switch(qq) {
case 0:
@@ -7805,7 +7922,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
qq = (q>>(((count/12)>>2)<<1))&3;
//printf("pmi_alloc %d: rb %d, pmi %d\n",q,count/12,qq);
- for(a_tx=0; a_txnb_antennas_tx_eNB; a_tx++) {
+ for(a_tx=0; a_txnb_antenna_ports_eNB; a_tx++) {
for (a_rx=0; a_rxnb_antennas_rx; a_rx++) {
switch(qq) {
case 0:
diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h
index 01d6cdc449..b6bbe09b31 100644
--- a/openair1/PHY/LTE_TRANSPORT/defs.h
+++ b/openair1/PHY/LTE_TRANSPORT/defs.h
@@ -227,11 +227,20 @@ typedef struct {
uint8_t control_only;
/// Flag to indicate that this is a calibration ULSCH (i.e. no MAC SDU and filled with TDD calibration information)
// int calibration_flag;
+ /// Number of soft channel bits
+ uint32_t G;
+
+ // decode phich
+ uint8_t decode_phich;
} LTE_UL_UE_HARQ_t;
typedef struct {
/// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding)
- uint32_t *txdataF[8];
+ int32_t *txdataF[8];
+ /// beamforming weights for UE-spec transmission (antenna ports 5 or 7..14), for each codeword, maximum 4 layers?
+ int32_t **ue_spec_bf_weights[4];
+ /// dl channel estimates (estimated from ul channel estimates)
+ int32_t **calib_dl_ch_estimates;
/// Allocated RNTI (0 means DLSCH_t is not currently used)
uint16_t rnti;
/// Active flag for baseband transmitter processing
@@ -333,12 +342,16 @@ typedef struct {
int16_t Po_PUSCH;
/// PHR - current power headroom (based on last PUSCH transmission)
int16_t PHR;
+ /// Po_SRS - target output power for SRS
+ int16_t Po_SRS;
/// num active cba group
uint8_t num_active_cba_groups;
/// num dci found for cba
uint8_t num_cba_dci[10];
/// allocated CBA RNTI
uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP];
+ /// UL max-harq-retransmission
+ uint8_t Mlimit;
} LTE_UE_ULSCH_t;
typedef struct {
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
index 0284ca27ad..0827918863 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
@@ -111,12 +111,14 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch)
}
-LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag)
+LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS* frame_parms)
{
LTE_eNB_DLSCH_t *dlsch;
- unsigned char exit_flag = 0,i,j,r;
+ unsigned char exit_flag = 0,i,j,r,aa,layer;
+ int re;
unsigned char bw_scaling =1;
+ uint8_t nb_antennas_tx = frame_parms->nb_antennas_tx;
switch (N_RB_DL) {
case 6:
@@ -145,6 +147,23 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_
dlsch->Mlimit = 4;
dlsch->Nsoft = Nsoft;
+ for (layer=0; layer<4; layer++) {
+ dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
+
+ for (aa=0; aanb_antennas_tx; aa++) {
+ dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
+ for (re=0;reue_spec_bf_weights[layer][aa][re] = 0x00007fff;
+ }
+ }
+ }
+
+ dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
+ for (aa=0; aanb_antennas_tx; aa++) {
+ dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
+
+ }
+
for (i=0; i<10; i++)
dlsch->harq_ids[i] = Mdlharq;
@@ -189,7 +208,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_
exit_flag=3;
}
}
-
+
if (exit_flag==0) {
for (i=0; iharq_processes[i]->round=0;
@@ -379,7 +398,7 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
A = dlsch->harq_processes[harq_pid]->TBS; //6228
mod_order = get_Qm(dlsch->harq_processes[harq_pid]->mcs);
- G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe);
+ G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,dlsch->harq_processes[harq_pid]->mimo_mode==TM7?7:0);
if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet
@@ -557,6 +576,7 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
unsigned char mod_order;
unsigned int Kr=0,Kr_bytes,r,r_offset=0;
unsigned short m=dlsch->harq_processes[harq_pid]->mcs;
+ uint8_t beamforming_mode=0;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
@@ -564,7 +584,13 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
// printf("Encoder: A: %d\n",A);
mod_order = get_Qm(dlsch->harq_processes[harq_pid]->mcs);
- G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe);
+ if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7)
+ beamforming_mode = 7;
+ else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8)
+ beamforming_mode = 8;
+ else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10)
+ beamforming_mode = 9;
+ G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode);
// if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
index f4ab4c0924..4a80110b22 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
@@ -249,7 +249,12 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
tc = phy_threegpplte_turbo_decoder16;
}
else
- tc = phy_threegpplte_turbo_decoder8;
+ {
+ AssertFatal (harq_process->TBS >= 256 , "Mismatch flag nbRB=%d TBS=%d mcs=%d Qm=%d RIV=%d round=%d \n",
+ harq_process->nb_rb, harq_process->TBS,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round);
+ tc = phy_threegpplte_turbo_decoder8;
+ }
+
// nb_rb = dlsch->nb_rb;
@@ -448,6 +453,11 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
#if 1
if (err_flag == 0) {
+ if (llr8_flag) {
+ AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n",
+ Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round);
+ }
+
start_meas(dlsch_turbo_decoding_stats);
ret = tc
(&harq_process->d[r][96],
@@ -609,7 +619,11 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
harq_process->errors[harq_process->round]++;
harq_process->round++;
- // LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round);
+
+ if(is_crnti)
+ {
+ LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round,harq_process->TBS);
+ }
// printf("Rate: [UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round);
if (harq_process->round >= dlsch->Mdlharq) {
harq_process->status = SCH_IDLE;
@@ -622,7 +636,10 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
dlsch->harq_ack[subframe].ack = 1;
dlsch->harq_ack[subframe].harq_id = harq_pid;
dlsch->harq_ack[subframe].send_harq_status = 1;
- LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round);
+ if(is_crnti)
+ {
+ LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round,harq_process->TBS);
+ }
}
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c
index 036eb86b24..33d7985768 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c
@@ -21,7 +21,7 @@
/*! \file PHY/LTE_TRANSPORT/dlsch_demodulation.c
* \brief Top-level routines for demodulating the PDSCH physical channel from 36-211, V8.6 2009-03
- * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert
+ * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert, X. Xiang
* \date 2011
* \version 0.1
* \company Eurecom
@@ -89,9 +89,11 @@ int rx_pdsch(PHY_VARS_UE *ue,
LTE_UE_DLSCH_t **dlsch;
unsigned char aatx,aarx;
- unsigned short nb_rb;
+ unsigned short nb_rb=0;
int avgs, rb;
LTE_DL_UE_HARQ_t *dlsch0_harq,*dlsch1_harq = 0;
+
+ uint8_t beamforming_mode;
uint32_t *rballoc;
switch (type) {
@@ -99,12 +101,14 @@ int rx_pdsch(PHY_VARS_UE *ue,
pdsch_vars = &ue->pdsch_vars_SI[eNB_id];
dlsch = &ue->dlsch_SI[eNB_id];
dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
+ beamforming_mode = 0;
break;
case RA_PDSCH:
pdsch_vars = &ue->pdsch_vars_ra[eNB_id];
dlsch = &ue->dlsch_ra[eNB_id];
dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
+ beamforming_mode = 0;
break;
case PDSCH:
@@ -112,6 +116,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
dlsch = ue->dlsch[eNB_id];
dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
dlsch1_harq = dlsch[1]->harq_processes[harq_pid];
+ beamforming_mode = ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id];
break;
default:
@@ -153,7 +158,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
else
rballoc = dlsch0_harq->rb_alloc_even;
- if (frame_parms->nb_antennas_tx_eNB>1) {
+ if (frame_parms->nb_antenna_ports_eNB>1 && beamforming_mode==0) {
#ifdef DEBUG_DLSCH_MOD
LOG_I(PHY,"dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),dlsch[0],dlsch0_harq->rb_alloc_even[0]);
#endif
@@ -195,8 +200,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
ue->high_speed_flag,
frame_parms);
}
- } // if n_tx>1
- else {
+ } else if (beamforming_mode==0) { //else if nb_antennas_ports_eNB==1 && beamforming_mode == 0
nb_rb = dlsch_extract_rbs_single(common_vars->rxdataF,
common_vars->dl_ch_estimates[eNB_id],
pdsch_vars[eNB_id]->rxdataF_ext,
@@ -235,7 +239,20 @@ int rx_pdsch(PHY_VARS_UE *ue,
ue->high_speed_flag,
frame_parms);
}
- } //else n_tx>1
+ } else if (beamforming_mode==7) { //else if beamforming_mode == 7
+ nb_rb = dlsch_extract_rbs_TM7(common_vars->rxdataF,
+ pdsch_vars[eNB_id]->dl_bf_ch_estimates,
+ pdsch_vars[eNB_id]->rxdataF_ext,
+ pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext,
+ rballoc,
+ symbol,
+ subframe,
+ ue->high_speed_flag,
+ frame_parms);
+
+ } else if(beamforming_mode>7) {
+ LOG_W(PHY,"dlsch_demodulation:beamforming mode not supported yet.\n");
+ }
// printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id);
if (nb_rb==0) {
@@ -252,11 +269,19 @@ int rx_pdsch(PHY_VARS_UE *ue,
nb_rb);
*/
if (first_symbol_flag==1) {
- dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
- frame_parms,
- avg,
- symbol,
- nb_rb);
+ if (beamforming_mode==0)
+ dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
+ frame_parms,
+ avg,
+ symbol,
+ nb_rb);
+ else if (beamforming_mode==7)
+ dlsch_channel_level_TM7(pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext,
+ frame_parms,
+ avg,
+ symbol,
+ nb_rb);
+
#ifdef DEBUG_PHY
LOG_D(PHY,"[DLSCH] avg[0] %d\n",avg[0]);
#endif
@@ -266,7 +291,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
// in case of precoding we add an additional factor of two for the precoding gain
avgs = 0;
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++)
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++)
for (aarx=0; aarxnb_antennas_rx; aarx++)
avgs = cmax(avgs,avg[(aatx<<1)+aarx]);
@@ -274,7 +299,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+1;
- // + log2_approx(frame_parms->nb_antennas_tx_eNB-1) //-1 because log2_approx counts the number of bits
+ // + log2_approx(frame_parms->nb_antenna_ports_eNB-1) //-1 because log2_approx counts the number of bits
// + log2_approx(frame_parms->nb_antennas_rx-1);
if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) &&
@@ -287,11 +312,11 @@ int rx_pdsch(PHY_VARS_UE *ue,
Nb_tx*Nb_rx in TM2,4,5
Nb_tx^2*Nb_rx in TM6 */
/*
- K = frame_parms->nb_antennas_rx*frame_parms->nb_antennas_tx_eNB; //that also covers TM1 since Nb_tx=1
+ K = frame_parms->nb_antennas_rx*frame_parms->nb_antenna_ports_eNB; //that also covers TM1 since Nb_tx=1
if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) &&
(dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) &&
(dlsch0_harq->dl_power_off==1)) // we are in TM 6
- K *= frame_parms->nb_antennas_tx_eNB;
+ K *= frame_parms->nb_antenna_ports_eNB;
pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2);
*/
@@ -302,7 +327,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
#endif
}
- aatx = frame_parms->nb_antennas_tx_eNB;
+ aatx = frame_parms->nb_antenna_ports_eNB;
aarx = frame_parms->nb_antennas_rx;
if (dlsch0_harq->mimo_modemimo_mode == LARGE_CDD) { // TM3
// LOG_I(PHY,"Running PDSCH RX for TM3\n");
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
if (first_symbol_flag==1) {
// effective channel of desired user is always stronger than interfering eff. channel
dlsch_channel_level_TM3(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
@@ -522,12 +547,28 @@ int rx_pdsch(PHY_VARS_UE *ue,
pdsch_vars[eNB_id]->log2_maxh,
1);
}
+ } else if (dlsch0_harq->mimo_mode==TM7) { //TM7
+
+ dlsch_channel_compensation(pdsch_vars[eNB_id]->rxdataF_ext,
+ pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext,
+ pdsch_vars[eNB_id]->dl_ch_mag0,
+ pdsch_vars[eNB_id]->dl_ch_magb0,
+ pdsch_vars[eNB_id]->rxdataF_comp0,
+ (aatx>1) ? pdsch_vars[eNB_id]->rho : NULL,
+ frame_parms,
+ symbol,
+ first_symbol_flag,
+ get_Qm(dlsch0_harq->mcs),
+ nb_rb,
+ //9,
+ pdsch_vars[eNB_id]->log2_maxh,
+ phy_measurements); // log2_maxh+I0_shift
}
// printf("MRC\n");
if (frame_parms->nb_antennas_rx > 1) {
if (dlsch0_harq->mimo_mode == LARGE_CDD) {
- if (frame_parms->nb_antennas_tx_eNB == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
dlsch_detection_mrc(frame_parms,
pdsch_vars[eNB_id]->rxdataF_comp0,
pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round],
@@ -561,8 +602,8 @@ int rx_pdsch(PHY_VARS_UE *ue,
// printf("Combining");
if ((dlsch0_harq->mimo_mode == SISO) ||
((dlsch0_harq->mimo_mode >= UNIFORM_PRECODING11) &&
- (dlsch0_harq->mimo_mode <= PUSCH_PRECODING0))) {
-
+ (dlsch0_harq->mimo_mode <= PUSCH_PRECODING0)) ||
+ (dlsch0_harq->mimo_mode == TM7)) {
/*
dlsch_siso(frame_parms,
pdsch_vars[eNB_id]->rxdataF_comp,
@@ -599,7 +640,8 @@ int rx_pdsch(PHY_VARS_UE *ue,
pdsch_vars[eNB_id]->llr[0],
symbol,first_symbol_flag,nb_rb,
adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
- pdsch_vars[eNB_id]->llr128);
+ pdsch_vars[eNB_id]->llr128,
+ beamforming_mode);
else if (i_mod == 2) {
dlsch_qpsk_qpsk_llr(frame_parms,
pdsch_vars[eNB_id]->rxdataF_comp0,
@@ -692,7 +734,8 @@ int rx_pdsch(PHY_VARS_UE *ue,
pdsch_vars[eNB_id]->dl_ch_mag0,
symbol,first_symbol_flag,nb_rb,
adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol),
- pdsch_vars[eNB_id]->llr128);
+ pdsch_vars[eNB_id]->llr128,
+ beamforming_mode);
} else if (i_mod == 2) {
dlsch_16qam_qpsk_llr(frame_parms,
pdsch_vars[eNB_id]->rxdataF_comp0,
@@ -738,7 +781,8 @@ int rx_pdsch(PHY_VARS_UE *ue,
pdsch_vars[eNB_id]->dl_ch_magb0,
symbol,first_symbol_flag,nb_rb,
adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol),
- pdsch_vars[eNB_id]->llr128);
+ pdsch_vars[eNB_id]->llr128,
+ beamforming_mode);
} else if (i_mod == 2) {
dlsch_64qam_qpsk_llr(frame_parms,
pdsch_vars[eNB_id]->rxdataF_comp0,
@@ -781,7 +825,6 @@ int rx_pdsch(PHY_VARS_UE *ue,
return(-1);
break;
}
-
return(0);
}
@@ -821,7 +864,7 @@ void dlsch_channel_compensation(int **rxdataF_ext,
pilots=1;
}
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++) {
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++) {
if (mod_order == 4) {
QAM_amp128 = _mm_set1_epi16(QAM16_n1); // 2/sqrt(10)
QAM_amp128b = _mm_setzero_si128();
@@ -1081,7 +1124,7 @@ void dlsch_channel_compensation(int **rxdataF_ext,
}
}
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++) {
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++) {
if (mod_order == 4) {
QAM_amp128 = vmovq_n_s16(QAM16_n1); // 2/sqrt(10)
QAM_amp128b = vmovq_n_s16(0);
@@ -2594,7 +2637,7 @@ void dlsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms,
if (frame_parms->nb_antennas_rx>1) {
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++) {
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++) {
rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12];
rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12];
@@ -2654,7 +2697,7 @@ void dlsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms,
if (frame_parms->nb_antennas_rx>1) {
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++) {
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++) {
rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12];
rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12];
@@ -2736,7 +2779,7 @@ void dlsch_scale_channel(int **dl_ch_estimates_ext,
ch_amp128 = _mm_set1_epi16(ch_amp); // Q3.13
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++) {
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++) {
for (aarx=0; aarxnb_antennas_rx; aarx++) {
dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12];
@@ -2780,7 +2823,7 @@ void dlsch_channel_level(int **dl_ch_estimates_ext,
symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++)
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++)
for (aarx=0; aarxnb_antennas_rx; aarx++) {
//clear average level
avg128D = _mm_setzero_si128();
@@ -2837,7 +2880,7 @@ void dlsch_channel_level(int **dl_ch_estimates_ext,
symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
- for (aatx=0; aatxnb_antennas_tx_eNB; aatx++)
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++)
for (aarx=0; aarxnb_antennas_rx; aarx++) {
//clear average level
avg128D = vdupq_n_s32(0);
@@ -3054,6 +3097,76 @@ void dlsch_channel_level_TM56(int **dl_ch_estimates_ext,
#endif
}
+//compute average channel_level for TM7
+void dlsch_channel_level_TM7(int **dl_bf_ch_estimates_ext,
+ LTE_DL_FRAME_PARMS *frame_parms,
+ int *avg,
+ uint8_t symbol,
+ unsigned short nb_rb)
+{
+
+#if defined(__x86_64__)||defined(__i386__)
+
+ short rb;
+ unsigned char aatx,aarx,nre=12,symbol_mod;
+ __m128i *dl_ch128,avg128D;
+
+ symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
+
+ for (aatx=0; aatxnb_antenna_ports_eNB; aatx++)
+ for (aarx=0; aarxnb_antennas_rx; aarx++) {
+ //clear average level
+ avg128D = _mm_setzero_si128();
+ // 5 is always a symbol with no pilots for both normal and extended prefix
+
+ dl_ch128=(__m128i *)&dl_bf_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12];
+
+ for (rb=0; rbNcp-1)))&&(frame_parms->mode1_flag==0)) {
+ dl_ch128+=2;
+ } else {
+ avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[2],dl_ch128[2]));
+ dl_ch128+=3;
+ }
+
+ /*
+ if (rb==0) {
+ print_shorts("dl_ch128",&dl_ch128[0]);
+ print_shorts("dl_ch128",&dl_ch128[1]);
+ print_shorts("dl_ch128",&dl_ch128[2]);
+ }
+ */
+ }
+
+ if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1))))
+ nre=10;
+ else if ((frame_parms->Ncp==0) && (symbol==3 || symbol==6 || symbol==9 || symbol==12))
+ nre=9;
+ else if ((frame_parms->Ncp==1) && (symbol==4 || symbol==7 || symbol==9))
+ nre=8;
+ else
+ nre=12;
+
+ avg[(aatx<<1)+aarx] = (((int*)&avg128D)[0] +
+ ((int*)&avg128D)[1] +
+ ((int*)&avg128D)[2] +
+ ((int*)&avg128D)[3])/(nb_rb*nre);
+
+ // printf("Channel level : %d\n",avg[(aatx<<1)+aarx]);
+ }
+
+ _mm_empty();
+ _m_empty();
+
+#elif defined(__arm__)
+
+#endif
+}
void dlsch_alamouti(LTE_DL_FRAME_PARMS *frame_parms,
int **rxdataF_comp,
@@ -4183,8 +4296,850 @@ unsigned short dlsch_extract_rbs_dual(int **rxdataF,
return(nb_rb/frame_parms->nb_antennas_rx);
}
-//==============================================================================================
-// Auxiliary functions
+unsigned short dlsch_extract_rbs_TM7(int **rxdataF,
+ int **dl_bf_ch_estimates,
+ int **rxdataF_ext,
+ int **dl_bf_ch_estimates_ext,
+ unsigned int *rb_alloc,
+ unsigned char symbol,
+ unsigned char subframe,
+ uint32_t high_speed_flag,
+ LTE_DL_FRAME_PARMS *frame_parms)
+{
+
+ unsigned short rb,nb_rb=0;
+ unsigned char rb_alloc_ind;
+ unsigned char i,aarx,l,nsymb,skip_half=0,sss_symb,pss_symb=0;
+ int *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
+
+ unsigned char symbol_mod,pilots=0,uespec_pilots=0,j=0,poffset=0,uespec_poffset=0;
+ int8_t uespec_nushift = frame_parms->Nid_cell%3;
+
+ symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
+ pilots = ((symbol_mod==0)||(symbol_mod==(4-frame_parms->Ncp))) ? 1 : 0;
+ l=symbol;
+ nsymb = (frame_parms->Ncp==NORMAL) ? 14:12;
+
+ if (frame_parms->Ncp==0){
+ if (symbol==3 || symbol==6 || symbol==9 || symbol==12)
+ uespec_pilots = 1;
+ } else{
+ if (symbol==4 || symbol==7 || symbol==10)
+ uespec_pilots = 1;
+ }
+
+ if (frame_parms->frame_type == TDD) {// TDD
+ sss_symb = nsymb-1;
+ pss_symb = 2;
+ } else {
+ sss_symb = (nsymb>>1)-2;
+ pss_symb = (nsymb>>1)-1;
+ }
+
+ if (symbol_mod==(4-frame_parms->Ncp))
+ poffset=3;
+
+ if ((frame_parms->Ncp==0 && (symbol==6 ||symbol ==12)) || (frame_parms->Ncp==1 && symbol==7))
+ uespec_poffset=2;
+
+ for (aarx=0; aarxnb_antennas_rx; aarx++) {
+
+ if (high_speed_flag == 1)
+ dl_ch0 = &dl_bf_ch_estimates[aarx][symbol*(frame_parms->ofdm_symbol_size)];
+ else
+ dl_ch0 = &dl_bf_ch_estimates[aarx][0];
+
+ dl_ch0_ext = &dl_bf_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)];
+
+ rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)];
+ rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))];
+
+ if ((frame_parms->N_RB_DL&1) == 0) // even number of RBs
+ for (rb=0; rbN_RB_DL; rb++) {
+
+ if (rb < 32)
+ rb_alloc_ind = (rb_alloc[0]>>rb) & 1;
+ else if (rb < 64)
+ rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1;
+ else if (rb < 96)
+ rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1;
+ else if (rb < 100)
+ rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1;
+ else
+ rb_alloc_ind = 0;
+
+ if (rb_alloc_ind == 1)
+ nb_rb++;
+
+ // For second half of RBs skip DC carrier
+ if (rb==(frame_parms->N_RB_DL>>1)) {
+ rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))];
+ //dl_ch0++;
+ }
+
+ // PBCH
+ if ((subframe==0) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) {
+ rb_alloc_ind = 0;
+ }
+
+ //SSS
+ if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+
+ if (frame_parms->frame_type == FDD) {
+ //PSS
+ if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+ }
+
+ if ((frame_parms->frame_type == TDD) &&
+ (subframe==6)) { //TDD Subframe 6
+ if ((rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+ }
+
+ if (rb_alloc_ind==1) {
+
+ /*
+ printf("rb %d\n",rb);
+ for (i=0;i<12;i++)
+ printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]);
+ printf("\n");
+ */
+ if (pilots==0 && uespec_pilots==0) {
+ memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int));
+
+ for (i=0; i<12; i++) {
+ rxF_ext[i]=rxF[i];
+ }
+
+ dl_ch0_ext+=12;
+ rxF_ext+=12;
+ } else if(pilots==1 && uespec_pilots==0) {
+ j=0;
+
+ for (i=0; i<12; i++) {
+ if ((i!=(frame_parms->nushift+poffset)) &&
+ (i!=((frame_parms->nushift+poffset+6)%12))) {
+ rxF_ext[j]=rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+ }
+ }
+
+ dl_ch0_ext+=10;
+ rxF_ext+=10;
+
+ } else if (pilots==0 && uespec_pilots==1) {
+ j=0;
+
+
+ for (i=0; i<12; i++){
+ if (frame_parms->Ncp==0){
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+ rxF_ext[j] = rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+ }
+ } else{
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){
+ rxF_ext[j] = rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+ }
+ }
+
+ }
+
+ dl_ch0_ext+=9-frame_parms->Ncp;
+ rxF_ext+=9-frame_parms->Ncp;
+
+ } else {
+ msg("dlsch_extract_rbs_TM7(dl_demodulation.c):pilot or ue spec pilot detection error\n");
+ exit(-1);
+ }
+
+ }
+
+ dl_ch0+=12;
+ rxF+=12;
+
+ }
+ else { // Odd number of RBs
+ for (rb=0; rbN_RB_DL>>1; rb++) {
+ skip_half=0;
+
+ if (rb < 32)
+ rb_alloc_ind = (rb_alloc[0]>>rb) & 1;
+ else if (rb < 64)
+ rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1;
+ else if (rb < 96)
+ rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1;
+ else if (rb < 100)
+ rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1;
+ else
+ rb_alloc_ind = 0;
+
+ if (rb_alloc_ind == 1)
+ nb_rb++;
+
+ // PBCH
+ if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) {
+ rb_alloc_ind = 0;
+ }
+
+ //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3
+ if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+ skip_half=1;
+ else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+ skip_half=2;
+
+ //SSS
+
+ if (((subframe==0)||(subframe==5)) &&
+ (rb>((frame_parms->N_RB_DL>>1)-3)) &&
+ (rb<((frame_parms->N_RB_DL>>1)+3)) &&
+ (l==sss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ //SSS
+ if (((subframe==0)||(subframe==5)) &&
+ (rb==((frame_parms->N_RB_DL>>1)-3)) &&
+ (l==sss_symb))
+ skip_half=1;
+ else if (((subframe==0)||(subframe==5)) &&
+ (rb==((frame_parms->N_RB_DL>>1)+3)) &&
+ (l==sss_symb))
+ skip_half=2;
+
+ //PSS in subframe 0/5 if FDD
+ if (frame_parms->frame_type == FDD) { //FDD
+ if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+ skip_half=1;
+ else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+ skip_half=2;
+ }
+
+ if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) { //TDD Subframe 1 and 6
+ if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+ skip_half=1;
+ else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+ skip_half=2;
+ }
+
+
+ if (rb_alloc_ind==1) {
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("rb %d/symbol %d pilots %d, uespec_pilots %d, (skip_half %d)\n",rb,l,pilots,uespec_pilots,skip_half);
+#endif
+
+ if (pilots==0 && uespec_pilots==0) {
+ //printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half);
+
+ if (skip_half==1) {
+ memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int));
+
+ for (i=0; i<6; i++) {
+ rxF_ext[i]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+
+ dl_ch0_ext+=6;
+ rxF_ext+=6;
+ } else if (skip_half==2) {
+ memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int));
+
+ for (i=0; i<6; i++) {
+ rxF_ext[i]=rxF[(i+6)];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+
+ dl_ch0_ext+=6;
+ rxF_ext+=6;
+ } else {
+ memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int));
+
+ for (i=0; i<12; i++){
+ rxF_ext[i]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",symbol,rb,i,*(short *)&rxF[i],*(1+(short*)&rxF[i]));
+#endif
+ }
+ dl_ch0_ext+=12;
+ rxF_ext+=12;
+ }
+ } else if (pilots==1 && uespec_pilots==0) {
+ // printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half);
+ j=0;
+
+ if (skip_half==1) {
+ for (i=0; i<6; i++) {
+ if (i!=((frame_parms->nushift+poffset)%6)) {
+ rxF_ext[j]=rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+
+ dl_ch0_ext+=5;
+ rxF_ext+=5;
+ } else if (skip_half==2) {
+ for (i=0; i<6; i++) {
+ if (i!=((frame_parms->nushift+poffset)%6)) {
+ rxF_ext[j]=rxF[(i+6)];
+ dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+
+ dl_ch0_ext+=5;
+ rxF_ext+=5;
+ } else {
+ for (i=0; i<12; i++) {
+ if ((i!=(frame_parms->nushift+poffset)) &&
+ (i!=((frame_parms->nushift+poffset+6)%12))) {
+ rxF_ext[j]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j]));
+#endif
+ dl_ch0_ext[j++]=dl_ch0[i];
+
+ }
+ }
+
+ dl_ch0_ext+=10;
+ rxF_ext+=10;
+ }
+ } else if(pilots==0 && uespec_pilots==1){
+ //printf("Extracting with uespec pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half);
+ j=0;
+
+ if (skip_half==1) {
+ if (frame_parms->Ncp==0){
+ for (i=0; i<6; i++) {
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+ rxF_ext[j]=rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+ dl_ch0_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6);
+ rxF_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6);
+
+ } else{
+ for (i=0; i<6; i++) {
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){
+ rxF_ext[j]=rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+ dl_ch0_ext+=4;
+ rxF_ext+=4;
+ }
+
+ } else if (skip_half==2) {
+ if(frame_parms->Ncp==0){
+ for (i=0; i<6; i++) {
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+ rxF_ext[j]=rxF[(i+6)];
+ dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+ dl_ch0_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6);
+ rxF_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6);
+
+ } else {
+ for (i=0; i<6; i++) {
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){
+ rxF_ext[j]=rxF[(i+6)];
+ dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+ dl_ch0_ext+=4;
+ rxF_ext+=4;
+ }
+
+ } else {
+
+ for (i=0; i<12; i++){
+ if (frame_parms->Ncp==0){
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+ rxF_ext[j] = rxF[i];
+ dl_ch0_ext[j++] = dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d, j %d => (%d,%d)\n",symbol,rb,i,j-1,*(short *)&dl_ch0[j],*(1+(short*)&dl_ch0[i]));
+#endif
+ }
+ } else{
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){
+ rxF_ext[j] = rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+
+ }
+
+ dl_ch0_ext+=9-frame_parms->Ncp;
+ rxF_ext+=9-frame_parms->Ncp;
+ }
+
+ } else {
+ msg("dlsch_extract_rbs_TM7(dl_demodulation.c):pilot or ue spec pilot detection error\n");
+ exit(-1);
+
+ }
+ }
+
+ dl_ch0+=12;
+ rxF+=12;
+ } // first half loop
+
+
+ // Do middle RB (around DC)
+ if (rb < 32)
+ rb_alloc_ind = (rb_alloc[0]>>rb) & 1;
+ else if (rb < 64)
+ rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1;
+ else if (rb < 96)
+ rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1;
+ else if (rb < 100)
+ rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1;
+ else
+ rb_alloc_ind = 0;
+
+ if (rb_alloc_ind == 1)
+ nb_rb++;
+
+ // PBCH
+ if ((subframe==0) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) {
+ rb_alloc_ind = 0;
+ }
+
+ //SSS
+ if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ if (frame_parms->frame_type == FDD) {
+ //PSS
+ if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+ }
+
+ if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) {
+ //PSS
+ if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+ }
+
+ //printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]);
+ //printf("DC rb %d (%p)\n",rb,rxF);
+ if (rb_alloc_ind==1) {
+ //printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half);
+ if (pilots==0 && uespec_pilots==0) {
+ for (i=0; i<6; i++) {
+ dl_ch0_ext[i]=dl_ch0[i];
+ rxF_ext[i]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+
+ rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))];
+
+ for (; i<12; i++) {
+ dl_ch0_ext[i]=dl_ch0[i];
+ rxF_ext[i]=rxF[(1+i-6)];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+
+ dl_ch0_ext+=12;
+ rxF_ext+=12;
+ } else if(pilots==1 && uespec_pilots==0){ // pilots==1
+ j=0;
+
+ for (i=0; i<6; i++) {
+ if (i!=((frame_parms->nushift+poffset)%6)) {
+ dl_ch0_ext[j]=dl_ch0[i];
+ rxF_ext[j++]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+
+ rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))];
+
+ for (; i<12; i++) {
+ if (i!=((frame_parms->nushift+6+poffset)%12)) {
+ dl_ch0_ext[j]=dl_ch0[i];
+ rxF_ext[j++]=rxF[(1+i-6)];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+
+ dl_ch0_ext+=10;
+ rxF_ext+=10;
+ } else if(pilots==0 && uespec_pilots==1) {
+ j=0;
+
+ for (i=0; i<6; i++) {
+ if (frame_parms->Ncp==0){
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+ dl_ch0_ext[j]=dl_ch0[i];
+ rxF_ext[j++] = rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ } else {
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){
+ dl_ch0_ext[j]=dl_ch0[i];
+ rxF_ext[j++] = rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+ }
+
+ rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))];
+
+ for (; i<12; i++) {
+ if (frame_parms->Ncp==0){
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+ dl_ch0_ext[j]=dl_ch0[i];
+ rxF_ext[j++]=rxF[(1+i-6)];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ } else {
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){
+ dl_ch0_ext[j]=dl_ch0[i];
+ rxF_ext[j++] = rxF[(1+i-6)];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+ }
+
+ dl_ch0_ext+=9-frame_parms->Ncp;
+ rxF_ext+=9-frame_parms->Ncp;
+
+ }// symbol_mod==0
+
+ } // rballoc==1
+ else {
+ rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))];
+ }
+
+ dl_ch0+=12;
+ rxF+=7;
+ rb++;
+
+ for (; rbN_RB_DL; rb++) {
+ // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]);
+ // printf("rb %d (%p)\n",rb,rxF);
+ skip_half=0;
+
+ if (rb < 32)
+ rb_alloc_ind = (rb_alloc[0]>>rb) & 1;
+ else if (rb < 64)
+ rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1;
+ else if (rb < 96)
+ rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1;
+ else if (rb < 100)
+ rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1;
+ else
+ rb_alloc_ind = 0;
+
+ if (rb_alloc_ind==1)
+ nb_rb++;
+
+ // PBCH
+ if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) {
+ rb_alloc_ind = 0;
+ }
+
+ //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3
+ if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+ skip_half=1;
+ else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+ skip_half=2;
+
+ //SSS
+ if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ //SSS
+ if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb))
+ skip_half=1;
+ else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb))
+ skip_half=2;
+
+ //PSS
+ if (frame_parms->frame_type == FDD) {
+ if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+ skip_half=1;
+ else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+ skip_half=2;
+ }
+
+ if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) { //TDD Subframe 1 and 6
+ if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+ rb_alloc_ind = 0;
+ }
+
+ if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+ skip_half=1;
+ else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+ skip_half=2;
+ }
+
+ if (rb_alloc_ind==1) {
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half);
+#endif
+ /*
+ printf("rb %d\n",rb);
+ for (i=0;i<12;i++)
+ printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]);
+ printf("\n");
+ */
+ if (pilots==0 && uespec_pilots==0) {
+ //printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half);
+ if (skip_half==1) {
+ memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int));
+
+ for (i=0; i<6; i++) {
+ rxF_ext[i]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+
+ dl_ch0_ext+=6;
+ rxF_ext+=6;
+
+ } else if (skip_half==2) {
+ memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int));
+
+ for (i=0; i<6; i++) {
+ rxF_ext[i]=rxF[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+
+ dl_ch0_ext+=6;
+ rxF_ext+=6;
+
+ } else {
+ memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int));
+ //printf("symbol %d, extract rb %d, => (%d,%d)\n",symbol,rb,*(short *)&dl_ch0[j],*(1+(short*)&dl_ch0[i]));
+
+ for (i=0; i<12; i++) {
+ rxF_ext[i]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+
+ dl_ch0_ext+=12;
+ rxF_ext+=12;
+ }
+ } else if (pilots==1 && uespec_pilots==0){
+ //printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half);
+ j=0;
+
+ if (skip_half==1) {
+ for (i=0; i<6; i++) {
+ if (i!=((frame_parms->nushift+poffset)%6)) {
+ rxF_ext[j]=rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+
+ dl_ch0_ext+=5;
+ rxF_ext+=5;
+ } else if (skip_half==2) {
+ for (i=0; i<6; i++) {
+ if (i!=((frame_parms->nushift+poffset)%6)) {
+ rxF_ext[j]=rxF[(i+6)];
+ dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+
+ dl_ch0_ext+=5;
+ rxF_ext+=5;
+ } else {
+ for (i=0; i<12; i++) {
+ if ((i!=(frame_parms->nushift+poffset)) &&
+ (i!=((frame_parms->nushift+poffset+6)%12))) {
+ rxF_ext[j]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j]));
+#endif
+ dl_ch0_ext[j++]=dl_ch0[i];
+ }
+ }
+
+ dl_ch0_ext+=10;
+ rxF_ext+=10;
+ }
+ } else if(pilots==0 && uespec_pilots==1) {
+ j=0;
+
+ if (skip_half==1) {
+ if (frame_parms->Ncp==0){
+ for (i=0; i<6; i++) {
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+ rxF_ext[j]=rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+ dl_ch0_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6);
+ rxF_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6);
+
+ } else{
+ for (i=0; i<6; i++) {
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){
+ rxF_ext[j]=rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+ dl_ch0_ext+=4;
+ rxF_ext+=4;
+ }
+
+ } else if (skip_half==2) {
+ if(frame_parms->Ncp==0){
+ for (i=0; i<6; i++) {
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+ rxF_ext[j]=rxF[i+6];
+ dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+ dl_ch0_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6);
+ rxF_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6);
+
+ } else {
+ for (i=0; i<6; i++) {
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){
+ rxF_ext[j]=rxF[(i+6)];
+ dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+ dl_ch0_ext+=4;
+ rxF_ext+=4;
+ }
+
+ } else {
+ for (i=0; i<12; i++){
+ if (frame_parms->Ncp==0){
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+ rxF_ext[j] = rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ } else{
+ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){
+ rxF_ext[j] = rxF[i];
+ dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+ printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+ }
+ }
+ }
+
+ dl_ch0_ext+=9-frame_parms->Ncp;
+ rxF_ext+=9-frame_parms->Ncp;
+
+ }
+
+ }// pilots=0
+ }
+
+ dl_ch0+=12;
+ rxF+=12;
+ }
+ }
+ }
+
+ _mm_empty();
+ _m_empty();
+
+ return(nb_rb/frame_parms->nb_antennas_rx);
+}
+
+
+
//==============================================================================================
#ifdef USER_MODE
@@ -4210,13 +5165,24 @@ void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword
sprintf(vname,"dl%d_ch_r%d_ext00",eNB_id,round);
write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1);
+ if (ue->transmission_mode[eNB_id]==7){
+ sprintf(fname,"dlsch%d_bf_ch_r%d.m",eNB_id,round);
+ sprintf(vname,"dl%d_bf_ch_r%d",eNB_id,round);
+ write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_bf_ch_estimates[0],512*nsymb,1,1);
+ //write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_bf_ch_estimates[0],512,1,1);
+
+ sprintf(fname,"dlsch%d_bf_ch_r%d_ext00.m",eNB_id,round);
+ sprintf(vname,"dl%d_bf_ch_r%d_ext00",eNB_id,round);
+ write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1);
+ }
+
if (ue->frame_parms.nb_antennas_rx == 2) {
sprintf(fname,"dlsch%d_ch_r%d_ext01.m",eNB_id,round);
sprintf(vname,"dl%d_ch_r%d_ext01",eNB_id,round);
write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1);
}
- if (ue->frame_parms.nb_antennas_tx_eNB == 2) {
+ if (ue->frame_parms.nb_antenna_ports_eNB == 2) {
sprintf(fname,"dlsch%d_ch_r%d_ext10.m",eNB_id,round);
sprintf(vname,"dl%d_ch_r%d_ext10",eNB_id,round);
write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1);
@@ -4228,6 +5194,10 @@ void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword
}
}
+ sprintf(fname,"dlsch%d_rxF_r%d_uespec0.m",eNB_id,round);
+ sprintf(vname,"dl%d_rxF_r%d_uespec0",eNB_id,round);
+ write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_uespec_pilots[0],12*N_RB_DL,1,1);
+
/*
write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1);
write_output("dlsch%d_ch_ext10.m","dl10_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1);
@@ -4240,7 +5210,7 @@ void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword
sprintf(fname,"dlsch%d_rxF_r%d_comp0.m",eNB_id,round);
sprintf(vname,"dl%d_rxF_r%d_comp0",eNB_id,round);
write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_comp0[0],12*N_RB_DL*nsymb,1,1);
- if (ue->frame_parms.nb_antennas_tx_eNB == 2) {
+ if (ue->frame_parms.nb_antenna_ports_eNB == 2) {
sprintf(fname,"dlsch%d_rxF_r%d_comp1.m",eNB_id,round);
sprintf(vname,"dl%d_rxF_r%d_comp1",eNB_id,round);
write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_comp1[0][round],12*N_RB_DL*nsymb,1,1);
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c
index 9216985815..8165bc1f23 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c
@@ -21,7 +21,7 @@
/*! \file PHY/LTE_TRANSPORT/dlsch_llr_computation.c
* \brief Top-level routines for LLR computation of the PDSCH physical channel from 36-211, V8.6 2009-03
- * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert, S. Wagner
+ * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert, S. Wagner, X Jiang
* \date 2011
* \version 0.1
* \company Eurecom
@@ -632,7 +632,8 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t first_symbol_flag,
uint16_t nb_rb,
uint16_t pbch_pss_sss_adjust,
- int16_t **llr32p)
+ int16_t **llr32p,
+ uint8_t beamforming_mode)
{
uint32_t *rxF = (uint32_t*)&rxdataF_comp[0][((int32_t)symbol*frame_parms->N_RB_DL*12)];
@@ -657,6 +658,10 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
else
len = (nb_rb*10) - (5*pbch_pss_sss_adjust/6);
+ } else if((beamforming_mode==7) && (frame_parms->Ncp==0) && (symbol==3 || symbol==6 || symbol==9 || symbol==12)){
+ len = (nb_rb*9) - (3*pbch_pss_sss_adjust/4);
+ } else if((beamforming_mode==7) && (frame_parms->Ncp==1) && (symbol==4 || symbol==7 || symbol==10)){
+ len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
} else {
len = (nb_rb*12) - pbch_pss_sss_adjust;
}
@@ -688,7 +693,8 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t first_symbol_flag,
uint16_t nb_rb,
uint16_t pbch_pss_sss_adjust,
- int16_t **llr32p)
+ int16_t **llr32p,
+ uint8_t beamforming_mode)
{
#if defined(__x86_64__) || defined(__i386__)
@@ -731,11 +737,15 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
#endif
if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) {
if (frame_parms->mode1_flag==0)
- len = nb_rb*8 - (2*pbch_pss_sss_adjust/3);
+ len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
else
- len = nb_rb*10 - (5*pbch_pss_sss_adjust/6);
+ len = (nb_rb*10) - (5*pbch_pss_sss_adjust/6);
+ } else if((beamforming_mode==7) && (frame_parms->Ncp==0) && (symbol==3 || symbol==6 || symbol==9 || symbol==12)){
+ len = (nb_rb*9) - (3*pbch_pss_sss_adjust/4);
+ } else if((beamforming_mode==7) && (frame_parms->Ncp==1) && (symbol==4 || symbol==7 || symbol==10)){
+ len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
} else {
- len = nb_rb*12 - pbch_pss_sss_adjust;
+ len = (nb_rb*12) - pbch_pss_sss_adjust;
}
// update output pointer according to number of REs in this symbol (<<2 because 4 bits per RE)
@@ -811,7 +821,8 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t first_symbol_flag,
uint16_t nb_rb,
uint16_t pbch_pss_sss_adjust,
- int16_t **llr_save)
+ int16_t **llr_save,
+ uint8_t beamforming_mode)
{
#if defined(__x86_64__) || defined(__i386__)
__m128i *rxF = (__m128i*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
@@ -841,11 +852,15 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
#endif
if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) {
if (frame_parms->mode1_flag==0)
- len = nb_rb*8 - (2*pbch_pss_sss_adjust/3);
+ len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
else
- len = nb_rb*10 - (5*pbch_pss_sss_adjust/6);
+ len = (nb_rb*10) - (5*pbch_pss_sss_adjust/6);
+ } else if((beamforming_mode==7) && (frame_parms->Ncp==0) && (symbol==3 || symbol==6 || symbol==9 || symbol==12)){
+ len = (nb_rb*9) - (3*pbch_pss_sss_adjust/4);
+ } else if((beamforming_mode==7) && (frame_parms->Ncp==1) && (symbol==4 || symbol==7 || symbol==10)){
+ len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
} else {
- len = nb_rb*12 - pbch_pss_sss_adjust;
+ len = (nb_rb*12) - pbch_pss_sss_adjust;
}
llr2 = llr;
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
index bafa37b96f..d6e680344b 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
@@ -20,15 +20,15 @@
*/
/*! \file PHY/LTE_TRANSPORT/dlsch_modulation.c
-* \brief Top-level routines for generating the PDSCH physical channel from 36-211, V8.6 2009-03
-* \author R. Knopp, F. Kaltenberger
-* \date 2011
-* \version 0.1
-* \company Eurecom
-* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
-* \note
-* \warning
-*/
+ * \brief Top-level routines for generating the PDSCH physical channel from 36-211, V8.6 2009-03
+ * \author R. Knopp, F. Kaltenberger
+ * \date 2011
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
+ * \note
+ * \warning
+ */
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "PHY/CODING/defs.h"
@@ -62,10 +62,36 @@ uint8_t is_not_pilot(uint8_t pilots, uint8_t re, uint8_t nushift, uint8_t use2nd
return(0);
}
-uint8_t is_not_UEspecRS(int first_layer,int re)
+/*uint8_t is_not_UEspecRS(int first_layer,int re)
{
-
return(1);
+}*/
+uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, uint8_t beamforming_mode)
+{
+ uint8_t offset = (lprime==1||lprime==3)?2:0;
+ if (lprime==-1)
+ return(1);
+
+ switch (beamforming_mode) {
+ case 7:
+ if (Ncp == NORMAL){
+ if ((re!=nushift+offset) && (re!=((nushift+4+offset)%12)) && (re!=((nushift+8+offset)%12)))
+ return(1);
+ /*else{
+ printf("(is_no_UEspec_RS):lprime=%d, re=%d, nushift=%d, offset=%d\n",lprime, re,nushift,offset);
+ }*/
+ } else {
+ if ((re!=nushift+offset) && (re!=((nushift+3+offset)%12)) && (re!=((nushift+6+offset)%12)) && (re!=((nushift+9+offset)%12)))
+ return(1);
+ }
+ break;
+
+ default:
+ msg("is_not_UEspecRS() [dlsch_modulation.c] : ERROR, unknown beamforming_mode %d\n",beamforming_mode);
+ return(-1);
+ }
+
+ return(0);
}
void generate_64qam_table(void)
@@ -102,36 +128,36 @@ void layer1prec2A(int32_t *antenna0_sample, int32_t *antenna1_sample, uint8_t pr
switch (precoding_index) {
- case 0: // 1 1
- *antenna1_sample=*antenna0_sample;
- break;
+ case 0: // 1 1
+ *antenna1_sample=*antenna0_sample;
+ break;
- case 1: // 1 -1
- ((int16_t *)antenna1_sample)[0] = -((int16_t *)antenna0_sample)[0];
- ((int16_t *)antenna1_sample)[1] = -((int16_t *)antenna0_sample)[1];
- break;
+ case 1: // 1 -1
+ ((int16_t *)antenna1_sample)[0] = -((int16_t *)antenna0_sample)[0];
+ ((int16_t *)antenna1_sample)[1] = -((int16_t *)antenna0_sample)[1];
+ break;
- case 2: // 1 j
- ((int16_t *)antenna1_sample)[0] = -((int16_t *)antenna0_sample)[1];
- ((int16_t *)antenna1_sample)[1] = ((int16_t *)antenna0_sample)[0];
- break;
+ case 2: // 1 j
+ ((int16_t *)antenna1_sample)[0] = -((int16_t *)antenna0_sample)[1];
+ ((int16_t *)antenna1_sample)[1] = ((int16_t *)antenna0_sample)[0];
+ break;
- case 3: // 1 -j
- ((int16_t *)antenna1_sample)[0] = ((int16_t *)antenna0_sample)[1];
- ((int16_t *)antenna1_sample)[1] = -((int16_t *)antenna0_sample)[0];
- break;
+ case 3: // 1 -j
+ ((int16_t *)antenna1_sample)[0] = ((int16_t *)antenna0_sample)[1];
+ ((int16_t *)antenna1_sample)[1] = -((int16_t *)antenna0_sample)[0];
+ break;
}
// normalize
/* ((int16_t *)antenna0_sample)[0] = (int16_t)((((int16_t *)antenna0_sample)[0]*ONE_OVER_SQRT2_Q15)>>15);
- ((int16_t *)antenna0_sample)[1] = (int16_t)((((int16_t *)antenna0_sample)[1]*ONE_OVER_SQRT2_Q15)>>15); ((int16_t *)antenna1_sample)[0] = (int16_t)((((int16_t *)antenna1_sample)[0]*ONE_OVER_SQRT2_Q15)>>15);
- ((int16_t *)antenna1_sample)[1] = (int16_t)((((int16_t *)antenna1_sample)[1]*ONE_OVER_SQRT2_Q15)>>15); */
+ ((int16_t *)antenna0_sample)[1] = (int16_t)((((int16_t *)antenna0_sample)[1]*ONE_OVER_SQRT2_Q15)>>15); ((int16_t *)antenna1_sample)[0] = (int16_t)((((int16_t *)antenna1_sample)[0]*ONE_OVER_SQRT2_Q15)>>15);
+ ((int16_t *)antenna1_sample)[1] = (int16_t)((((int16_t *)antenna1_sample)[1]*ONE_OVER_SQRT2_Q15)>>15); */
}
uint32_t FOUR[2]={0,4};
uint32_t TWO[2]={0,2};
-int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
+int allocate_REs_in_RB_no_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB,
int **txdataF,
uint32_t *jj,
uint32_t *jj2,
@@ -147,11 +173,14 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
uint32_t *re_allocated,
uint8_t skip_dc,
uint8_t skip_half,
+ uint8_t lprime,
+ uint8_t mprime,
+ uint8_t Ns,
int *P1_SHIFT,
int *P2_SHIFT)
{
-
+ LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms;
uint8_t *x0 = dlsch0_harq->e;
uint32_t qam16_table_offset_re = 0;
uint32_t qam16_table_offset_im = 0;
@@ -205,7 +234,7 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
return(0);
}
-int allocate_REs_in_RB_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
+int allocate_REs_in_RB_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB,
int **txdataF,
uint32_t *jj,
uint32_t *jj2,
@@ -221,10 +250,14 @@ int allocate_REs_in_RB_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
uint32_t *re_allocated,
uint8_t skip_dc,
uint8_t skip_half,
+ uint8_t lprime,
+ uint8_t mprime,
+ uint8_t Ns,
int *P1_SHIFT,
int *P2_SHIFT)
{
+ LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms;
uint8_t *x0 = dlsch0_harq->e;
uint32_t qam16_table_offset_re = 0;
@@ -287,7 +320,7 @@ int allocate_REs_in_RB_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
return(0);
}
-int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
+int allocate_REs_in_RB_no_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB,
int **txdataF,
uint32_t *jj,
uint32_t *jj2,
@@ -303,10 +336,14 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
uint32_t *re_allocated,
uint8_t skip_dc,
uint8_t skip_half,
+ uint8_t lprime,
+ uint8_t mprime,
+ uint8_t Ns,
int *P1_SHIFT,
int *P2_SHIFT)
{
+ LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms;
uint8_t *x0 = dlsch0_harq->e;
uint32_t qam64_table_offset_re = 0;
@@ -423,7 +460,7 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
return(0);
}
-int allocate_REs_in_RB_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
+int allocate_REs_in_RB_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB,
int **txdataF,
uint32_t *jj,
uint32_t *jj2,
@@ -439,10 +476,14 @@ int allocate_REs_in_RB_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
uint32_t *re_allocated,
uint8_t skip_dc,
uint8_t skip_half,
+ uint8_t lprime,
+ uint8_t mprime,
+ uint8_t Ns,
int *P1_SHIFT,
int *P2_SHIFT)
{
+ LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms;
uint8_t *x0 = dlsch0_harq->e;
uint32_t qam64_table_offset_re = 0;
@@ -511,7 +552,7 @@ int allocate_REs_in_RB_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
return(0);
}
-int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
+int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB,
int32_t **txdataF,
uint32_t *jj,
uint32_t *jj2,
@@ -527,11 +568,16 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
uint32_t *re_allocated,
uint8_t skip_dc,
uint8_t skip_half,
+ uint8_t lprime,
+ uint8_t mprime,
+ uint8_t Ns,
int *P1_SHIFT,
int *P2_SHIFT)
{
+ LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms;
+
uint8_t *x0 = dlsch0_harq->e;
MIMO_mode_t mimo_mode = dlsch0_harq->mimo_mode;
@@ -573,10 +619,21 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
int32_t tmp_sample1,tmp_sample2;
int16_t tmp_amp=amp;
int s=1;
+ int mprime2 = mprime,ind,ind_dword,ind_qpsk_symb;
gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);
// if (mimo_mode == LARGE_CDD) gain_lin_QPSK>>=1;
+ int32_t qpsk[4];
+ ((int16_t *)&qpsk[0])[0] = gain_lin_QPSK;
+ ((int16_t *)&qpsk[0])[1] = gain_lin_QPSK;
+ ((int16_t *)&qpsk[1])[0] = -gain_lin_QPSK;
+ ((int16_t *)&qpsk[1])[1] = gain_lin_QPSK;;
+ ((int16_t *)&qpsk[2])[0] = gain_lin_QPSK;;
+ ((int16_t *)&qpsk[2])[1] = -gain_lin_QPSK;;
+ ((int16_t *)&qpsk[3])[0] = -gain_lin_QPSK;;
+ ((int16_t *)&qpsk[3])[1] = -gain_lin_QPSK;
+
if (dlsch1_harq) {
x1 = dlsch1_harq->e;
// Fill these in later for TM8-10
@@ -587,7 +644,8 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
}
#ifdef DEBUG_DLSCH_MODULATION
- printf("allocate_re (mod %d): symbol_offset %d re_offset %d (%d,%d), jj %d -> %d,%d\n",mod_order0,symbol_offset,re_offset,skip_dc,skip_half,*jj, x0[*jj], x0[1+*jj]);
+ printf("allocate_re (mod %d): symbol_offset %d re_offset %d (%d,%d), jj %d -> %d,%d\n",mod_order0,symbol_offset,re_offset,skip_dc,skip_half,*jj, x0[*jj],
+x0[1+*jj]);
#endif
first_re=0;
@@ -620,15 +678,11 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
case 2: //QPSK
// printf("re %d %d(%d) : %d,%d => ",re,tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
- for (aa=0; aanb_antennas_tx; aa++) {
- ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
- }
+ ((int16_t*)&txdataF[0][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
*jj = *jj + 1;
- for (aa=0; aanb_antennas_tx; aa++) {
- ((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
- }
+ ((int16_t*)&txdataF[0][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
*jj = *jj + 1;
@@ -661,12 +715,10 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
*jj=*jj+1;
- for (aa=0; aanb_antennas_tx; aa++) {
- ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s0[qam16_table_offset_re];
- ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s0[qam16_table_offset_im];
- // ((int16_t *)&txdataF[aa][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
- // ((int16_t *)&txdataF[aa][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
- }
+ ((int16_t *)&txdataF[0][tti_offset])[0]+=qam_table_s0[qam16_table_offset_re];
+ ((int16_t *)&txdataF[0][tti_offset])[1]+=qam_table_s0[qam16_table_offset_im];
+ // ((int16_t *)&txdataF[aa][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
+ // ((int16_t *)&txdataF[aa][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
break;
@@ -706,10 +758,8 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
*jj=*jj+1;
- for (aa=0; aanb_antennas_tx; aa++) {
- ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s0[qam64_table_offset_re];
- ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s0[qam64_table_offset_im];
- }
+ ((int16_t *)&txdataF[0][tti_offset])[0]+=qam_table_s0[qam64_table_offset_re];
+ ((int16_t *)&txdataF[0][tti_offset])[1]+=qam_table_s0[qam64_table_offset_im];
break;
@@ -912,7 +962,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
*re_allocated = *re_allocated + 1;
- if (frame_parms->nb_antennas_tx == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
switch (mod_order0) {
default:
LOG_E(PHY,"Unknown mod_order0 %d\n",mod_order0);
@@ -1128,7 +1178,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15);
((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15);
- if (frame_parms->nb_antennas_tx == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index);
((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15);
((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15);
@@ -1168,7 +1218,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
((int16_t *)&txdataF[0][tti_offset])[0] += ((int16_t*)&tmp_sample1)[0];
((int16_t *)&txdataF[0][tti_offset])[1] += ((int16_t*)&tmp_sample1)[1];
- if (frame_parms->nb_antennas_tx == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index);
((int16_t*)&txdataF[1][tti_offset])[0] += ((int16_t*)&tmp_sample2)[0];
((int16_t*)&txdataF[1][tti_offset])[1] += ((int16_t*)&tmp_sample2)[1];
@@ -1218,7 +1268,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
((int16_t *)&txdataF[0][tti_offset])[0] += ((int16_t*)&tmp_sample1)[0];
((int16_t *)&txdataF[0][tti_offset])[1] += ((int16_t*)&tmp_sample1)[1];
- if (frame_parms->nb_antennas_tx == 2) {
+ if (frame_parms->nb_antenna_ports_eNB == 2) {
layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index);
((int16_t*)&txdataF[1][tti_offset])[0] += ((int16_t*)&tmp_sample2)[0];
((int16_t*)&txdataF[1][tti_offset])[1] += ((int16_t*)&tmp_sample2)[1];
@@ -1226,7 +1276,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
break;
- }
+ }
}
if (mimo_mode == ALAMOUTI) {
@@ -1238,10 +1288,114 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
*re_allocated = *re_allocated + 1;
}
}
+
+ if (mimo_mode == TM7) {
+ *re_allocated = *re_allocated + 1;
- if (mimo_mode >= TM8) { //TM8,TM9,TM10
+ if (is_not_UEspecRS(lprime,re,frame_parms->Nid_cell%3,frame_parms->Ncp,7)) {
- if (is_not_UEspecRS(first_layer0,re)) {
+ switch (mod_order0){
+ case 2: //QPSK
+
+ ((int16_t*)&txdataF[5][tti_offset])[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+ *jj = *jj + 1;
+ ((int16_t*)&txdataF[5][tti_offset])[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+ *jj = *jj + 1;
+
+ //printf("%d(%d) : %d,%d =>
+ //",tti_offset,*jj,((int16_t*)&tmp_sample1)[0],((int16_t*)&tmp_sample1)[1]);
+ break;
+
+ case 4: //16QAM
+
+ qam16_table_offset_re = 0;
+ qam16_table_offset_im = 0;
+
+ if (x0[*jj] == 1)
+ qam16_table_offset_re+=2;
+
+ *jj=*jj+1;
+
+ if (x0[*jj] == 1)
+ qam16_table_offset_im+=2;
+
+ *jj=*jj+1;
+
+
+ if (x0[*jj] == 1)
+ qam16_table_offset_re+=1;
+
+ *jj=*jj+1;
+
+ if (x0[*jj] == 1)
+ qam16_table_offset_im+=1;
+
+ *jj=*jj+1;
+
+ ((int16_t*)&txdataF[5][tti_offset])[0] = (int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
+ ((int16_t*)&txdataF[5][tti_offset])[1] = (int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
+
+ break;
+
+ case 6: //64QAM
+
+
+ qam64_table_offset_re = 0;
+ qam64_table_offset_im = 0;
+
+ if (x0[*jj] == 1)
+ qam64_table_offset_re+=4;
+
+ *jj=*jj+1;
+
+ if (x0[*jj] == 1)
+ qam64_table_offset_im+=4;
+
+ *jj=*jj+1;
+
+ if (x0[*jj] == 1)
+ qam64_table_offset_re+=2;
+
+ *jj=*jj+1;
+
+ if (x0[*jj] == 1)
+ qam64_table_offset_im+=2;
+
+ *jj=*jj+1;
+
+ if (x0[*jj] == 1)
+ qam64_table_offset_re+=1;
+
+ *jj=*jj+1;
+
+ if (x0[*jj] == 1)
+ qam64_table_offset_im+=1;
+
+ *jj=*jj+1;
+
+ ((int16_t*)&txdataF[5][tti_offset])[0] = (int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
+ ((int16_t*)&txdataF[5][tti_offset])[1] = (int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
+
+ break;
+
+ }
+ } else {
+ //precoding UE spec RS
+ //printf("precoding UE spec RS\n");
+
+ ind = 3*lprime*dlsch0_harq->nb_rb+mprime2;
+ ind_dword = ind>>4;
+ ind_qpsk_symb = ind&0xf;
+
+ txdataF[5][tti_offset] = qpsk[(phy_vars_eNB->lte_gold_uespec_port5_table[0][Ns][ind_dword]>>(2*ind_qpsk_symb))&3];
+ mprime2++;
+
+ }
+
+ } else if (mimo_mode >= TM8) { //TM8,TM9,TM10
+ //uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, uint8_t beamforming_mode)
+
+ if (is_not_UEspecRS(lprime,re,frame_parms->nushift,frame_parms->Ncp,8)) {
switch (mod_order0) {
case 2: //QPSK
@@ -1256,7 +1410,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
break;
case 4: //16QAM
- if (is_not_UEspecRS(0/*layer (FIXME uninitialized!)*/,re)) {
+ if (is_not_UEspecRS(lprime,re,frame_parms->nushift,frame_parms->Ncp,8)) {
qam16_table_offset_re = 0;
qam16_table_offset_im = 0;
@@ -1345,21 +1499,22 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
return(0);
}
+
int allocate_REs_in_RB_MCH(int32_t **txdataF,
uint32_t *jj,
- uint16_t re_offset,
- uint32_t symbol_offset,
- uint8_t *x0,
- uint8_t l,
- uint8_t mod_order,
- int16_t amp,
- int16_t *qam_table_s,
- uint32_t *re_allocated,
- uint8_t skip_dc,
- LTE_DL_FRAME_PARMS *frame_parms)
+ uint16_t re_offset,
+ uint32_t symbol_offset,
+ uint8_t *x0,
+ uint8_t l,
+ uint8_t mod_order,
+ int16_t amp,
+ int16_t *qam_table_s,
+ uint32_t *re_allocated,
+ uint8_t skip_dc,
+ LTE_DL_FRAME_PARMS *frame_parms)
{
- uint32_t tti_offset,aa;
+ uint32_t tti_offset;
uint8_t re;
uint8_t qam64_table_offset_re = 0;
uint8_t qam64_table_offset_im = 0;
@@ -1397,99 +1552,91 @@ int allocate_REs_in_RB_MCH(int32_t **txdataF,
switch (mod_order) {
- case 2: //QPSK
+ case 2: //QPSK
// printf("%d : %d,%d => ",tti_offset,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
- for (aa=0; aanb_antennas_tx; aa++)
- ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
+ ((int16_t*)&txdataF[4][tti_offset])[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
*jj = *jj + 1;
- for (aa=0; aanb_antennas_tx; aa++)
- ((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
+ ((int16_t*)&txdataF[4][tti_offset])[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
*jj = *jj + 1;
// printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
break;
- case 4: //16QAM
+ case 4: //16QAM
- qam16_table_offset_re = 0;
- qam16_table_offset_im = 0;
+ qam16_table_offset_re = 0;
+ qam16_table_offset_im = 0;
- if (x0[*jj] == 1)
- qam16_table_offset_re+=2;
+ if (x0[*jj] == 1)
+ qam16_table_offset_re+=2;
- *jj=*jj+1;
+ *jj=*jj+1;
- if (x0[*jj] == 1)
- qam16_table_offset_im+=2;
+ if (x0[*jj] == 1)
+ qam16_table_offset_im+=2;
- *jj=*jj+1;
+ *jj=*jj+1;
- if (x0[*jj] == 1)
- qam16_table_offset_re+=1;
+ if (x0[*jj] == 1)
+ qam16_table_offset_re+=1;
- *jj=*jj+1;
+ *jj=*jj+1;
- if (x0[*jj] == 1)
- qam16_table_offset_im+=1;
+ if (x0[*jj] == 1)
+ qam16_table_offset_im+=1;
- *jj=*jj+1;
+ *jj=*jj+1;
- for (aa=0; aanb_antennas_tx; aa++) {
- ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s[qam16_table_offset_re];
- ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s[qam16_table_offset_im];
- // ((int16_t *)&txdataF[aa][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
- // ((int16_t *)&txdataF[aa][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
- }
+ ((int16_t *)&txdataF[4][tti_offset])[0]=qam_table_s[qam16_table_offset_re];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
+ ((int16_t *)&txdataF[4][tti_offset])[1]=qam_table_s[qam16_table_offset_im];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
- break;
+ break;
- case 6: //64QAM
+ case 6: //64QAM
- qam64_table_offset_re = 0;
- qam64_table_offset_im = 0;
+ qam64_table_offset_re = 0;
+ qam64_table_offset_im = 0;
- if (x0[*jj] == 1)
- qam64_table_offset_re+=4;
+ if (x0[*jj] == 1)
+ qam64_table_offset_re+=4;
- *jj=*jj+1;
+ *jj=*jj+1;
- if (x0[*jj] == 1)
- qam64_table_offset_im+=4;
+ if (x0[*jj] == 1)
+ qam64_table_offset_im+=4;
- *jj=*jj+1;
+ *jj=*jj+1;
- if (x0[*jj] == 1)
- qam64_table_offset_re+=2;
+ if (x0[*jj] == 1)
+ qam64_table_offset_re+=2;
- *jj=*jj+1;
+ *jj=*jj+1;
- if (x0[*jj] == 1)
- qam64_table_offset_im+=2;
+ if (x0[*jj] == 1)
+ qam64_table_offset_im+=2;
- *jj=*jj+1;
+ *jj=*jj+1;
- if (x0[*jj] == 1)
- qam64_table_offset_re+=1;
+ if (x0[*jj] == 1)
+ qam64_table_offset_re+=1;
- *jj=*jj+1;
+ *jj=*jj+1;
- if (x0[*jj] == 1)
- qam64_table_offset_im+=1;
+ if (x0[*jj] == 1)
+ qam64_table_offset_im+=1;
- *jj=*jj+1;
+ *jj=*jj+1;
- for (aa=0; aanb_antennas_tx; aa++) {
- ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s[qam64_table_offset_re];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
- ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s[qam64_table_offset_im];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
- }
+ ((int16_t *)&txdataF[4][tti_offset])[0]=qam_table_s[qam64_table_offset_re];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
+ ((int16_t *)&txdataF[4][tti_offset])[1]=qam_table_s[qam64_table_offset_im];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
- break;
+ break;
}
}
@@ -1506,38 +1653,38 @@ uint8_t get_pmi(uint8_t N_RB_DL,LTE_DL_eNB_HARQ_t *dlsch_harq,uint16_t rb)
// printf("Getting pmi for RB %d => %d\n",rb,(pmi_alloc>>((rb>>2)<<1))&3);
switch (N_RB_DL) {
- case 6: // 1 PRB per subband
- if (mode <= PUSCH_PRECODING1)
- return((pmi_alloc>>(rb<<1))&3);
- else
- return((pmi_alloc>>rb)&1);
+ case 6: // 1 PRB per subband
+ if (mode <= PUSCH_PRECODING1)
+ return((pmi_alloc>>(rb<<1))&3);
+ else
+ return((pmi_alloc>>rb)&1);
- break;
+ break;
- default:
- case 25: // 4 PRBs per subband
- if (mode <= PUSCH_PRECODING1)
- return((pmi_alloc>>((rb>>2)<<1))&3);
- else
- return((pmi_alloc>>(rb>>2))&1);
+ default:
+ case 25: // 4 PRBs per subband
+ if (mode <= PUSCH_PRECODING1)
+ return((pmi_alloc>>((rb>>2)<<1))&3);
+ else
+ return((pmi_alloc>>(rb>>2))&1);
- break;
+ break;
- case 50: // 6 PRBs per subband
- if (mode <= PUSCH_PRECODING1)
- return((pmi_alloc>>((rb/6)<<1))&3);
- else
- return((pmi_alloc>>(rb/6))&1);
+ case 50: // 6 PRBs per subband
+ if (mode <= PUSCH_PRECODING1)
+ return((pmi_alloc>>((rb/6)<<1))&3);
+ else
+ return((pmi_alloc>>(rb/6))&1);
- break;
+ break;
- case 100: // 8 PRBs per subband
- if (mode <= PUSCH_PRECODING1)
- return((pmi_alloc>>((rb>>3)<<1))&3);
- else
- return((pmi_alloc>>(rb>>3))&1);
+ case 100: // 8 PRBs per subband
+ if (mode <= PUSCH_PRECODING1)
+ return((pmi_alloc>>((rb>>3)<<1))&3);
+ else
+ return((pmi_alloc>>(rb>>3))&1);
- break;
+ break;
}
}
@@ -1679,14 +1826,15 @@ inline int check_skip_dc(int rb,LTE_DL_FRAME_PARMS *frame_parms) {
}
-int dlsch_modulation(int32_t **txdataF,
+int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
+ int32_t **txdataF,
int16_t amp,
uint32_t subframe_offset,
- LTE_DL_FRAME_PARMS *frame_parms,
uint8_t num_pdcch_symbols,
LTE_eNB_DLSCH_t *dlsch0,
LTE_eNB_DLSCH_t *dlsch1)
{
+ LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms;
uint8_t nsymb;
uint8_t harq_pid = dlsch0->current_harq_pid;
@@ -1704,7 +1852,7 @@ int dlsch_modulation(int32_t **txdataF,
int16_t qam16_table_a0[4],qam64_table_a0[8],qam16_table_b0[4],qam64_table_b0[8];
int16_t qam16_table_a1[4],qam64_table_a1[8],qam16_table_b1[4],qam64_table_b1[8];
int16_t *qam_table_s0=NULL,*qam_table_s1=NULL;
- int (*allocate_REs)(LTE_DL_FRAME_PARMS *,
+ int (*allocate_REs)(PHY_VARS_eNB*,
int **,
uint32_t*,
uint32_t*,
@@ -1720,10 +1868,17 @@ int dlsch_modulation(int32_t **txdataF,
uint32_t *,
uint8_t,
uint8_t,
+ uint8_t,
+ uint8_t,
+ uint8_t,
int *,
int *);
int P1_SHIFT[13],P2_SHIFT[13];
int offset,nushiftmod3;
+ MIMO_mode_t mimo_mode = dlsch0_harq->mimo_mode;
+ uint8_t mprime=0,Ns;
+ int8_t lprime=-1;
+ int aa=0;
#ifdef DEBUG_DLSCH_MODULATION
uint8_t Nl0 = dlsch0_harq->Nl;
@@ -1746,7 +1901,7 @@ int dlsch_modulation(int32_t **txdataF,
amp_rho_b = (int16_t)(((int32_t)amp*dlsch0->sqrt_rho_b)>>13);
if (mod_order0 == 4)
- for (i=0; i<4; i++) {
+ for (i=0;i<4; i++) {
qam16_table_a0[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_a)>>15);
qam16_table_b0[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_b)>>15);
}
@@ -1804,6 +1959,39 @@ int dlsch_modulation(int32_t **txdataF,
pilots=0;
}
+ if(mimo_mode==TM7){ //36.211 V8.6.0 2009-03
+ mprime = 0;
+ if (frame_parms->Ncp==0) { // normal prefix
+ if (l==12)
+ lprime=3; // pilots in nushift+3, nushift+9
+ else if (l==9)
+ lprime=2; // pilots in nushift, nushift+6
+ else if (l==6)
+ lprime=1; // pilots in nushift+3, nushift+9
+ else if (l==3)
+ lprime=0; // pilots in nushift, nushift+6
+ else
+ lprime=-1;
+ } else {
+ if (l==10)
+ lprime=2;
+ else if (l==7)
+ lprime=1;
+ else if (l==4)
+ lprime=0;
+ else
+ lprime=-1;
+ }
+
+ // mapping ue specific beamforming weights from UE specified DLSCH structure to common space
+ for (aa=0;aanb_antennas_tx;aa++){
+ memcpy(phy_vars_eNB->common_vars.beam_weights[0][5][aa],dlsch0->ue_spec_bf_weights[0][aa],frame_parms->ofdm_symbol_size*sizeof(int32_t));
+ }
+
+ }
+
+ Ns = 2*subframe_offset+(l>=(nsymb>>1));
+
offset = (pilots==2)?3:0;
nushiftmod3 = frame_parms->nushift%3;
@@ -1934,25 +2122,32 @@ int dlsch_modulation(int32_t **txdataF,
if (rb_alloc_ind > 0) {
- // printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj);
- allocate_REs(frame_parms,
- txdataF,
- &jj,
- &jj2,
- re_offset,
- symbol_offset,
- dlsch0->harq_processes[harq_pid],
- (dlsch1==NULL) ? NULL : dlsch1->harq_processes[harq_pid],
- pilots,
- ((pilots) ? amp_rho_b : amp_rho_a),
- get_pmi(frame_parms->N_RB_DL,dlsch0->harq_processes[harq_pid],rb),
- qam_table_s0,
- qam_table_s1,
- &re_allocated,
- skip_dc,
- skip_half,
- P1_SHIFT,
- P2_SHIFT);
+ // printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj);
+ allocate_REs(phy_vars_eNB,
+ txdataF,
+ &jj,
+ &jj2,
+ re_offset,
+ symbol_offset,
+ dlsch0->harq_processes[harq_pid],
+ (dlsch1==NULL) ? NULL : dlsch1->harq_processes[harq_pid],
+ pilots,
+ ((pilots) ? amp_rho_b : amp_rho_a),
+ get_pmi(frame_parms->N_RB_DL,dlsch0->harq_processes[harq_pid],rb),
+ qam_table_s0,
+ qam_table_s1,
+ &re_allocated,
+ skip_dc,
+ skip_half,
+ lprime,
+ mprime,
+ Ns,
+ P1_SHIFT,
+ P2_SHIFT);
+
+ if ((mimo_mode == TM7) && (lprime>=0))
+ mprime +=3+frame_parms->Ncp;
+
}
else {
// printf("Unallocated rb %d/symbol %d, re_offset %d, jj %d\n",rb,l,re_offset,jj);
@@ -1974,7 +2169,7 @@ int dlsch_modulation(int32_t **txdataF,
#ifdef DEBUG_DLSCH_MODULATION
- printf("generate_dlsch : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch0_harq->nb_rb,dlsch0_harq->rb_alloc,mod_order0,Nl0,2,0,subframe_offset));
+ printf("generate_dlsch : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch0_harq->nb_rb,dlsch0_harq->rb_alloc,mod_order0,Nl0,2,0,subframe_offset,1/*transmission mode*/));
#endif
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT);
@@ -2073,7 +2268,7 @@ int mch_modulation(int32_t **txdataF,
#ifdef DEBUG_DLSCH_MODULATION
- printf("generate_dlsch(MCH) : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch->harq_processes[0]->nb_rb,dlsch->harq_processes[0]->rb_alloc,mod_order,1,2,0,subframe_offset));
+ printf("generate_dlsch(MCH) : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch->harq_processes[0]->nb_rb,dlsch->harq_processes[0]->rb_alloc,mod_order,1,2,0,subframe_offset,1/*transmission mode*/));
#endif
return (re_allocated);
diff --git a/openair1/PHY/LTE_TRANSPORT/group_hopping.c b/openair1/PHY/LTE_TRANSPORT/group_hopping.c
index be3acce5bd..bbd908b34a 100644
--- a/openair1/PHY/LTE_TRANSPORT/group_hopping.c
+++ b/openair1/PHY/LTE_TRANSPORT/group_hopping.c
@@ -42,6 +42,8 @@ void generate_grouphop(LTE_DL_FRAME_PARMS *frame_parms)
// This is from Section 5.5.1.3
uint32_t fss_pusch = frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH;
+ uint32_t fss_pucch = frame_parms->Nid_cell;
+
x2 = frame_parms->Nid_cell/30;
#ifdef DEBUG_GROUPHOP
printf("[PHY] GroupHop:");
@@ -49,7 +51,10 @@ void generate_grouphop(LTE_DL_FRAME_PARMS *frame_parms)
for (ns=0; ns<20; ns++) {
if (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled == 0)
+ {
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[ns] = fss_pusch%30;
+ frame_parms->pucch_config_common.grouphop[ns] = fss_pucch%30;
+ }
else {
if ((ns&3) == 0) {
s = lte_gold_generic(&x1,&x2,reset);
@@ -57,6 +62,7 @@ void generate_grouphop(LTE_DL_FRAME_PARMS *frame_parms)
}
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[ns] = (((uint8_t*)&s)[ns&3]+fss_pusch)%30;
+ frame_parms->pucch_config_common.grouphop[ns] = (((uint8_t*)&s)[ns&3]+fss_pucch)%30;
}
#ifdef DEBUG_GROUPHOP
diff --git a/openair1/PHY/LTE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_TRANSPORT/initial_sync.c
index 661fe96be8..75c558f52c 100644
--- a/openair1/PHY/LTE_TRANSPORT/initial_sync.c
+++ b/openair1/PHY/LTE_TRANSPORT/initial_sync.c
@@ -152,7 +152,7 @@ int pbch_detection(PHY_VARS_UE *ue, runmode_t mode)
if (pbch_decoded) {
- frame_parms->nb_antennas_tx_eNB = pbch_tx_ant;
+ frame_parms->nb_antenna_ports_eNB = pbch_tx_ant;
// set initial transmission mode to 1 or 2 depending on number of detected TX antennas
frame_parms->mode1_flag = (pbch_tx_ant==1);
@@ -462,6 +462,13 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
}
}
+ /* Consider this is a false detection if the offset is > 1000 Hz */
+ if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) )
+ {
+ ret=-1;
+ LOG_E(HW,"Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset);
+ }
+
if (ret==0) { // PBCH found so indicate sync to higher layers and configure frame parameters
//#ifdef DEBUG_INITIAL_SYNCH
@@ -469,6 +476,15 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
//#endif
if (ue->UE_scan_carrier == 0) {
+
+ #if UE_AUTOTEST_TRACE
+ LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n",
+ ue->Mod_id,
+ ue->proc.proc_rxtx[0].frame_rx,
+ ue->rx_offset,
+ ue->common_vars.freq_offset );
+ #endif
+
if (ue->mac_enabled==1) {
LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id);
//mac_resynch();
@@ -506,7 +522,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
ue->frame_parms.N_RB_DL,
ue->frame_parms.phich_config_common.phich_duration,
phich_string[ue->frame_parms.phich_config_common.phich_resource],
- ue->frame_parms.nb_antennas_tx_eNB);
+ ue->frame_parms.nb_antenna_ports_eNB);
#if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
LOG_I(PHY,"[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n",
diff --git a/openair1/PHY/LTE_TRANSPORT/lte_mcs.c b/openair1/PHY/LTE_TRANSPORT/lte_mcs.c
index b4f158f873..0abc1511ea 100644
--- a/openair1/PHY/LTE_TRANSPORT/lte_mcs.c
+++ b/openair1/PHY/LTE_TRANSPORT/lte_mcs.c
@@ -325,11 +325,8 @@ int adjust_G(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_orde
return(0);
}
-int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe)
+int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe,uint8_t beamforming_mode)
{
-
-
-
int G_adj;
if (is_pmch_subframe(frame,subframe,frame_parms) == 0) {
@@ -340,9 +337,11 @@ int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint
// PDDDPDD PDDDPDD - 13 PDSCH symbols, 10 full, 3 w/ pilots = 10*12 + 3*8
// PCDDPDD PDDDPDD - 12 PDSCH symbols, 9 full, 3 w/ pilots = 9*12 + 3*8
// PCCDPDD PDDDPDD - 11 PDSCH symbols, 8 full, 3 w/pilots = 8*12 + 3*8
- if (frame_parms->mode1_flag==0) // SISO
+ if (beamforming_mode==0 && frame_parms->mode1_flag==0)
return((((int)nb_rb * mod_order * ((11-num_pdcch_symbols)*12 + 3*8)) - G_adj)*Nl);
- else
+ else if(beamforming_mode==7)
+ return(((int)nb_rb * mod_order * ((7-num_pdcch_symbols)*12 + 3*10 + 4*9)) - G_adj);
+ else //SISO
return(((int)nb_rb * mod_order * ((11-num_pdcch_symbols)*12 + 3*10)) - G_adj);
} else {
// PDDPDD PDDPDD - 11 PDSCH symbols, 8 full, 3 w/ pilots = 8*12 + 3*8
@@ -350,7 +349,9 @@ int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint
// PCCPDD PDDPDD - 9 PDSCH symbols, 6 full, 3 w/pilots = 6*12 + 3*8
if (frame_parms->mode1_flag==0)
return((((int)nb_rb * mod_order * ((9-num_pdcch_symbols)*12 + 3*8)) - G_adj)*Nl);
- else
+ else if(beamforming_mode==7)
+ return(((int)nb_rb * mod_order * ((5-num_pdcch_symbols)*12 + 3*8 + 4*9)) - G_adj);
+ else //SISO
return(((int)nb_rb * mod_order * ((9-num_pdcch_symbols)*12 + 3*10)) - G_adj);
}
} else { // This is an MBSFN subframe
diff --git a/openair1/PHY/LTE_TRANSPORT/pbch.c b/openair1/PHY/LTE_TRANSPORT/pbch.c
index 03190de43b..8f6489861b 100644
--- a/openair1/PHY/LTE_TRANSPORT/pbch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pbch.c
@@ -66,7 +66,7 @@ int allocate_pbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
MIMO_mode_t mimo_mode = (frame_parms->mode1_flag==1)?SISO:ALAMOUTI;
- uint32_t tti_offset,aa;
+ uint32_t tti_offset;
uint8_t re;
int16_t gain_lin_QPSK;
int16_t re_off=re_offset;
@@ -91,15 +91,11 @@ int allocate_pbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
*re_allocated = *re_allocated + 1;
// printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
- for (aa=0; aanb_antennas_tx; aa++) {
- ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
- }
+ ((int16_t*)&txdataF[0][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
*jj = *jj + 1;
- for (aa=0; aanb_antennas_tx; aa++) {
- ((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
- }
+ ((int16_t*)&txdataF[0][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
*jj = *jj + 1;
} else if (mimo_mode == ALAMOUTI) {
@@ -192,7 +188,7 @@ int generate_pbch(LTE_eNB_PBCH *eNB_pbch,
/*
// scramble crc with PBCH CRC mask (Table 5.3.1.1-1 of 3GPP 36.212-860)
- switch (frame_parms->nb_antennas_tx_eNB) {
+ switch (frame_parms->nb_antenna_ports_eNB) {
case 1:
crc = crc ^ (uint16_t) 0;
break;
@@ -224,7 +220,7 @@ int generate_pbch(LTE_eNB_PBCH *eNB_pbch,
if (frame_parms->mode1_flag == 1)
amask = 0x0000;
else {
- switch (frame_parms->nb_antennas_tx_eNB) {
+ switch (frame_parms->nb_antenna_ports_eNB) {
case 1:
amask = 0x0000;
break;
@@ -484,7 +480,7 @@ uint16_t pbch_extract(int **rxdataF,
}
}
- for (aatx=0; aatx<4; aatx++) { //frame_parms->nb_antennas_tx_eNB;aatx++) {
+ for (aatx=0; aatx<4; aatx++) { //frame_parms->nb_antenna_ports_eNB;aatx++) {
if (high_speed_flag == 1)
dl_ch0 = &dl_ch_estimates[(aatx<<1)+aarx][LTE_CE_OFFSET+ch_offset+(symbol*(frame_parms->ofdm_symbol_size))];
else
@@ -546,7 +542,7 @@ int pbch_channel_level(int **dl_ch_estimates_ext,
uint32_t nsymb = (frame_parms->Ncp==0) ? 7:6;
uint32_t symbol_mod = symbol % nsymb;
- for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antennas_tx_eNB;aatx++)
+ for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antenna_ports_eNB;aatx++)
for (aarx=0; aarxnb_antennas_rx; aarx++) {
//clear average level
@@ -616,7 +612,7 @@ void pbch_channel_compensation(int **rxdataF_ext,
#endif
symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
- for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antennas_tx_eNB;aatx++)
+ for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antenna_ports_eNB;aatx++)
for (aarx=0; aarxnb_antennas_rx; aarx++) {
#if defined(__x86_64__) || defined(__i386__)
@@ -723,7 +719,7 @@ void pbch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms,
symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
if (frame_parms->nb_antennas_rx>1) {
- for (aatx=0; aatx<4; aatx++) { //frame_parms->nb_antennas_tx_eNB;aatx++) {
+ for (aatx=0; aatx<4; aatx++) { //frame_parms->nb_antenna_ports_eNB;aatx++) {
#if defined(__x86_64__) || defined(__i386__)
rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol_mod*6*12];
rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol_mod*6*12];
@@ -1070,7 +1066,7 @@ uint16_t rx_pbch_emul(PHY_VARS_UE *phy_vars_ue,
if (pbch_phase == (frame_rx % 4)) {
if (uniformrandom() >= bler) {
memcpy(phy_vars_ue->pbch_vars[eNB_id]->decoded_output,PHY_vars_eNB_g[eNB_id][CC_id]->pbch_pdu,PBCH_PDU_SIZE);
- return(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antennas_tx_eNB);
+ return(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antenna_ports_eNB);
} else
return(-1);
} else
diff --git a/openair1/PHY/LTE_TRANSPORT/pcfich.c b/openair1/PHY/LTE_TRANSPORT/pcfich.c
index 8af540eea1..08a3d80904 100644
--- a/openair1/PHY/LTE_TRANSPORT/pcfich.c
+++ b/openair1/PHY/LTE_TRANSPORT/pcfich.c
@@ -208,7 +208,7 @@ void generate_pcfich(uint8_t num_pdcch_symbols,
if ((i!=nushiftmod3)&&(i!=(nushiftmod3+3))) {
txdataF[0][symbol_offset+reg_offset+i] = pcfich_d[0][m];
- if (frame_parms->nb_antennas_tx_eNB>1)
+ if (frame_parms->nb_antenna_ports_eNB>1)
txdataF[1][symbol_offset+reg_offset+i] = pcfich_d[1][m];
m++;
diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c
index 6b66ee0282..989567ca34 100644
--- a/openair1/PHY/LTE_TRANSPORT/phich.c
+++ b/openair1/PHY/LTE_TRANSPORT/phich.c
@@ -34,6 +34,10 @@
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "defs.h"
+
+#include "LAYER2/MAC/extern.h"
+#include "LAYER2/MAC/defs.h"
+
#ifndef USER_MODE
#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
#endif
@@ -1046,7 +1050,6 @@ void generate_phich(LTE_DL_FRAME_PARMS *frame_parms,
// This routine demodulates the PHICH and updates PUSCH/ULSCH parameters
-
void rx_phich(PHY_VARS_UE *ue,
UE_rxtx_proc_t *proc,
uint8_t subframe,
@@ -1081,8 +1084,10 @@ void rx_phich(PHY_VARS_UE *ue,
if (!ulsch)
return;
+ LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX Status: %d \n",ue->Mod_id,harq_pid,proc->frame_rx,subframe, ulsch->harq_processes[harq_pid]->status);
+
if (ulsch->harq_processes[harq_pid]->status == ACTIVE) {
- LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX ACTIVE\n",ue->Mod_id,harq_pid,proc->frame_rx,subframe);
+ LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX ACTIVE\n",ue->Mod_id,harq_pid,proc->frame_rx,subframe);
Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48;
if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0)
@@ -1375,15 +1380,39 @@ void rx_phich(PHY_VARS_UE *ue,
subframe,
HI16,
nseq_PHICH,
- ngroup_PHICH);
+ ngroup_PHICH,
+ ulsch->Mlimit);
//#endif
- ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
+
// ulsch->harq_processes[harq_pid]->Ndi = 0;
ulsch->harq_processes[harq_pid]->round++;
- ulsch->harq_processes[harq_pid]->rvidx = rv_table[ulsch->harq_processes[harq_pid]->round&3];
- ulsch->O_RI = 0;
- ulsch->O = 0;
- ulsch->uci_format = HLC_subband_cqi_nopmi;
+
+ if ( ulsch->harq_processes[harq_pid]->round >= (ulsch->Mlimit - 1) )
+ {
+ // this is last push re transmission
+ ulsch->harq_processes[harq_pid]->rvidx = rv_table[ulsch->harq_processes[harq_pid]->round&3];
+ ulsch->O_RI = 0;
+ ulsch->O = 0;
+ ulsch->uci_format = HLC_subband_cqi_nopmi;
+
+ // disable phich decoding since it is the last retransmission
+ ulsch->harq_processes[harq_pid]->status = IDLE;
+
+ //ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
+ //ulsch->harq_processes[harq_pid]->round = 0;
+
+ //LOG_I(PHY,"PUSCH MAX Retransmission acheived ==> flush harq buff (%d) \n",harq_pid);
+ //LOG_I(PHY,"[HARQ-UL harqId: %d] PHICH NACK MAX RETRANS(%d) ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->Mlimit, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, ulsch->harq_processes[harq_pid]->round);
+ }
+ else
+ {
+ // ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
+ ulsch->harq_processes[harq_pid]->rvidx = rv_table[ulsch->harq_processes[harq_pid]->round&3];
+ ulsch->O_RI = 0;
+ ulsch->O = 0;
+ ulsch->uci_format = HLC_subband_cqi_nopmi;
+ //LOG_I(PHY,"[HARQ-UL harqId: %d] PHICH NACK ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag,ulsch->harq_processes[harq_pid]->round);
+ }
}
@@ -1405,11 +1434,22 @@ void rx_phich(PHY_VARS_UE *ue,
//#endif
}
+ // LOG_I(PHY,"[HARQ-UL harqId: %d] subframe_scheduling_flag = %d \n",harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag);
+
+ // Incase of adaptive retransmission, PHICH is always decoded as ACK (at least with OAI-eNB)
+ // Workaround:
+ // rely only on DCI0 decoding and check if NDI has toggled
+ // save current harq_processes content in temporary struct
+ // harqId-8 corresponds to the temporary struct. In total we have 8 harq process(0 ..7) + 1 temporary harq process()
+ //ulsch->harq_processes[8] = ulsch->harq_processes[harq_pid];
+
ulsch->harq_processes[harq_pid]->subframe_scheduling_flag =0;
ulsch->harq_processes[harq_pid]->status = IDLE;
ulsch->harq_processes[harq_pid]->round = 0;
// inform MAC?
ue->ulsch_Msg3_active[eNB_id] = 0;
+
+ //LOG_I(PHY,"[HARQ-UL harqId: %d] PHICH ACK ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, ulsch->harq_processes[harq_pid]->round);
}
}
diff --git a/openair1/PHY/LTE_TRANSPORT/pilots.c b/openair1/PHY/LTE_TRANSPORT/pilots.c
index a1f7d5bac6..a4d0fae259 100644
--- a/openair1/PHY/LTE_TRANSPORT/pilots.c
+++ b/openair1/PHY/LTE_TRANSPORT/pilots.c
@@ -62,7 +62,7 @@ void generate_pilots(PHY_VARS_eNB *eNB,
// printf("tti %d : offset %d (slot %d)\n",tti,tti_offset,slot_offset);
//Generate Pilots
- //antenna 0 symbol 0 slot 0
+ //antenna port 0 symbol 0 slot 0
lte_dl_cell_spec(eNB,&txdataF[0][tti_offset],
amp,
slot_offset,
@@ -71,7 +71,7 @@ void generate_pilots(PHY_VARS_eNB *eNB,
// printf("tti %d : second_pilot offset %d \n",tti,tti_offset+(second_pilot*samples_per_symbol));
- //antenna 0 symbol 3/4 slot 0
+ //antenna port 0 symbol 3/4 slot 0
lte_dl_cell_spec(eNB,&txdataF[0][tti_offset+(second_pilot*samples_per_symbol)],
amp,
slot_offset,
@@ -79,7 +79,7 @@ void generate_pilots(PHY_VARS_eNB *eNB,
0);
// printf("tti %d : third_pilot offset %d \n",tti,tti_offset+((Nsymb>>1)*samples_per_symbol));
- //antenna 0 symbol 0 slot 1
+ //antenna port 0 symbol 0 slot 1
lte_dl_cell_spec(eNB,&txdataF[0][tti_offset+((Nsymb>>1)*samples_per_symbol)],
amp,
1+slot_offset,
@@ -87,7 +87,7 @@ void generate_pilots(PHY_VARS_eNB *eNB,
0);
// printf("tti %d : third_pilot offset %d \n",tti,tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol));
- //antenna 0 symbol 3/4 slot 1
+ //antenna port 0 symbol 3/4 slot 1
lte_dl_cell_spec(eNB,&txdataF[0][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)],
amp,
1+slot_offset,
@@ -95,66 +95,35 @@ void generate_pilots(PHY_VARS_eNB *eNB,
0);
- if (frame_parms->nb_antennas_tx > 1) {
- if (frame_parms->mode1_flag) {
- // antenna 1 symbol 0 slot 0
- lte_dl_cell_spec(eNB,&txdataF[1][tti_offset],
- amp,
- slot_offset,
- 0,
- 0);
+ if (frame_parms->nb_antenna_ports_eNB > 1) {
- // antenna 1 symbol 3 slot 0
- lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(second_pilot*samples_per_symbol)],
- amp,
- slot_offset,
- 1,
- 0);
-
- //antenna 1 symbol 0 slot 1
- lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(Nsymb>>1)*samples_per_symbol],
- amp,
- 1+slot_offset,
- 0,
- 0);
-
- // antenna 1 symbol 3 slot 1
- lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)],
- amp,
- 1+slot_offset,
- 1,
- 0);
-
- } else {
-
- // antenna 1 symbol 0 slot 0
+ // antenna port 1 symbol 0 slot 0
lte_dl_cell_spec(eNB,&txdataF[1][tti_offset],
amp,
slot_offset,
0,
1);
- // antenna 1 symbol 3 slot 0
+ // antenna port 1 symbol 3 slot 0
lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(second_pilot*samples_per_symbol)],
amp,
slot_offset,
1,
1);
- //antenna 1 symbol 0 slot 1
+ //antenna port 1 symbol 0 slot 1
lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(Nsymb>>1)*samples_per_symbol],
amp,
1+slot_offset,
0,
1);
- // antenna 1 symbol 3 slot 1
+ // antenna port 1 symbol 3 slot 1
lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)],
amp,
1+slot_offset,
1,
1);
- }
}
}
}
@@ -185,7 +154,7 @@ int generate_pilots_slot(PHY_VARS_eNB *eNB,
// printf("tti %d : offset %d (slot %d)\n",tti,tti_offset,slot_offset);
//Generate Pilots
- //antenna 0 symbol 0 slot 0
+ //antenna port 0 symbol 0 slot 0
lte_dl_cell_spec(eNB,
&txdataF[0][slot_offset],
amp,
@@ -204,44 +173,24 @@ int generate_pilots_slot(PHY_VARS_eNB *eNB,
0);
}
- if (frame_parms->nb_antennas_tx > 1) {
- if (frame_parms->mode1_flag) {
- // antenna 1 symbol 0 slot 0
+ if (frame_parms->nb_antenna_ports_eNB > 1) {
+
+ // antenna port 1 symbol 0 slot 0
+ lte_dl_cell_spec(eNB,
+ &txdataF[1][slot_offset],
+ amp,
+ slot,
+ 0,
+ 1);
+
+ if (first_pilot_only == 0) {
+ // antenna port 1 symbol 3 slot 0
lte_dl_cell_spec(eNB,
- &txdataF[1][slot_offset],
+ &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)],
amp,
slot,
- 0,
- 0);
-
- if (first_pilot_only==0) {
- // antenna 1 symbol 3 slot 0
- lte_dl_cell_spec(eNB,
- &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)],
- amp,
- slot,
- 1,
- 0);
- }
- } else {
-
- // antenna 1 symbol 0 slot 0
- lte_dl_cell_spec(eNB,
- &txdataF[1][slot_offset],
- amp,
- slot,
- 0,
+ 1,
1);
-
- if (first_pilot_only == 0) {
- // antenna 1 symbol 3 slot 0
- lte_dl_cell_spec(eNB,
- &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)],
- amp,
- slot,
- 1,
- 1);
- }
}
}
diff --git a/openair1/PHY/LTE_TRANSPORT/pilots_ue_spec.c b/openair1/PHY/LTE_TRANSPORT/pilots_ue_spec.c
new file mode 100644
index 0000000000..4a9010fca0
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/pilots_ue_spec.c
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@eurecom.fr
+
+ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+ *******************************************************************************/
+
+/*! \file PHY/LTE_TRANSPORT/uespec_pilots.c
+* \brief Top-level routines for generating DL ue-specific reference signals V12.5 2015-03
+* \author X.JIANG
+* \date 2011
+* \version 0.1
+* \company Eurecom
+* \email: xiwen.jiangeurecom.fr
+* \note
+* \warning
+*/
+//#include "defs.h"
+#include "PHY/defs.h"
+
+void generate_ue_spec_pilots(PHY_VARS_eNB *phy_vars_eNB,
+ uint8_t UE_id,
+ int32_t **txdataF,
+ int16_t amp,
+ uint16_t Ntti,
+ uint8_t beamforming_mode)
+{
+
+ /*LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms;
+
+ uint32_t tti,tti_offset,slot_offset,Nsymb,samples_per_symbol;
+ uint8_t second_pilot,aa;
+
+ // printf("Doing TX pilots Nsymb %d, second_pilot %d\n",Nsymb,second_pilot);
+
+ switch(beamforming_mode){
+ case 7:
+ for (tti=0; ttiofdm_symbol_size*Nsymb;
+ samples_per_symbol = frame_parms->ofdm_symbol_size;
+ slot_offset = (tti*2)%20;
+
+ // printf("tti %d : offset %d (slot %d)\n",tti,tti_offset,slot_offset);
+ //Generate UE specific Pilots
+ printf("generate_dl_ue_spec:tti_offset=%d\n",tti_offset);
+
+ if(frame_parms->Ncp==0) {
+ for(aa=0;aanb_antennas_tx;aa++){
+ //antenna port 5 symbol 0 slot 0
+ lte_dl_ue_spec(phy_vars_eNB,
+ UE_id,
+ &txdataF[aa][tti_offset+3*samples_per_symbol],
+ amp,
+ slot_offset,
+ 1,
+ 5,
+ 0);
+
+ //antenna port 5 symbol 1 slot 0
+ lte_dl_ue_spec(phy_vars_eNB,
+ UE_id,
+ &txdataF[aa][tti_offset+6*samples_per_symbol],
+ amp,
+ slot_offset,
+ 1,
+ 5,
+ 0);
+
+ //antenna port 5 symbol 0 slot 1
+ lte_dl_ue_spec(phy_vars_eNB,
+ UE_id,
+ &txdataF[aa][tti_offset+9*samples_per_symbol],
+ amp,
+ slot_offset+1,
+ 0,
+ 5,
+ 0);
+
+ //antenna port 5 symbol 1 slot 1
+ lte_dl_ue_spec(phy_vars_eNB,
+ UE_id,
+ &txdataF[aa][tti_offset+12*samples_per_symbol],
+ amp,
+ slot_offset+1,
+ 1,
+ 5,
+ 0);
+ }
+ } else{
+ msg("generate_ue_soec_pilots:Extented Cyclic Prefix for TM7 is not supported yet.\n");
+ }
+
+
+ }
+ break;
+
+ case 8:
+ case 9:
+ case 10:
+ default:
+ msg("[generate_ue_spec_pilots(in uespec_pilots.c)]ERROR:beamforming mode %d is not supported\n",beamforming_mode);
+
+ }*/
+}
+
+/*int generate_ue_spec_pilots_slot(PHY_VARS_eNB *phy_vars_eNB,
+ int32_t **txdataF,
+ int16_t amp,
+ uint16_t slot,
+ int first_pilot_only)
+{
+
+ LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms;
+ uint32_t slot_offset,Nsymb,samples_per_symbol;
+ uint8_t second_pilot;
+
+ if (slot<0 || slot>= 20) {
+ msg("generate_pilots_slot: slot not in range (%d)\n",slot);
+ return(-1);
+ }
+
+ Nsymb = (frame_parms->Ncp==0)?7:6;
+ second_pilot = (frame_parms->Ncp==0)?4:3;
+
+
+ slot_offset = slot*frame_parms->ofdm_symbol_size*Nsymb;
+ samples_per_symbol = frame_parms->ofdm_symbol_size;
+
+ // printf("tti %d : offset %d (slot %d)\n",tti,tti_offset,slot_offset);
+ //Generate Pilots
+
+ //antenna 0 symbol 0 slot 0
+ lte_dl_cell_spec(phy_vars_eNB,
+ &txdataF[0][slot_offset],
+ amp,
+ slot,
+ 0,
+ 0);
+
+
+ if (first_pilot_only==0) {
+ //antenna 0 symbol 3 slot 0
+ lte_dl_cell_spec(phy_vars_eNB,
+ &txdataF[0][slot_offset+(second_pilot*samples_per_symbol)],
+ amp,
+ slot,
+ 1,
+ 0);
+ }
+
+ if (frame_parms->nb_antennas_tx > 1) {
+ if (frame_parms->mode1_flag) {
+ // antenna 1 symbol 0 slot 0
+ lte_dl_cell_spec(phy_vars_eNB,
+ &txdataF[1][slot_offset],
+ amp,
+ slot,
+ 0,
+ 0);
+
+ if (first_pilot_only==0) {
+ // antenna 1 symbol 3 slot 0
+ lte_dl_cell_spec(phy_vars_eNB,
+ &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)],
+ amp,
+ slot,
+ 1,
+ 0);
+ }
+ } else {
+
+ // antenna 1 symbol 0 slot 0
+ lte_dl_cell_spec(phy_vars_eNB,
+ &txdataF[1][slot_offset],
+ amp,
+ slot,
+ 0,
+ 1);
+
+ if (first_pilot_only == 0) {
+ // antenna 1 symbol 3 slot 0
+ lte_dl_cell_spec(phy_vars_eNB,
+ &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)],
+ amp,
+ slot,
+ 1,
+ 1);
+ }
+ }
+ }
+
+ return(0);
+}*/
+
diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c
index c4088a8a5b..1a2838e5cf 100644
--- a/openair1/PHY/LTE_TRANSPORT/pmch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pmch.c
@@ -305,7 +305,7 @@ void generate_mch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t *a)
eNB->frame_parms.N_RB_DL,
eNB->dlsch_MCH->harq_processes[0]->rb_alloc,
get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs),1,
- 2,proc->frame_tx,subframe);
+ 2,proc->frame_tx,subframe,0);
generate_mbsfn_pilot(eNB,proc,
eNB->common_vars.txdataF[0],
diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c
index d9f5434cf5..33780a7def 100644
--- a/openair1/PHY/LTE_TRANSPORT/prach.c
+++ b/openair1/PHY/LTE_TRANSPORT/prach.c
@@ -629,6 +629,13 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1
#if defined(EXMIMO) || defined(OAI_USRP)
prach_start = (ue->rx_offset+subframe*ue->frame_parms.samples_per_tti-ue->hw_timing_advance-ue->N_TA_offset);
+#ifdef PRACH_DEBUG
+ LOG_I(PHY,"[UE %d] prach_start %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", ue->Mod_id,
+ prach_start,
+ ue->rx_offset,
+ ue->hw_timing_advance,
+ ue->N_TA_offset);
+#endif
if (prach_start<0)
prach_start+=(ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME);
diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h
index 86bc3723af..94aa21c717 100644
--- a/openair1/PHY/LTE_TRANSPORT/proto.h
+++ b/openair1/PHY/LTE_TRANSPORT/proto.h
@@ -48,7 +48,7 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch);
void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
-/** \fn new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag)
+/** \fn new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag, LTE_DL_FRAME_PARMS* frame_parms)
\brief This function allocates structures for a particular DLSCH at eNB
@returns Pointer to DLSCH to be removed
@param Kmimo Kmimo factor from 36-212/36-213
@@ -56,8 +56,9 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
@param Nsoft Soft-LLR buffer size from UE-Category
@params N_RB_DL total number of resource blocks (determine the operating BW)
@param abstraction_flag Flag to indicate abstracted interface
+ @param frame_parms Pointer to frame descriptor structure
*/
-LTE_eNB_DLSCH_t *new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t N_RB_DL, uint8_t abstraction_flag);
+LTE_eNB_DLSCH_t *new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t N_RB_DL, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS* frame_parms);
/** \fn free_ue_dlsch(LTE_UE_DLSCH_t *dlsch)
\brief This function frees memory allocated for a particular DLSCH at UE
@@ -191,11 +192,50 @@ void dlsch_encoding_emul(PHY_VARS_eNB *phy_vars_eNB,
\param re_allocated pointer to allocation counter
\param skip_dc offset for positive RBs
\param skip_half indicate that first or second half of RB must be skipped for PBCH/PSS/SSS
+ \param ue_spec_rs UE specific RS indicator
+ \param nb_antennas_tx_phy Physical antenna elements which can be different with antenna port number, especially in beamforming case
\param use2ndpilots Set to use the pilots from antenna port 1 for PDSCH
\param frame_parms Frame parameter descriptor
*/
-int32_t allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
+// Functions below implement 36-211
+
+/** \fn allocate_REs_in_RB(int32_t **txdataF,
+ uint32_t *jj,
+ uint32_t *jj2,
+ uint16_t re_offset,
+ uint32_t symbol_offset,
+ LTE_DL_eNB_HARQ_t *dlsch0_harq,
+ LTE_DL_eNB_HARQ_t *dlsch1_harq,
+ uint8_t pilots,
+ int16_t amp,
+ int16_t *qam_table_s,
+ uint32_t *re_allocated,
+ uint8_t skip_dc,
+ uint8_t skip_half,
+ uint8_t use2ndpilots,
+ LTE_DL_FRAME_PARMS *frame_parms);
+
+ \brief Fills RB with data
+ \param txdataF pointer to output data (frequency domain signal)
+ \param jj index to output (from CW 1)
+ \param jj index to output (from CW 2)
+ \param re_offset index of the first RE of the RB
+ \param symbol_offset index to the OFDM symbol
+ \param dlsch0_harq Pointer to Transport block 0 HARQ structure
+ \param dlsch0_harq Pointer to Transport block 1 HARQ structure
+ \param pilots =1 if symbol_offset is an OFDM symbol that contains pilots, 0 otherwise
+ \param amp Amplitude for symbols
+ \param qam_table_s0 pointer to scaled QAM table for Transport Block 0 (by rho_a or rho_b)
+ \param qam_table_s1 pointer to scaled QAM table for Transport Block 1 (by rho_a or rho_b)
+ \param re_allocated pointer to allocation counter
+ \param skip_dc offset for positive RBs
+ \param skip_half indicate that first or second half of RB must be skipped for PBCH/PSS/SSS
+ \param use2ndpilots Set to use the pilots from antenna port 1 for PDSCH
+ \param frame_parms Frame parameter descriptor
+*/
+
+int32_t allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB,
int32_t **txdataF,
uint32_t *jj,
uint32_t *jj2,
@@ -211,6 +251,9 @@ int32_t allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
uint32_t *re_allocated,
uint8_t skip_dc,
uint8_t skip_half,
+ uint8_t lprime,
+ uint8_t mprime,
+ uint8_t Ns,
int *P1_SHIFT,
int *P2_SHIFT);
@@ -230,12 +273,11 @@ int32_t allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
@param num_pdcch_symbols Number of PDCCH symbols in this subframe
@param dlsch0 Pointer to Transport Block 0 DLSCH descriptor for this allocation
@param dlsch1 Pointer to Transport Block 0 DLSCH descriptor for this allocation
-
*/
-int32_t dlsch_modulation(int32_t **txdataF,
+int32_t dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
+ int32_t **txdataF,
int16_t amp,
uint32_t sub_frame_offset,
- LTE_DL_FRAME_PARMS *frame_parms,
uint8_t num_pdcch_symbols,
LTE_eNB_DLSCH_t *dlsch0,
LTE_eNB_DLSCH_t *dlsch1);
@@ -329,6 +371,13 @@ int32_t generate_mbsfn_pilot(PHY_VARS_eNB *phy_vars_eNB,
int32_t **txdataF,
int16_t amp);
+void generate_ue_spec_pilots(PHY_VARS_eNB *phy_vars_eNB,
+ uint8_t UE_id,
+ int32_t **txdataF,
+ int16_t amp,
+ uint16_t Ntti,
+ uint8_t beamforming_mode);
+
int32_t generate_pss(int32_t **txdataF,
int16_t amp,
LTE_DL_FRAME_PARMS *frame_parms,
@@ -714,6 +763,7 @@ int dlsch_64qam_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
@param nb_rb number of RBs for this allocation
@param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
@param llr128p pointer to pointer to symbol in dlsch_llr
+ @param beamforming_mode beamforming mode
*/
int32_t dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **rxdataF_comp,
@@ -722,7 +772,8 @@ int32_t dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t first_symbol_flag,
uint16_t nb_rb,
uint16_t pbch_pss_sss_adj,
- int16_t **llr128p);
+ int16_t **llr128p,
+ uint8_t beamforming_mode);
/**
\brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms
@@ -735,6 +786,7 @@ int32_t dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
@param nb_rb number of RBs for this allocation
@param pbch_pss_sss_adjust Adjustment factor in RE for PBCH/PSS/SSS allocations
@param llr128p pointer to pointer to symbol in dlsch_llr
+ @param beamforming_mode beamforming mode
*/
void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
@@ -745,7 +797,8 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t first_symbol_flag,
uint16_t nb_rb,
uint16_t pbch_pss_sss_adjust,
- int16_t **llr128p);
+ int16_t **llr128p,
+ uint8_t beamforming_mode);
/**
\brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms
@@ -758,6 +811,7 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
@param first_symbol_flag
@param nb_rb number of RBs for this allocation
@param pbch_pss_sss_adjust PBCH/PSS/SSS RE adjustment (in REs)
+ @param beamforming_mode beamforming mode
*/
void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **rxdataF_comp,
@@ -768,7 +822,8 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t first_symbol_flag,
uint16_t nb_rb,
uint16_t pbch_pss_sss_adjust,
- short **llr_save);
+ int16_t **llr_save,
+ uint8_t beamforming_mode);
/** \fn dlsch_siso(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **rxdataF_comp,
@@ -939,6 +994,37 @@ uint16_t dlsch_extract_rbs_dual(int32_t **rxdataF,
uint32_t high_speed_flag,
LTE_DL_FRAME_PARMS *frame_parms);
+/** \fn dlsch_extract_rbs_TM7(int32_t **rxdataF,
+ int32_t **dl_bf_ch_estimates,
+ int32_t **rxdataF_ext,
+ int32_t **dl_bf_ch_estimates_ext,
+ uint32_t *rb_alloc,
+ uint8_t symbol,
+ uint8_t subframe,
+ uint32_t high_speed_flag,
+ LTE_DL_FRAME_PARMS *frame_parms)
+ \brief This function extracts the received resource blocks, both channel estimates and data symbols,
+ for the current allocation and for single antenna eNB transmission.
+ @param rxdataF Raw FFT output of received signal
+ @param dl_bf_ch_estimates Beamforming channel estimates of current slot
+ @param rxdataF_ext FFT output for RBs in this allocation
+ @param dl_bf_ch_estimates_ext Beamforming channel estimates for RBs in this allocation
+ @param rb_alloc RB allocation vector
+ @param symbol Symbol to extract
+ @param subframe Subframe number
+ @param high_speed_flag
+ @param frame_parms Pointer to frame descriptor
+*/
+uint16_t dlsch_extract_rbs_TM7(int32_t **rxdataF,
+ int32_t **dl_bf_ch_estimates,
+ int32_t **rxdataF_ext,
+ int32_t **dl_bf_ch_estimates_ext,
+ uint32_t *rb_alloc,
+ uint8_t symbol,
+ uint8_t subframe,
+ uint32_t high_speed_flag,
+ LTE_DL_FRAME_PARMS *frame_parms);
+
/** \brief This function performs channel compensation (matched filtering) on the received RBs for this allocation. In addition, it computes the squared-magnitude of the channel with weightings for 16QAM/64QAM detection as well as dual-stream detection (cross-correlation)
@param rxdataF_ext Frequency-domain received signal in RBs to be demodulated
@param dl_ch_estimates_ext Frequency-domain channel estimates in RBs to be demodulated
@@ -1029,6 +1115,12 @@ void dlsch_channel_level_TM56(int32_t **dl_ch_estimates_ext,
uint8_t symbol_mod,
uint16_t nb_rb);
+void dlsch_channel_level_TM7(int32_t **dl_bf_ch_estimates_ext,
+ LTE_DL_FRAME_PARMS *frame_parms,
+ int32_t *avg,
+ uint8_t pilots_flag,
+ uint16_t nb_rb);
+
void dlsch_scale_channel(int32_t **dl_ch_estimates_ext,
LTE_DL_FRAME_PARMS *frame_parms,
LTE_UE_DLSCH_t **dlsch_ue,
@@ -1293,7 +1385,7 @@ uint8_t get_transmission_mode(module_id_t Mod_id, uint8_t CC_id, rnti_t rnti);
*/
uint32_t conv_nprb(uint8_t ra_header,uint32_t rb_alloc,int N_RB_DL);
-int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe);
+int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe, uint8_t beamforming_mode);
int adjust_G(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe);
int adjust_G2(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe,uint8_t symbol);
@@ -1406,7 +1498,8 @@ int generate_ue_dlsch_params_from_dci(int frame,
PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated,
uint16_t si_rnti,
uint16_t ra_rnti,
- uint16_t p_rnti);
+ uint16_t p_rnti,
+ uint8_t beamforming_mode);
int32_t generate_eNB_dlsch_params_from_dci(int frame,
uint8_t subframe,
@@ -1419,7 +1512,8 @@ int32_t generate_eNB_dlsch_params_from_dci(int frame,
uint16_t si_rnti,
uint16_t ra_rnti,
uint16_t p_rnti,
- uint16_t DL_pmi_single);
+ uint16_t DL_pmi_single,
+ uint8_t beamforming_mode);
int32_t generate_eNB_ulsch_params_from_rar(uint8_t *rar_pdu,
frame_t frame,
@@ -1445,6 +1539,9 @@ int32_t generate_ue_ulsch_params_from_rar(PHY_VARS_UE *phy_vars_ue,
uint8_t eNB_id);
double sinr_eff_cqi_calc(PHY_VARS_UE *phy_vars_ue,
uint8_t eNB_id);
+
+uint8_t sinr2cqi(double sinr,uint8_t trans_mode);
+
int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *PHY_vars_eNB,
eNB_rxtx_proc_t *proc,
void *dci_pdu,
@@ -1633,7 +1730,7 @@ uint8_t phich_subframe2_pusch_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t s
@param subframe Subframe of received/transmitted PHICH
@returns frame of PUSCH transmission
*/
-uint8_t phich_frame2_pusch_frame(LTE_DL_FRAME_PARMS *frame_parms,frame_t frame,uint8_t subframe);;
+uint8_t phich_frame2_pusch_frame(LTE_DL_FRAME_PARMS *frame_parms,frame_t frame,uint8_t subframe);
void print_CQI(void *o,UCI_format_t uci_format,uint8_t eNB_id,int N_RB_DL);
@@ -1712,6 +1809,20 @@ void generate_pucch1x(int32_t **txdataF,
int16_t amp,
uint8_t subframe);
+void generate_pucch2x(int32_t **txdataF,
+ LTE_DL_FRAME_PARMS *fp,
+ uint8_t ncs_cell[20][7],
+ PUCCH_FMT_t fmt,
+ PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
+ uint16_t n2_pucch,
+ uint16_t *payload,
+ int A,
+ int B2,
+ int16_t amp,
+ uint8_t subframe,
+ uint16_t rnti);
+
+
void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue,
UE_rxtx_proc_t *proc,
PUCCH_FMT_t format,
@@ -1821,6 +1932,8 @@ int is_pmch_subframe(frame_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parm
uint8_t is_not_pilot(uint8_t pilots, uint8_t re, uint8_t nushift, uint8_t use2ndpilots);
+uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, uint8_t beamforming_mode);
+
uint32_t dlsch_decoding_abstraction(double *dlsch_MIPB,
LTE_DL_FRAME_PARMS *lte_frame_parms,
LTE_UE_DLSCH_t *dlsch,
diff --git a/openair1/PHY/LTE_TRANSPORT/pss.c b/openair1/PHY/LTE_TRANSPORT/pss.c
index f74675157b..44c7bffd9a 100644
--- a/openair1/PHY/LTE_TRANSPORT/pss.c
+++ b/openair1/PHY/LTE_TRANSPORT/pss.c
@@ -72,12 +72,12 @@ int generate_pss(int32_t **txdataF,
return(-1);
}
- a = (frame_parms->nb_antennas_tx == 1) ? amp: (amp*ONE_OVER_SQRT2_Q15)>>15;
+ a = (frame_parms->nb_antenna_ports_eNB == 1) ? amp: (amp*ONE_OVER_SQRT2_Q15)>>15;
//printf("[PSS] amp=%d, a=%d\n",amp,a);
Nsymb = (frame_parms->Ncp==NORMAL)?14:12;
- for (aa=0; aanb_antennas_tx; aa++) {
+ for (aa=0; aanb_antenna_ports_eNB; aa++) {
// aa = 0;
// The PSS occupies the inner 6 RBs, which start at
diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c
index c0c54b9782..34e64dfd5f 100644
--- a/openair1/PHY/LTE_TRANSPORT/pucch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pucch.c
@@ -442,7 +442,7 @@ inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti
int i;
uint8_t c;
- x2 = (rnti<<14) + ((1+subframe)<<16)*(1+(fp->Nid_cell<<1)); //this is c_init in 36.211 Sec 6.3.1
+ x2 = (rnti) + ((uint32_t)(1+subframe)<<16)*(1+(fp->Nid_cell<<1)); //this is c_init in 36.211 Sec 6.3.1
s = lte_gold_generic(&x1, &x2, 1);
for (i=0;i<19;i++) {
c = (uint8_t)((s>>i)&1);
@@ -456,22 +456,24 @@ inline void pucch2x_modulation(uint8_t *btilde,int16_t *d,int16_t amp) {
int i;
for (i=0;i<20;i++)
- d[i] = btilde[i] == 1 ? amp : -amp;
+ d[i] = btilde[i] == 1 ? -amp : amp;
}
+
+
uint32_t pucch_code[13] = {0xFFFFF,0x5A933,0x10E5A,0x6339C,0x73CE0,
0xFFC00,0xD8E64,0x4F6B0,0x218EC,0x1B746,
0x0FFFF,0x33FFF,0x3FFFC};
+
void generate_pucch2x(int32_t **txdataF,
LTE_DL_FRAME_PARMS *fp,
uint8_t ncs_cell[20][7],
PUCCH_FMT_t fmt,
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
uint16_t n2_pucch,
- uint8_t shortened_format,
- uint32_t *payload,
+ uint16_t *payload,
int A,
int B2,
int16_t amp,
@@ -486,13 +488,14 @@ void generate_pucch2x(int32_t **txdataF,
uint8_t NRB2 = fp->pucch_config_common.nRB_CQI;
uint8_t Ncs1 = fp->pucch_config_common.nCS_AN;
- uint32_t u0 = (fp->Nid_cell + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30;
- uint32_t u1 = (fp->Nid_cell + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30;
- uint32_t v0=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
- uint32_t v1=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
+ uint32_t u0 = fp->pucch_config_common.grouphop[subframe<<1];
+ uint32_t u1 = fp->pucch_config_common.grouphop[1+(subframe<<1)];
+ uint32_t v0 = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
+ uint32_t v1 = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
+
uint32_t z[12*14],*zptr;
uint32_t u,v,n;
- uint8_t ns,N_UL_symb,nsymb;
+ uint8_t ns,N_UL_symb,nsymb_slot0,nsymb_pertti;
uint32_t nprime,l,n_cs;
int alpha_ind,data_ind;
int16_t ref_re,ref_im;
@@ -509,7 +512,6 @@ void generate_pucch2x(int32_t **txdataF,
return;
}
-
// pucch2x_encoding
for (i=0;i 0)
@@ -545,66 +547,72 @@ void generate_pucch2x(int32_t **txdataF,
}
}
- zptr = z;
#ifdef DEBUG_PUCCH_TX
printf("[PHY] PUCCH2x: n2_pucch %d\n",n2_pucch);
#endif
N_UL_symb = (fp->Ncp==0) ? 7 : 6;
-
+ data_ind = 0;
+ zptr = z;
for (ns=(subframe<<1),u=u0,v=v0; ns<(2+(subframe<<1)); ns++,u=u1,v=v1) {
if ((ns&1) == 0)
- nprime = (n2_pucch < 12*NRB2) ?
- n2_pucch % 12 :
- (n2_pucch+Ncs1 + 1)%12;
- else
- nprime = (n2_pucch < 12*NRB2) ?
- ((12*(nprime+1)) % 13)-1 :
- (10-n2_pucch)%12;
-
+ nprime = (n2_pucch < 12*NRB2) ?
+ n2_pucch % 12 :
+ (n2_pucch+Ncs1 + 1)%12;
+ else {
+ nprime = (n2_pucch < 12*NRB2) ?
+ ((12*(nprime+1)) % 13)-1 :
+ (10-n2_pucch)%12;
+ }
//loop over symbols in slot
for (l=0; l>15);
+ ref_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15);
- // this is r_uv^alpha(n)
- ref_re = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][n<<1] - (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)])>>15);
- ref_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15);
-
- if ((l<2)||(l>=(N_UL_symb-2))) { //these are PUCCH data symbols
- ((int16_t *)&zptr[n])[0] = ((int32_t)d[data_ind]*ref_re - (int32_t)d[data_ind+1]*ref_im)>>15;
- ((int16_t *)&zptr[n])[1] = ((int32_t)d[data_ind]*ref_im + (int32_t)d[data_ind+1]*ref_re)>>15;
- }
- else {
- ((int16_t *)&zptr[n])[0] = ref_re;
- ((int16_t *)&zptr[n])[1] = ref_im;
- }
-
+ if ((l!=1)&&(l!=5)) { //these are PUCCH data symbols
+ ((int16_t *)&zptr[n])[0] = ((int32_t)d[data_ind]*ref_re - (int32_t)d[data_ind+1]*ref_im)>>15;
+ ((int16_t *)&zptr[n])[1] = ((int32_t)d[data_ind]*ref_im + (int32_t)d[data_ind+1]*ref_re)>>15;
+ //LOG_I(PHY,"slot %d ofdm# %d ==> d[%d,%d] \n",ns,l,data_ind,n);
+ }
+ else {
+ ((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_re>>15);
+ ((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_im>>15);
+ //LOG_I(PHY,"slot %d ofdm# %d ==> dmrs[%d] \n",ns,l,n);
+ }
+ alpha_ind = (alpha_ind + n_cs)%12;
} // n
- if ((l<2)||(l>=(N_UL_symb-2))) //these are PUCCH data symbols so increment data index
- data_ind+=2;
+ zptr+=12;
+
+ if ((l!=1)&&(l!=5)) //these are PUCCH data symbols so increment data index
+ data_ind+=2;
} // l
} //ns
m = n2_pucch/12;
#ifdef DEBUG_PUCCH_TX
- printf("[PHY] PUCCH: m %d\n",m);
+ LOG_D(PHY,"[PHY] PUCCH: n2_pucch %d m %d\n",n2_pucch,m);
#endif
- nsymb = N_UL_symb<<1;
+
+ nsymb_slot0 = ((fp->Ncp==0) ? 7 : 6);
+ nsymb_pertti = nsymb_slot0 << 1;
+
+ //nsymb = nsymb_slot0<<1;
//for (j=0,l=0;l<(nsymb-1);l++) {
- for (j=0,l=0; l<(nsymb); l++) {
- if ((l<(nsymb>>1)) && ((m&1) == 0))
+ for (j=0,l=0; l<(nsymb_pertti); l++) {
+
+ if ((lfirst_carrier_offset;
- else if ((l<(nsymb>>1)) && ((m&1) == 1))
+ else if ((lfirst_carrier_offset + (fp->N_RB_DL - (m>>1) - 1)*12;
else if ((m&1) == 0)
re_offset = fp->first_carrier_offset + (fp->N_RB_DL - (m>>1) - 1)*12;
@@ -614,23 +622,33 @@ void generate_pucch2x(int32_t **txdataF,
if (re_offset > fp->ofdm_symbol_size)
re_offset -= (fp->ofdm_symbol_size);
- symbol_offset = (unsigned int)fp->ofdm_symbol_size*(l+(subframe*nsymb));
+
+
+ symbol_offset = (unsigned int)fp->ofdm_symbol_size*(l+(subframe*nsymb_pertti));
txptr = &txdataF[0][symbol_offset];
+ //LOG_I(PHY,"ofdmSymb %d/%d, firstCarrierOffset %d, symbolOffset[sfn %d] %d, reOffset %d, &txptr: %x \n", l, nsymb, fp->first_carrier_offset, subframe, symbol_offset, re_offset, &txptr[0]);
+
for (i=0; i<12; i++,j++) {
- txptr[re_offset++] = z[j];
+ txptr[re_offset] = z[j];
+
+ re_offset++;
if (re_offset==fp->ofdm_symbol_size)
- re_offset = 0;
+ re_offset -= (fp->ofdm_symbol_size);
#ifdef DEBUG_PUCCH_TX
- printf("[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]);
+ LOG_D(PHY,"[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]);
#endif
}
}
}
+//#define Amax 13
+//void init_pucch2x_rx() {};
+
+
uint32_t rx_pucch(PHY_VARS_eNB *eNB,
PUCCH_FMT_t fmt,
uint8_t UE_id,
diff --git a/openair1/PHY/LTE_TRANSPORT/rar_tools.c b/openair1/PHY/LTE_TRANSPORT/rar_tools.c
index f86c009543..60fa52df16 100644
--- a/openair1/PHY/LTE_TRANSPORT/rar_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/rar_tools.c
@@ -34,6 +34,7 @@
#include "SCHED/extern.h"
#include "LAYER2/MAC/defs.h"
#include "SCHED/defs.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
#include "assertions.h"
@@ -171,6 +172,8 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue,
unsigned char eNB_id )
{
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_RAR,VCD_FUNCTION_IN);
+
// RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)rar_pdu;
uint8_t transmission_mode = ue->transmission_mode[eNB_id];
unsigned char *rar_pdu = ue->dlsch_ra[eNB_id]->harq_processes[0]->b;
@@ -315,6 +318,9 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue,
msg("ulsch ra (UE): TPC %d\n",ulsch->harq_processes[harq_pid]->TPC);
msg("ulsch ra (UE): O %d\n",ulsch->O);
msg("ulsch ra (UE): ORI %d\n",ulsch->O_RI);
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_RAR,VCD_FUNCTION_OUT);
+
//#endif
return(0);
}
diff --git a/openair1/PHY/LTE_TRANSPORT/srs_modulation.c b/openair1/PHY/LTE_TRANSPORT/srs_modulation.c
index a78536246f..7e29d998a1 100644
--- a/openair1/PHY/LTE_TRANSPORT/srs_modulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/srs_modulation.c
@@ -129,18 +129,27 @@ int32_t generate_srs_tx(PHY_VARS_UE *ue,
LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id];
- int32_t *txdataF = ue->common_vars.txdataF[0];
+ int32_t **txdataF = ue->common_vars.txdataF;
uint16_t msrsb=0,Nb=0,nb,b,msrs0=0,k,Msc_RS,Msc_RS_idx,carrier_pos,symbol_offset;
uint16_t *Msc_idx_ptr;
int32_t k0;
- uint32_t T_SFC;
- uint32_t subframe_offset;
+ //uint32_t subframe_offset;
uint8_t Bsrs = soundingrs_ul_config_dedicated->srs_Bandwidth;
uint8_t Csrs = frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig;
uint8_t Ssrs = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig;
uint8_t n_RRC = soundingrs_ul_config_dedicated->freqDomainPosition;
uint8_t kTC = soundingrs_ul_config_dedicated->transmissionComb;
+ // u is the PUCCH sequence-group number defined in Section 5.5.1.3
+ // ν is the base sequence number defined in Section 5.5.1.4
+ uint32_t u=frame_parms->pucch_config_common.grouphop[1+(subframe<<1)];;
+ uint32_t v=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
+
+ LOG_D(PHY,"SRS root sequence: u %d, v %d\n",u,v);
+ LOG_D(PHY,"CommonSrsConfig: Csrs %d, Ssrs %d, AnSrsSimultan %d \n",Csrs,Ssrs,frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission);
+ LOG_D(PHY,"DedicatedSrsConfig: Bsrs %d, bhop %d, nRRC %d, Isrs %d, kTC %d, n_SRS %d\n",Bsrs,soundingrs_ul_config_dedicated->srs_HoppingBandwidth,n_RRC
+ ,soundingrs_ul_config_dedicated->srs_ConfigIndex,kTC
+ ,soundingrs_ul_config_dedicated->cyclicShift);
if (frame_parms->N_RB_UL < 41) {
msrs0 = msrsb_6_40[Csrs][0];
@@ -161,7 +170,7 @@ int32_t generate_srs_tx(PHY_VARS_UE *ue,
}
Msc_RS = msrsb * 6;
- k0 = (((frame_parms->N_RB_UL>>1)-(msrs0>>1))*12) + kTC;
+ k0 = ( ( (int16_t)(frame_parms->N_RB_UL>>1) - (int16_t)(msrs0>>1) ) * 12 ) + kTC;
nb = (4*n_RRC/msrsb)%Nb;
for (b=0; b<=Bsrs; b++) {
@@ -200,53 +209,32 @@ int32_t generate_srs_tx(PHY_VARS_UE *ue,
msg("generate_srs_tx: Msc_RS = %d, Msc_RS_idx = %d\n",Msc_RS, Msc_RS_idx);
#endif
- T_SFC = (Ssrs<=7 ? 5 : 10);
+ carrier_pos = (frame_parms->first_carrier_offset + k0);
+ if (carrier_pos>frame_parms->ofdm_symbol_size) {
+ carrier_pos -= frame_parms->ofdm_symbol_size;
+ }
+ uint16_t nsymb = (frame_parms->Ncp==0) ? 14:12;
+ symbol_offset = (int)frame_parms->ofdm_symbol_size*((subframe*nsymb)+(nsymb-1));
- if ((1<<(subframe%T_SFC))&transmission_offset_tdd[Ssrs]) {
-
-#ifndef IFFT_FPGA_UE
- carrier_pos = (frame_parms->first_carrier_offset + k0) % frame_parms->ofdm_symbol_size;
//msg("carrier_pos = %d\n",carrier_pos);
+ //subframe_offset = subframe*frame_parms->symbols_per_tti*frame_parms->ofdm_symbol_size;
+ //symbol_offset = subframe_offset+(frame_parms->symbols_per_tti-1)*frame_parms->ofdm_symbol_size;
- subframe_offset = subframe*frame_parms->symbols_per_tti*frame_parms->ofdm_symbol_size;
- symbol_offset = subframe_offset+(frame_parms->symbols_per_tti-1)*frame_parms->ofdm_symbol_size;
+ int32_t *txptr;
+ txptr = &txdataF[0][symbol_offset];
for (k=0; k>15);
- ((short*) txdataF)[2*(symbol_offset + carrier_pos)+1] = (short) (((int32_t) amp * (int32_t) ul_ref_sigs[0][0][Msc_RS_idx][(k<<1)+1])>>15);
- carrier_pos+=2;
+ int32_t real = ((int32_t) amp * (int32_t) ul_ref_sigs[u][v][Msc_RS_idx][k<<1]) >> 15;
+ int32_t imag = ((int32_t) amp * (int32_t) ul_ref_sigs[u][v][Msc_RS_idx][(k<<1)+1]) >> 15;
+ txptr[carrier_pos] = (real&0xFFFF) + ((imag<<16)&0xFFFF0000);
+
+
+ carrier_pos = carrier_pos+2;
if (carrier_pos >= frame_parms->ofdm_symbol_size)
- carrier_pos=1;
+ carrier_pos=carrier_pos-frame_parms->ofdm_symbol_size;
}
-#else
- carrier_pos = (frame_parms->N_RB_UL*12/2 + k0) % (frame_parms->N_RB_UL*12);
- //msg("carrier_pos = %d\n",carrier_pos);
-
- subframe_offset = subframe*frame_parms->symbols_per_tti*frame_parms->N_RB_UL*12;
- symbol_offset = subframe_offset+(frame_parms->symbols_per_tti-1)*frame_parms->N_RB_UL*12;
-
- for (k=0; k= 0) && (ul_ref_sigs[0][0][Msc_RS_idx][(k<<1)+1] >= 0))
- txdataF[symbol_offset+carrier_pos] = (int32_t) 4;
- else if ((ul_ref_sigs[0][0][Msc_RS_idx][k<<1] >= 0) && (ul_ref_sigs[0][0][Msc_RS_idx][(k<<1)+1] < 0))
- txdataF[symbol_offset+carrier_pos] = (int32_t) 2;
- else if ((ul_ref_sigs[0][0][Msc_RS_idx][k<<1] < 0) && (ul_ref_sigs[0][0][Msc_RS_idx][(k<<1)+1] >= 0))
- txdataF[symbol_offset+carrier_pos] = (int32_t) 3;
- else if ((ul_ref_sigs[0][0][Msc_RS_idx][k<<1] < 0) && (ul_ref_sigs[0][0][Msc_RS_idx][(k<<1)+1] < 0))
- txdataF[symbol_offset+carrier_pos] = (int32_t) 1;
-
- carrier_pos+=2;
-
- if (carrier_pos >= frame_parms->N_RB_UL*12)
- carrier_pos=0;
- }
-
-#endif
- // write_output("srs_txF.m","srstxF",&txdataF[symbol_offset],512,1,1);
- }
-
return(0);
}
diff --git a/openair1/PHY/LTE_TRANSPORT/sss.c b/openair1/PHY/LTE_TRANSPORT/sss.c
index 39112725b1..320d7ac75a 100644
--- a/openair1/PHY/LTE_TRANSPORT/sss.c
+++ b/openair1/PHY/LTE_TRANSPORT/sss.c
@@ -59,10 +59,10 @@ int generate_sss(int32_t **txdataF,
Nsymb = (frame_parms->Ncp==NORMAL)?14:12;
k = frame_parms->ofdm_symbol_size-3*12+5;
- a = (frame_parms->nb_antennas_tx == 1) ? amp : (amp*ONE_OVER_SQRT2_Q15)>>15;
+ a = (frame_parms->nb_antenna_ports_eNB == 1) ? amp : (amp*ONE_OVER_SQRT2_Q15)>>15;
for (i=0; i<62; i++) {
- for (aa=0; aanb_antennas_tx; aa++) {
+ for (aa=0; aanb_antenna_ports_eNB; aa++) {
((int16_t*)txdataF[aa])[2*(slot_offset*Nsymb/2*frame_parms->ofdm_symbol_size +
symbol*frame_parms->ofdm_symbol_size + k)] =
diff --git a/openair1/PHY/LTE_TRANSPORT/uci_tools.c b/openair1/PHY/LTE_TRANSPORT/uci_tools.c
index a8f9f6ba57..37c5dc1432 100644
--- a/openair1/PHY/LTE_TRANSPORT/uci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/uci_tools.c
@@ -836,3 +836,5 @@ void print_CQI(void *o,UCI_format_t uci_format,unsigned char eNB_id,int N_RB_DL)
}
+
+
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c
index 53eaa849fd..4559aaa326 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c
@@ -140,6 +140,8 @@ LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag)
if (ulsch) {
memset(ulsch,0,sizeof(LTE_UE_ULSCH_t));
+ ulsch->Mlimit = 4;
+
for (i=0; i<8; i++) {
ulsch->harq_processes[i] = (LTE_UL_UE_HARQ_t *)malloc16(sizeof(LTE_UL_UE_HARQ_t));
@@ -498,6 +500,21 @@ uint32_t ulsch_encoding(uint8_t *a,
G = G - Q_RI - Q_CQI;
+ ulsch->harq_processes[harq_pid]->G = G;
+
+/*
+ LOG_I(PHY,"ULSCH Encoding G %d, Q_RI %d (O_RI%d, Msc_initial %d, Nsymb_initial%d, beta_offset_ri_times8 %d), Q_CQI %d, Q_ACK %d \n",G,Q_RI,ulsch->O_RI,ulsch->harq_processes[harq_pid]->Msc_initial,ulsch->harq_processes[harq_pid]->Nsymb_initial,ulsch->beta_offset_ri_times8,Q_CQI,Q_ACK);
+
+ LOG_I(PHY,"ULSCH Encoding (Nid_cell %d, rnti %x): harq_pid %d round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d\n",
+ frame_parms->Nid_cell,ulsch->rnti,
+ harq_pid,
+ ulsch->harq_processes[harq_pid]->round,
+ ulsch->harq_processes[harq_pid]->rvidx,
+ ulsch->harq_processes[harq_pid]->mcs,
+ ulsch->O_RI,
+ ulsch->harq_processes[harq_pid]->O_ACK,
+ G);
+*/
if ((int)G < 0) {
LOG_E(PHY,"FATAL: ulsch_coding.c G < 0 (%d) : Q_RI %d, Q_CQI %d, O %d, betaCQI_times8 %d)\n",G,Q_RI,Q_CQI,ulsch->O,ulsch->beta_offset_cqi_times8);
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
index 0ce810a52c..68f3abc094 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
@@ -872,7 +872,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
int16_t ys,c;
uint32_t wACK_idx;
uint8_t dummy_w_cc[3*(MAX_CQI_BITS+8+32)];
- int16_t y[6*14*1200];
+ int16_t y[6*14*1200] __attribute__((aligned(32)));
uint8_t ytag[14*1200];
// uint8_t ytag2[6*14*1200],*ytag2_ptr;
int16_t cseq[6*14*1200];
@@ -1442,7 +1442,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
}
#if defined(__x86_64__)||defined(__i386__)
-#ifndef __AVX2
+#ifndef __AVX2__
for (iprime=0; iprimee[iprime]) = *((__m128i *)&y[j2]);
#else
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c
index 80168dd3c5..ee9bfc53cd 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c
@@ -426,13 +426,14 @@ void ulsch_modulation(int32_t **txdataF,
G = (int)ulsch->harq_processes[harq_pid]->nb_rb * (12 * Q_m) * (ulsch->Nsymb_pusch);
+
// Mapping
nsymb = (frame_parms->Ncp==0) ? 14:12;
Msc_PUSCH = ulsch->harq_processes[harq_pid]->nb_rb*12;
#ifdef DEBUG_ULSCH_MODULATION
- printf("ulsch_modulation.c: Doing modulation (rnti %x,x2 %x) for G=%d bits, harq_pid %d , nb_rb %d, Q_m %d, Nsymb_pusch %d (nsymb %d), subframe %d\n",
- ulsch->rnti,x2,G,harq_pid,ulsch->harq_processes[harq_pid]->nb_rb,Q_m, ulsch->Nsymb_pusch,nsymb,subframe);
+ LOG_D(PHY,"ulsch_modulation.c: Doing modulation (rnti %x,x2 %x) for G=%d bits, harq_pid %d , nb_rb %d, Q_m %d, Nsymb_pusch %d (nsymb %d), subframe %d\n",
+ ulsch->rnti,x2,G,harq_pid,ulsch->harq_processes[harq_pid]->nb_rb,Q_m, ulsch->Nsymb_pusch,nsymb,subframe);
#endif
// scrambling (Note the placeholding bits are handled in ulsch_coding.c directly!)
diff --git a/openair1/PHY/MODULATION/beamforming.c b/openair1/PHY/MODULATION/beamforming.c
new file mode 100644
index 0000000000..6557a47ee7
--- /dev/null
+++ b/openair1/PHY/MODULATION/beamforming.c
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@eurecom.fr
+
+Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+ *******************************************************************************/
+
+/*! \file PHY/MODULATION/beamforming.c
+ * \brief
+ * \author X. JIANG, F. Kaltenberger, R. KNOPP
+ * \date 2016
+ * \version 0.1
+ * \company Eurecom
+ * \email: xiwen.jiang@eurecom.fr,florian.kaltenberger@eurecom.fr,raymond.knopp@eurecom.fr
+ * \note
+ * \warning
+ */
+#include "PHY/defs.h"
+#include "PHY/extern.h"
+#include "PHY/CODING/defs.h"
+#include "PHY/CODING/extern.h"
+#include "PHY/CODING/lte_interleaver_inline.h"
+#include "PHY/LTE_TRANSPORT/defs.h"
+#include "defs.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+
+int beam_precoding(int32_t **txdataF,
+ int32_t **txdataF_BF,
+ LTE_DL_FRAME_PARMS *frame_parms,
+ int32_t ***beam_weights,
+ int slot,
+ int symbol,
+ int aa)
+{
+ uint8_t p;
+ uint16_t re=0;
+ int slot_offset_F;
+
+ slot_offset_F = slot*(frame_parms->ofdm_symbol_size)*((frame_parms->Ncp==1) ? 6 : 7);
+
+ // clear txdata_BF[aa][re] for each call of ue_spec_beamforming
+ memset(txdataF_BF[aa],0,sizeof(int32_t)*(frame_parms->ofdm_symbol_size));
+
+ for (p=0; p<14; p++) {
+ //if (p==0 || p==1 || p==5 || p>7)
+ // mult_cpx_conj_vector((int16_t*)txdataF[p], (int16_t*)beam_weights[p][aa], (int16_t*)txdataF_BF[aa], frame_parms->ofdm_symbol_size, 15);
+ for (re=0;reofdm_symbol_size;re++) {
+ if ((p==0 || p==1 || p==5 || p>=7) && txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re]!=0) {
+ ((int16_t*)&txdataF_BF[aa][re])[0] += (int16_t)((((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[0]*((int16_t*)&beam_weights[p][aa][re])[0])>>15);
+ ((int16_t*)&txdataF_BF[aa][re])[0] -= (int16_t)((((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[1]*((int16_t*)&beam_weights[p][aa][re])[1])>>15);
+ ((int16_t*)&txdataF_BF[aa][re])[1] += (int16_t)((((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[0]*((int16_t*)&beam_weights[p][aa][re])[1])>>15);
+ ((int16_t*)&txdataF_BF[aa][re])[1] += (int16_t)((((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[1]*((int16_t*)&beam_weights[p][aa][re])[0])>>15);
+
+ /*
+ printf("beamforming.c:txdataF[%d][%d]=%d+j%d, beam_weights[%d][%d][%d]=%d+j%d,txdata_BF[%d][%d]=%d+j%d\n",
+ p,slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re,
+ ((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[0],
+ ((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[1],
+ p,aa,re,
+ ((int16_t*)&beam_weights[p][aa][re])[0],((int16_t*)&beam_weights[p][aa][re])[1],
+ aa,re,
+ ((int16_t*)&txdataF_BF[aa][re])[0],
+ ((int16_t*)&txdataF_BF[aa][re])[1]);
+ */
+ }
+ }
+ }
+ return 0;
+}
diff --git a/openair1/PHY/MODULATION/compute_bf_weights.c b/openair1/PHY/MODULATION/compute_bf_weights.c
new file mode 100644
index 0000000000..32a91c11f5
--- /dev/null
+++ b/openair1/PHY/MODULATION/compute_bf_weights.c
@@ -0,0 +1,56 @@
+#include
+#include
+#include "PHY/impl_defs_lte.h"
+
+int f_read(char *calibF_fname, int nb_ant, int nb_freq, int32_t **tdd_calib_coeffs){
+
+ FILE *calibF_fd;
+ int i,j,l,calibF_e;
+
+ calibF_fd = fopen(calibF_fname,"r");
+
+ if (calibF_fd) {
+ printf("Loading Calibration matrix from %s\n", calibF_fname);
+
+ for(i=0;itxdataF[eNB_id];
+ int32_t **txdataF_BF = eNB_common_vars->txdataF_BF[eNB_id];
+ int32_t **txdata = eNB_common_vars->txdata[eNB_id];
+
+ slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1);
+
+ //printf("Thread %d starting ... aa %d (%llu)\n",omp_get_thread_num(),aa,rdtsc());
+ for (l=0; lsymbols_per_tti>>1; l++) {
+
+ for (aa=0; aanb_antennas_tx; aa++) {
+
+ //printf("do_OFDM_mod_l, slot=%d, l=%d, NUMBER_OF_OFDM_CARRIERS=%d,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES=%d\n",next_slot, l,NUMBER_OF_OFDM_CARRIERS,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_BEAM_PRECODING,1);
+ beam_precoding(txdataF,txdataF_BF,frame_parms,eNB_common_vars->beam_weights[eNB_id],next_slot,l,aa);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_BEAM_PRECODING,0);
+
+ //PMCH case not implemented...
+
+ if (frame_parms->Ncp == 1)
+ PHY_ofdm_mod(txdataF_BF[aa], // input
+ &txdata[aa][slot_offset+l*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES], // output
+ frame_parms->ofdm_symbol_size,
+ 1, // number of symbols
+ frame_parms->nb_prefix_samples, // number of prefix samples
+ CYCLIC_PREFIX);
+ else {
+ if (l==0) {
+ PHY_ofdm_mod(txdataF_BF[aa], // input
+ &txdata[aa][slot_offset], // output
+ frame_parms->ofdm_symbol_size,
+ 1, // number of symbols
+ frame_parms->nb_prefix_samples0, // number of prefix samples
+ CYCLIC_PREFIX);
+
+ } else {
+ PHY_ofdm_mod(txdataF_BF[aa], // input
+ &txdata[aa][slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES], // output
+ frame_parms->ofdm_symbol_size,
+ 1, // number of symbols
+ frame_parms->nb_prefix_samples, // number of prefix samples
+ CYCLIC_PREFIX);
+
+ /* printf("txdata[%d][%d]=%d\n",aa,slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES,txdata[aa][slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES]);
+ * */
+ }
+ }
+ }
+ }
+
+}
diff --git a/openair1/PHY/MODULATION/slot_fep.c b/openair1/PHY/MODULATION/slot_fep.c
index 0a592a1a19..94de0d3cbc 100644
--- a/openair1/PHY/MODULATION/slot_fep.c
+++ b/openair1/PHY/MODULATION/slot_fep.c
@@ -47,6 +47,11 @@ int slot_fep(PHY_VARS_UE *ue,
unsigned int frame_length_samples = frame_parms->samples_per_tti * 10;
unsigned int rx_offset;
+ /*LTE_UE_DLSCH_t **dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id];
+ unsigned char harq_pid = dlsch_ue[0]->current_harq_pid;
+ LTE_DL_UE_HARQ_t *dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid];
+ int uespec_pilot[9][1200];*/
+
void (*dft)(int16_t *,int16_t *, int);
int tmp_dft_in[2048] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs
@@ -175,7 +180,7 @@ int slot_fep(PHY_VARS_UE *ue,
if (ue->perfect_ce == 0) {
if ((l==0) || (l==(4-frame_parms->Ncp))) {
- for (aa=0; aanb_antennas_tx_eNB; aa++) {
+ for (aa=0; aanb_antenna_ports_eNB; aa++) {
#ifdef DEBUG_FEP
printf("Channel estimation eNB %d, aatx %d, slot %d, symbol %d\n",eNB_id,aa,Ns,l);
@@ -215,6 +220,7 @@ int slot_fep(PHY_VARS_UE *ue,
}
}
+
}
#ifdef DEBUG_FEP
diff --git a/openair1/PHY/Makefile.inc b/openair1/PHY/Makefile.inc
index 06f9447488..1586f353c0 100644
--- a/openair1/PHY/Makefile.inc
+++ b/openair1/PHY/Makefile.inc
@@ -1,6 +1,7 @@
PHY_OBJS = $(TOP_DIR)/PHY/LTE_TRANSPORT/pss.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/sss.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/pilots.o
+PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/pilots_ue_spec.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/pilots_mbsfn.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/dlsch_coding.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/dlsch_modulation.o
@@ -40,6 +41,7 @@ PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_sync_time.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_sync_timefreq.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_adjust_sync.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.o
+PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_est_freq_offset.o
@@ -47,7 +49,7 @@ PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_ue_measurements.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_eNB_measurements.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/adjust_gain.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_dl_cell_spec.o
-PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_dl_uespec.o
+PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_dl_ue_spec.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_gold.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_gold_mbsfn.o
PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_dl_mbsfn.o
diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c
index 1465da6544..768dedddf5 100644
--- a/openair1/PHY/TOOLS/lte_phy_scope.c
+++ b/openair1/PHY/TOOLS/lte_phy_scope.c
@@ -484,7 +484,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms;
int nsymb_ce = frame_parms->ofdm_symbol_size;//*frame_parms->symbols_per_tti;
uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
- uint8_t nb_antennas_tx = frame_parms->nb_antennas_tx_eNB;
+ uint8_t nb_antennas_tx = frame_parms->nb_antenna_ports_eNB;
int16_t **rxsig_t;
int16_t **chest_t;
int16_t **chest_f;
@@ -507,6 +507,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
int coded_bits_per_codeword = 0;
int mcs = 0;
unsigned char harq_pid = 0;
+ int beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0;
if (phy_vars_ue->dlsch[eNB_id][0]!=NULL) {
@@ -537,7 +538,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl,
num_pdcch_symbols,
frame,
- subframe);
+ subframe,
+ beamforming_mode);
} else {
coded_bits_per_codeword = 0; //frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti);
}
diff --git a/openair1/PHY/TOOLS/read_F.c b/openair1/PHY/TOOLS/read_F.c
new file mode 100644
index 0000000000..32ade0dfdb
--- /dev/null
+++ b/openair1/PHY/TOOLS/read_F.c
@@ -0,0 +1,24 @@
+#include
+#include
+
+int f_read(char *calibF_fname, int nb_antM, int nb_freq, int16_t (*calibF_mtx)[nb_freq*2]){
+
+ FILE *calibF_fd;
+ int i,j,l,calibF_e;
+
+ calibF_fd = fopen(calibF_fname,"r");
+
+ if (calibF_fd) {
+ printf("Loading Calibration matrix from %s\n", calibF_fname);
+
+ for(i=0;itdd_config_S);
// MIMO
- fprintf(f_ptr, "BB:EUTR:DL:MIMO:CONF TX%d\n",frame_parms->nb_antennas_tx_eNB);
+ fprintf(f_ptr, "BB:EUTR:DL:MIMO:CONF TX%d\n",frame_parms->nb_antenna_ports_eNB);
fprintf(f_ptr, "BB:EUTR:DL:MIMO:ANTA ANT1\n");
fprintf(f_ptr, "BB:EUTR:DL:MIMO:ANTB NONE\n");
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 66ff465708..182a57082f 100644
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -454,9 +454,6 @@ typedef struct PHY_VARS_eNB_s {
LTE_eNB_COMMON common_vars;
LTE_eNB_SRS srs_vars[NUMBER_OF_UE_MAX];
LTE_eNB_PBCH pbch;
- /// \brief ?.
- /// - first index: UE [0..NUMBER_OF_UE_MAX[ (hard coded)
- /// - second index: UE [0..NUMBER_OF_UE_MAX[
LTE_eNB_PUSCH *pusch_vars[NUMBER_OF_UE_MAX];
LTE_eNB_PRACH prach_vars;
LTE_eNB_DLSCH_t *dlsch[NUMBER_OF_UE_MAX][2]; // Nusers times two spatial streams
@@ -469,6 +466,9 @@ typedef struct PHY_VARS_eNB_s {
/// cell-specific reference symbols
uint32_t lte_gold_table[20][2][14];
+ /// UE-specific reference symbols (p=5), TM 7
+ uint32_t lte_gold_uespec_port5_table[NUMBER_OF_UE_MAX][20][38];
+
/// UE-specific reference symbols (p=7...14), TM 8/9/10
uint32_t lte_gold_uespec_table[2][20][2][21];
@@ -679,7 +679,7 @@ typedef struct {
/// \brief Total gains with bypassed RF gain stage (ExpressMIMO2/Lime)
uint32_t rx_gain_byp[4];
/// \brief Current transmit power
- int8_t tx_power_dBm[10];
+ int16_t tx_power_dBm[10];
/// \brief Total number of REs in current transmission
int tx_total_RE[10];
/// \brief Maximum transmit power
@@ -729,8 +729,11 @@ typedef struct {
/// cell-specific reference symbols
uint32_t lte_gold_table[7][20][2][14];
+ /// UE-specific reference symbols (p=5), TM 7
+ uint32_t lte_gold_uespec_port5_table[20][38];
+
/// ue-specific reference symbols
- uint32_t lte_gold_uespec_table[2][20][2][21];
+ uint32_t lte_gold_uespec_table[2][20][2][21];
/// mbsfn reference symbols
uint32_t lte_gold_mbsfn_table[10][3][42];
diff --git a/openair1/PHY/extern.h b/openair1/PHY/extern.h
index 09d4c74f52..0eb5dc6c97 100644
--- a/openair1/PHY/extern.h
+++ b/openair1/PHY/extern.h
@@ -117,5 +117,17 @@ extern char eNB_timing[2][20];
extern int16_t unscrambling_lut[65536*16];
extern uint8_t scrambling_lut[65536*16];
+extern unsigned short msrsb_6_40[8][4];
+extern unsigned short msrsb_41_60[8][4];
+extern unsigned short msrsb_61_80[8][4];
+extern unsigned short msrsb_81_110[8][4];
+extern unsigned short Nb_6_40[8][4];
+extern unsigned short Nb_41_60[8][4];
+extern unsigned short Nb_61_80[8][4];
+extern unsigned short Nb_81_110[8][4];
+
+extern uint16_t hundred_times_log10_NPRB[100];
+extern uint8_t alpha_lut[8];
+
#endif /*__PHY_EXTERN_H__ */
diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h
index f80effbebd..7a30bff6ab 100644
--- a/openair1/PHY/impl_defs_lte.h
+++ b/openair1/PHY/impl_defs_lte.h
@@ -142,6 +142,11 @@ typedef struct {
uint8_t nCS_AN;
/// Parameter: \f$N^{(1)}_\text{PUCCH}\f$ see TS 36.213 (10.1). \vr{[0..2047]}
uint16_t n1PUCCH_AN;
+
+ /// group hopping sequence for DRS \note not part of offical UL-PUCCH_CONFIG_COMMON ASN1 specification.
+ uint8_t grouphop[20];
+ /// sequence hopping sequence for DRS \note not part of offical UL-PUCCH_CONFIG_COMMON ASN1 specification.
+ uint8_t seqhop[20];
} PUCCH_CONFIG_COMMON;
/// UL-ReferenceSignalsPUSCH from 36.331 RRC spec
@@ -315,6 +320,12 @@ typedef struct {
uint16_t srs_ConfigIndex;
/// Parameter: \f$n^\text{CS}_\text{SRS}\f$. See TS 36.211 (5.5.3.1). \vr{[0..7]} \note the specification sais it is an enumerated value.
uint8_t cyclicShift;
+ // Parameter: ue srs subframe for internal implementation
+ uint8_t srsConfigDedicatedSetup;
+ // Parameter: cell srs subframe for internal implementation
+ uint8_t srsCellSubframe;
+ // Parameter: ue srs subframe for internal implementation
+ uint8_t srsUeSubframe;
} SOUNDINGRS_UL_CONFIG_DEDICATED;
/// UplinkPowerControlDedicated Information Element from 36.331 RRC spec
@@ -418,16 +429,20 @@ typedef struct {
/// CQI-ReportPeriodic
typedef struct {
- /// Parameter: \f$n^{(2)}_\text{PUCCH}\f$, see TS 36.213 (7.2). \vr{[0..1185]}
- uint16_t cqi_PUCCH_ResourceIndex;
+ /// Parameter: \f$n^{(2)}_\text{PUCCH}\f$, see TS 36.213 (7.2). \vr{[0..1185]}, -1 indicates inactivity
+ int16_t cqi_PUCCH_ResourceIndex;
/// Parameter: CQI/PMI Periodicity and Offset Configuration Index \f$I_\text{CQI/PMI}\f$, see TS 36.213 (tables 7.2.2-1A and 7.2.2-1C). \vr{[0..1023]}
- uint16_t cqi_PMI_ConfigIndex;
+ int16_t cqi_PMI_ConfigIndex;
/// Parameter: K, see 36.213 (4.2.2). \vr{[1..4]}
uint8_t K;
- /// Parameter: RI Config Index \f$I_\text{RI}\f$, see TS 36.213 (7.2.2-1B). \vr{[0..1023]}
- uint16_t ri_ConfigIndex;
+ /// Parameter: RI Config Index \f$I_\text{RI}\f$, see TS 36.213 (7.2.2-1B). \vr{[0..1023]}, -1 indicates inactivity
+ int16_t ri_ConfigIndex;
/// Parameter: Simultaneous-AN-and-CQI, see TS 36.213 (10.1). \vr{[0..1]} 1 indicates that simultaneous transmission of ACK/NACK and CQI is allowed.
uint8_t simultaneousAckNackAndCQI;
+ /// parameter computed from Tables 7.2.2-1A and 7.2.2-1C
+ uint16_t Npd;
+ /// parameter computed from Tables 7.2.2-1A and 7.2.2-1C
+ uint16_t N_OFFSET_CQI;
} CQI_REPORTPERIODIC;
/// Enumeration for parameter reporting mode \ref CQI_REPORT_CONFIG::cqi_ReportModeAperiodic.
@@ -527,12 +542,12 @@ typedef struct {
uint32_t samples_per_tti;
/// Number of OFDM/SC-FDMA symbols in one subframe (to be modified to account for potential different in UL/DL)
uint16_t symbols_per_tti;
- /// Number of Transmit antennas in node
+ /// Number of Physical transmit antennas in node
uint8_t nb_antennas_tx;
/// Number of Receive antennas in node
uint8_t nb_antennas_rx;
- /// Number of Transmit antennas in eNodeB
- uint8_t nb_antennas_tx_eNB;
+ /// Number of Logical transmit antenna ports in eNodeB
+ uint8_t nb_antenna_ports_eNB;
/// PRACH_CONFIG
PRACH_CONFIG_COMMON prach_config_common;
/// PUCCH Config Common (from 36-331 RRC spec)
@@ -586,10 +601,20 @@ typedef enum {
DUALSTREAM_UNIFORM_PRECODING1=9,
DUALSTREAM_UNIFORM_PRECODINGj=10,
DUALSTREAM_PUSCH_PRECODING=11,
- TM8=12,
- TM9_10=13
+ TM7=12,
+ TM8=13,
+ TM9_10=14
} MIMO_mode_t;
+typedef enum {
+ /// MRT
+ MRT=0,
+ /// ZF
+ ZF=1,
+ /// MMSE
+ MMSE=2
+} PRECODE_TYPE_t;
+
typedef struct {
/// \brief Holds the transmit data in time domain.
/// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
@@ -598,11 +623,17 @@ typedef struct {
/// - third index:
int32_t **txdata[3];
/// \brief holds the transmit data in the frequency domain.
- /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
+ /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER. //?
+ /// - first index: eNB id [0..2] (hard coded)
+ /// - second index: tx antenna [0..14[ where 14 is the total supported antenna ports.
+ /// - third index: sample [0..]
+ int32_t **txdataF[3];
+ /// \brief holds the transmit data after beamforming in the frequency domain.
+ /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER. //?
/// - first index: eNB id [0..2] (hard coded)
/// - second index: tx antenna [0..nb_antennas_tx[
/// - third index: sample [0..]
- int32_t **txdataF[3];
+ int32_t **txdataF_BF[3];
/// \brief Holds the received data in time domain.
/// Should point to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
/// - first index: sector id [0..2] (hard coded)
@@ -623,6 +654,17 @@ typedef struct {
/// - first index: sector id [0..2] (hard coded)
/// - second index: sample [0..samples_per_tti*10[
uint32_t *sync_corr[3];
+ /// \brief Holds the beamforming weights
+ /// - first index: eNB id [0..2] (hard coded)
+ /// - second index: eNB antenna port index (hard coded)
+ /// - third index: tx antenna [0..nb_antennas_tx[
+ /// - fourth index: sample [0..]
+ int32_t **beam_weights[3][15];
+ /// \brief Holds the tdd reciprocity calibration coefficients
+ /// - first index: eNB id [0..2] (hard coded)
+ /// - second index: tx antenna [0..nb_antennas_tx[
+ /// - third index: frequency [0..]
+ int32_t **tdd_calib_coeffs[3];
} LTE_eNB_COMMON;
typedef struct {
@@ -783,6 +825,10 @@ typedef struct {
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
int32_t **rxdataF_ext;
+ /// \brief Received frequency-domain ue specific pilots.
+ /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+ /// - second index: ? [0..12*N_RB_DL[
+ int32_t **rxdataF_uespec_pilots;
/// \brief Received frequency-domain signal after extraction and channel compensation.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
@@ -796,6 +842,14 @@ typedef struct {
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
int32_t **dl_ch_estimates_ext;
+ /// \brief Downlink beamforming channel estimates in frequency domain.
+ /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+ /// - second index: samples? [0..symbols_per_tti*(ofdm_symbol_size+LTE_CE_FILTER_LENGTH)[
+ int32_t **dl_bf_ch_estimates;
+ /// \brief Downlink beamforming channel estimates.
+ /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+ /// - second index: ? [0..168*N_RB_DL[
+ int32_t **dl_bf_ch_estimates_ext;
/// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
@@ -999,13 +1053,13 @@ typedef struct {
/// first index: ? [0..1023] (hard coded)
int16_t *prachF;
/// \brief ?.
- /// first index: rx antenna [0..3] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
+ /// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
/// second index: ? [0..ofdm_symbol_size*12[
- int16_t *rxsigF[4];
+ int16_t *rxsigF[64];
/// \brief local buffer to compute prach_ifft (necessary in case of multiple CCs)
- /// first index: rx antenna [0..3] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
+ /// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
/// second index: ? [0..2047] (hard coded)
- int16_t *prach_ifft[4];
+ int16_t *prach_ifft[64];
} LTE_eNB_PRACH;
typedef struct {
diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h
index c9e468948e..79e684215c 100644
--- a/openair1/PHY/impl_defs_top.h
+++ b/openair1/PHY/impl_defs_top.h
@@ -177,6 +177,7 @@
#define DMA_BLKS_PER_SLOT (SLOT_LENGTH_BYTES/2048) // Number of DMA blocks per slot
#define SLOT_TIME_NS (SLOT_LENGTH_SAMPLES*(1e3)/7.68) // slot time in ns
+#define NB_ANTENNA_PORTS_ENB 14 // total number of eNB antenna ports
#ifdef EXMIMO
#define TARGET_RX_POWER 55 // Target digital power for the AGC
diff --git a/openair1/SCHED/Makefile.inc b/openair1/SCHED/Makefile.inc
index e3fd877e5d..559d3dca32 100644
--- a/openair1/SCHED/Makefile.inc
+++ b/openair1/SCHED/Makefile.inc
@@ -3,3 +3,4 @@ SCHED_OBJS += $(TOP_DIR)/SCHED/phy_procedures_lte_ue.o
SCHED_OBJS += $(TOP_DIR)/SCHED/phy_procedures_lte_eNb.o
SCHED_OBJS += $(TOP_DIR)/SCHED/pusch_pc.o
SCHED_OBJS += $(TOP_DIR)/SCHED/pucch_pc.o
+SCHED_OBJS += $(TOP_DIR)/SCHED/srs_pc.o
diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h
index ba5f4cc8b5..2490a4035c 100644
--- a/openair1/SCHED/defs.h
+++ b/openair1/SCHED/defs.h
@@ -69,6 +69,11 @@ enum openair_SYNCH_STATUS {
openair_SCHED_EXIT
};
+enum openair_HARQ_TYPE {
+ openair_harq_DL = 0,
+ openair_harq_UL,
+ openair_harq_RA
+};
#define DAQ_AGC_ON 1
#define DAQ_AGC_OFF 0
@@ -437,6 +442,17 @@ int8_t pucch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t subframe,ui
*/
void pusch_power_cntl(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag);
+/*! \brief This function implements the power control mechanism for SRS from 36.213.
+ @param phy_vars_ue PHY variables
+ @param proc Pointer to proc descriptor
+ @param eNB_id Index of eNB
+ @param j index of type of PUSCH (SPS, Normal, Msg3)
+ @returns Transmit power
+ */
+void srs_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t *pnb_rb_srs, uint8_t abstraction_flag);
+
+void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id);
+
int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id, uint8_t eNB_index);
#ifdef LOCALIZATION
@@ -452,6 +468,8 @@ double aggregate_eNB_UE_localization_stats(PHY_VARS_eNB *phy_vars_eNB, int8_t UE
#endif
LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti);
+
+
LTE_DL_FRAME_PARMS *get_lte_frame_parms(module_id_t Mod_id, uint8_t CC_id);
MU_MIMO_mode* get_mu_mimo_mode (module_id_t Mod_id, uint8_t CC_id, rnti_t rnti);
diff --git a/openair1/SCHED/phy_mac_stub.c b/openair1/SCHED/phy_mac_stub.c
index 0ac194d051..cb22461656 100644
--- a/openair1/SCHED/phy_mac_stub.c
+++ b/openair1/SCHED/phy_mac_stub.c
@@ -40,14 +40,21 @@
#include "SCHED/phy_procedures_emos.h"
#endif
+/* SYRTEM */
+uint8_t dci_ndi_toggle_even[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+uint8_t dci_ndi_toggle_odd[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
{
-
+/* SYRTEM */
+ uint8_t *dci_ndi_toggle_tmp = NULL;
+ uint8_t harq_pid_value = 0;
+/* End of SYRTEM */
//uint8_t cooperation_flag = eNB->cooperation_flag;
uint8_t transmission_mode = eNB->transmission_mode[0];
- uint32_t rballoc = 0x7FFF;
+ uint32_t rballoc = 0x1FFFF;
//uint32_t rballoc2 = 0x000F;
int subframe = proc->subframe_tx;
@@ -63,17 +70,21 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
uint32_t bcch_pdu;
uint64_t dlsch_pdu;
+ LOG_I(PHY,"frame %d, subframe %d, transmission_mode %d\n",proc->frame_tx,proc->subframe_tx,transmission_mode);
+
DCI_pdu->Num_common_dci = 0;
DCI_pdu->Num_ue_spec_dci=0;
switch (subframe) {
case 5:
- DCI_pdu->Num_common_dci = 1;
- DCI_pdu->dci_alloc[0].L = 2;
- DCI_pdu->dci_alloc[0].firstCCE = 0;
- DCI_pdu->dci_alloc[0].rnti = SI_RNTI;
- DCI_pdu->dci_alloc[0].format = format1A;
- DCI_pdu->dci_alloc[0].ra_flag = 0;
+ if ( !(proc->frame_tx&1) ) // SI message on even frame only (SFN mod 2 == 0)
+ {
+ DCI_pdu->Num_common_dci = 1;
+ DCI_pdu->dci_alloc[0].L = 2;
+ DCI_pdu->dci_alloc[0].firstCCE = 0;
+ DCI_pdu->dci_alloc[0].rnti = SI_RNTI;
+ DCI_pdu->dci_alloc[0].format = format1A;
+ DCI_pdu->dci_alloc[0].ra_flag = 0;
switch (eNB->frame_parms.N_RB_DL) {
case 6:
@@ -187,6 +198,12 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
}
break; //subframe switch
+ } // if ( !(proc->frame_tx&1) )
+ else // No SI message on odd frame (SFN mod 2 == 1)
+ {
+ /* warning: work around to send dlsch on subframe 5 odd frame !!! */
+ /* todo: clean up, espacially if subframe cases are added next !!! */
+ }
/*
case 6:
DCI_pdu->Num_ue_spec_dci = 1;
@@ -218,22 +235,30 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
DCI_pdu->dci_alloc[0].format = format1;
DCI_pdu->dci_alloc[0].ra_flag = 0;
- if (transmission_mode<3) {
+ if (transmission_mode<3 || transmission_mode == 7) {
//user 1
switch (eNB->frame_parms.N_RB_DL) {
case 25:
if (eNB->frame_parms.frame_type == FDD) {
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_5MHz_FDD_t;
+ harq_pid_value = ( ((proc->frame_tx * 10) + subframe) % 8 );
+
+ if (!(subframe&1)) // even subframe
+ dci_ndi_toggle_tmp = &(dci_ndi_toggle_even[harq_pid_value]);
+ else // odd subframe
+ dci_ndi_toggle_tmp = &(dci_ndi_toggle_odd[harq_pid_value]);
+
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; //computeRIV(25,10,3);
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC = 0;
- ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = subframe % 5;
+ ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = harq_pid_value;
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs;
- //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28);
- ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = subframe / 5;
+ ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = (*dci_ndi_toggle_tmp);
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0;
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rah = 0;
+ (*dci_ndi_toggle_tmp) = ((*dci_ndi_toggle_tmp) + 1) & 1;
+
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_FDD_t));
/*
@@ -296,36 +321,24 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
if (eNB->frame_parms.frame_type == FDD) {
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_10MHz_FDD_t;
+ harq_pid_value = ( ((proc->frame_tx * 10) + subframe) % 8 );
+
+ if (!(subframe&1)) // even subframe
+ dci_ndi_toggle_tmp = &(dci_ndi_toggle_even[harq_pid_value]);
+ else // odd subframe
+ dci_ndi_toggle_tmp = &(dci_ndi_toggle_odd[harq_pid_value]);
+
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; //computeRIV(50,10,3);
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->TPC = 0;
- ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = subframe % 5;
+ ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = harq_pid_value;
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs;
- //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28);
- ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = subframe / 5;
+ ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = (*dci_ndi_toggle_tmp);
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0;
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rah = 0;
+ (*dci_ndi_toggle_tmp) = ((*dci_ndi_toggle_tmp) + 1) & 1;
+
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_FDD_t));
-
- /*
- //user2
- DCI_pdu->dci_alloc[1].dci_length = sizeof_DCI1_10MHz_TDD_t;
- DCI_pdu->dci_alloc[1].L = 2;
- DCI_pdu->dci_alloc[1].rnti = 0x1236;
- DCI_pdu->dci_alloc[1].format = format1;
- DCI_pdu->dci_alloc[1].ra_flag = 0;
-
- ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc2;
- ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->TPC = 0;
- ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->dai = 0;
- ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1;
- //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->proc[subframe].frame%1024)%28);
- ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs;
- ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = 1;
- ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0;
- ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rah = 0;
- memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_10MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_10MHz_TDD_t));
- */
} else {
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_10MHz_TDD_t;
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 5e0c750b10..319ee8f48a 100644
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -21,11 +21,11 @@
/*! \file phy_procedures_lte_eNB.c
* \brief Implementation of eNB procedures from 36.213 LTE specifications
- * \author R. Knopp, F. Kaltenberger, N. Nikaein
+ * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas
* \date 2011
* \version 0.1
* \company Eurecom
- * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr
+ * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk
* \note
* \warning
*/
@@ -61,6 +61,14 @@
# include "intertask_interface.h"
#endif
+
+#if defined(FLEXRAN_AGENT_SB_IF)
+//Agent-related headers
+#include "ENB_APP/flexran_agent_extern.h"
+#include "ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h"
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+#endif
+
//#define DIAG_PHY
#define NS_PER_SLOT 500000
@@ -221,7 +229,7 @@ int8_t find_next_ue_index(PHY_VARS_eNB *eNB)
return(-1);
}
-int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t ul_flag)
+int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t harq_flag)
{
LTE_eNB_DLSCH_t *DLSCH_ptr;
LTE_eNB_ULSCH_t *ULSCH_ptr;
@@ -235,9 +243,20 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16
return(-1);
}
- if (ul_flag == 0) {// this is a DL request
+ if ((harq_flag == openair_harq_DL) || (harq_flag == openair_harq_RA)) {// this is a DL request
+
DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch[(uint32_t)UE_id][0];
+ if (harq_flag == openair_harq_RA) {
+ if (DLSCH_ptr->harq_processes[0] != NULL) {
+ *harq_pid = 0;
+ *round = DLSCH_ptr->harq_processes[0]->round;
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+
/* let's go synchronous for the moment - maybe we can change at some point */
i = (frame * 10 + subframe) % 8;
@@ -671,7 +690,8 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC
SI_RNTI,
0,
P_RNTI,
- eNB->UE_stats[0].DL_pmi_single);
+ eNB->UE_stats[0].DL_pmi_single,
+ 0);
eNB->dlsch_SI->nCCE[subframe] = dci_alloc->firstCCE;
@@ -704,7 +724,8 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC
SI_RNTI,
dci_alloc->rnti,
P_RNTI,
- eNB->UE_stats[0].DL_pmi_single);
+ eNB->UE_stats[0].DL_pmi_single,
+ 0);
eNB->dlsch_ra->nCCE[subframe] = dci_alloc->firstCCE;
@@ -753,7 +774,8 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC
SI_RNTI,
0,
P_RNTI,
- eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single);
+ eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single,
+ eNB->transmission_mode[(uint8_t)UE_id]<7?0:eNB->transmission_mode[(uint8_t)UE_id]);
LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n",
eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,frame,subframe);
@@ -886,7 +908,10 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
dlsch_harq->rb_alloc,
get_Qm(dlsch_harq->mcs),
dlsch_harq->Nl,
- num_pdcch_symbols,frame,subframe),
+ num_pdcch_symbols,
+ frame,
+ subframe,
+ dlsch_harq->mimo_mode==TM7?7:0),
dlsch_harq->nb_rb,
dlsch_harq->mcs,
pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
@@ -905,7 +930,10 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
dlsch_harq->rb_alloc,
get_Qm(dlsch_harq->mcs),
dlsch_harq->Nl,
- num_pdcch_symbols,frame,subframe),
+ num_pdcch_symbols,
+ frame,
+ subframe,
+ dlsch_harq->mimo_mode==TM7?7:0),
dlsch_harq->nb_rb,
dlsch_harq->mcs,
pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
@@ -1062,7 +1090,9 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
dlsch_harq->rb_alloc,
get_Qm(dlsch_harq->mcs),
dlsch_harq->Nl,
- num_pdcch_symbols,frame,subframe),
+ num_pdcch_symbols,
+ frame,subframe,
+ 0),
0,
subframe<<1);
stop_meas(&eNB->dlsch_scrambling_stats);
@@ -1070,10 +1100,10 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
start_meas(&eNB->dlsch_modulation_stats);
- dlsch_modulation(eNB->common_vars.txdataF[0],
+ dlsch_modulation(eNB,
+ eNB->common_vars.txdataF[0],
AMP,
subframe,
- fp,
num_pdcch_symbols,
dlsch,
dlsch1);
@@ -1105,7 +1135,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
int frame=proc->frame_tx;
int subframe=proc->subframe_tx;
// uint16_t input_buffer_length;
- uint32_t i,aa;
+ uint32_t i,j,aa;
uint8_t harq_pid;
DCI_PDU *DCI_pdu;
DCI_PDU DCI_pdu_tmp;
@@ -1165,7 +1195,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
// clear the transmit data array for the current subframe
if (eNB->abstraction_flag==0) {
- for (aa=0; aanb_antennas_tx_eNB; aa++) {
+ for (aa=0; aanb_antenna_ports_eNB; aa++) {
memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
}
@@ -1203,6 +1233,14 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
fill_dci_emos(DCI_pdu,eNB);
#else
fill_dci(DCI_pdu,eNB,proc);
+ // clear previous allocation information for all UEs
+ for (i=0; idlsch[i][0]){
+ for (j=0; j<8; j++)
+ eNB->dlsch[i][0]->harq_processes[j]->round = 0;
+ }
+ }
+
#endif
}
@@ -1405,7 +1443,16 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
eNB->dlsch_ra->active = 0;
}
-
+
+#if defined(FLEXRAN_AGENT_SB_IF)
+#ifndef DISABLE_SF_TRIGGER
+ //Send subframe trigger to the controller
+ if (mac_agent_registered[eNB->Mod_id]) {
+ agent_mac_xface[eNB->Mod_id]->flexran_agent_send_sf_trigger(eNB->Mod_id);
+ }
+#endif
+#endif
+
// Now scan UE specific DLSCH
for (UE_id=0; UE_iddlsch[eNB_id][0]->harq_processes[harq_pid]->Qm,
ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl,
ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
- proc->frame_rx,subframe);
+ proc->frame_rx,
+ subframe,
+ ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]);
write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,2,1);
write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars[0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1);
@@ -118,7 +124,9 @@ void dump_dlsch_SI(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t s
2,
1,
ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
- proc->frame_rx,subframe);
+ proc->frame_rx,
+ subframe,
+ 0);
LOG_D(PHY,"[UE %d] Dumping dlsch_SI : ofdm_symbol_size %d, nsymb %d, nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n",
ue->Mod_id,
ue->frame_parms.ofdm_symbol_size,
@@ -224,7 +232,9 @@ void dump_dlsch_ra(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t s
2,
1,
ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
- proc->frame_rx,subframe);
+ proc->frame_rx,
+ subframe,
+ 0);
LOG_D(PHY,"[UE %d] Dumping dlsch_ra : nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n",
ue->Mod_id,
ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb,
@@ -377,6 +387,345 @@ uint8_t is_SR_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
return(0);
}
+uint8_t is_cqi_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
+{
+ int subframe = proc->subframe_tx;
+ int frame = proc->frame_tx;
+ CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic;
+
+ //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for CQI TXOp (cqi_ConfigIndex %d) isCQIOp %d\n",
+ // ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame,subframe,
+ // cqirep->cqi_PMI_ConfigIndex,
+ // (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI));
+
+ if (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI)
+ return(1);
+ else
+ return(0);
+}
+uint8_t is_ri_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
+{
+
+
+ int subframe = proc->subframe_tx;
+ int frame = proc->frame_tx;
+ CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic;
+ int log2Mri = cqirep->ri_ConfigIndex/161;
+ int N_OFFSET_RI = cqirep->ri_ConfigIndex % 161;
+
+ //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for RI TXOp (ri_ConfigIndex %d) isRIOp %d\n",
+ // ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame,subframe,
+ // cqirep->ri_ConfigIndex,
+ // (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<macphy_exit("2 ms SRS periodicity not supported");
+ }
+
+ if((isrs>9)&&(isrs<15))
+ {
+ *psrsPeriodicity=5;
+ *psrsOffset=isrs-10;
+ }
+ if((isrs>14)&&(isrs<25))
+ {
+ *psrsPeriodicity=10;
+ *psrsOffset=isrs-15;
+ }
+ if((isrs>24)&&(isrs<45))
+ {
+ *psrsPeriodicity=20;
+ *psrsOffset=isrs-25;
+ }
+ if((isrs>44)&&(isrs<85))
+ {
+ *psrsPeriodicity=40;
+ *psrsOffset=isrs-45;
+ }
+ if((isrs>84)&&(isrs<165))
+ {
+ *psrsPeriodicity=80;
+ *psrsOffset=isrs-85;
+ }
+ if((isrs>164)&&(isrs<325))
+ {
+ *psrsPeriodicity=160;
+ *psrsOffset=isrs-165;
+ }
+ if((isrs>324)&&(isrs<645))
+ {
+ *psrsPeriodicity=320;
+ *psrsOffset=isrs-325;
+ }
+
+ if(isrs>644)
+ {
+ mac_xface->macphy_exit("Isrs out of range");
+ }
+
+ }
+ else
+ {
+ if(isrs<2)
+ {
+ *psrsPeriodicity=2;
+ *psrsOffset=isrs;
+ }
+ if((isrs>1)&&(isrs<7))
+ {
+ *psrsPeriodicity=5;
+ *psrsOffset=isrs-2;
+ }
+ if((isrs>6)&&(isrs<17))
+ {
+ *psrsPeriodicity=10;
+ *psrsOffset=isrs-7;
+ }
+ if((isrs>16)&&(isrs<37))
+ {
+ *psrsPeriodicity=20;
+ *psrsOffset=isrs-17;
+ }
+ if((isrs>36)&&(isrs<77))
+ {
+ *psrsPeriodicity=40;
+ *psrsOffset=isrs-37;
+ }
+ if((isrs>76)&&(isrs<157))
+ {
+ *psrsPeriodicity=80;
+ *psrsOffset=isrs-77;
+ }
+ if((isrs>156)&&(isrs<317))
+ {
+ *psrsPeriodicity=160;
+ *psrsOffset=isrs-157;
+ }
+ if((isrs>316)&&(isrs<637))
+ {
+ *psrsPeriodicity=320;
+ *psrsOffset=isrs-317;
+ }
+ if(isrs>636)
+ {
+ mac_xface->macphy_exit("Isrs out of range");
+ }
+ }
+}
+
+void ue_compute_srs_occasion(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
+{
+ LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
+ int frame_tx = proc->frame_tx;
+ int subframe_tx = proc->subframe_tx;
+ uint8_t isSubframeSRS = 0; // SRS Cell Occasion
+
+ uint8_t is_pucch2_subframe = 0;
+ uint8_t is_sr_an_subframe = 0;
+
+ SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id];
+
+ // check for SRS opportunity
+ pSoundingrs_ul_config_dedicated->srsUeSubframe = 0;
+ pSoundingrs_ul_config_dedicated->srsCellSubframe = 0;
+
+ ue->ulsch[eNB_id]->srs_active = 0;
+ ue->ulsch[eNB_id]->Nsymb_pusch = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active;
+ if(frame_parms->soundingrs_ul_config_common.enabled_flag)
+ {
+
+ LOG_D(PHY," SRS SUBFRAMECONFIG: %d, Isrs: %d \n", frame_parms->soundingrs_ul_config_common.srs_SubframeConfig, pSoundingrs_ul_config_dedicated->srs_ConfigIndex);
+
+ uint8_t TSFC;
+ uint16_t deltaTSFC; // bitmap
+ uint8_t srs_SubframeConfig;
+ uint16_t srsPeriodicity;
+ uint16_t srsOffset;
+
+ // table resuming TSFC (Period) and deltaSFC (offset)
+ const uint16_t deltaTSFCTabType1[15][2] = { {1,1},{1,2},{2,2},{1,5},{2,5},{4,5},{8,5},{3,5},{12,5},{1,10},{2,10},{4,10},{8,10},{351,10},{383,10} }; // Table 5.5.3.3-2 3GPP 36.211 FDD
+ const uint16_t deltaTSFCTabType2[14][2] = { {2,5},{6,5},{10,5},{18,5},{14,5},{22,5},{26,5},{30,5},{70,10},{74,10},{194,10},{326,10},{586,10},{210,10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD
+
+ srs_SubframeConfig = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig;
+ if (FDD == frame_parms->frame_type)
+ {
+ // srs_SubframeConfig =< 14
+ deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
+ TSFC = deltaTSFCTabType1[srs_SubframeConfig][1];
+ }
+ else
+ {
+ // srs_SubframeConfig =< 13
+ deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0];
+ TSFC = deltaTSFCTabType2[srs_SubframeConfig][1];
+ }
+
+ // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC
+ uint16_t tmp = (subframe_tx % TSFC);
+ if((1<srsCellSubframe = 1;
+ }
+ LOG_D(PHY," ISTDD: %d, TSFC: %d, deltaTSFC: %d, AbsSubframeTX: %d.%d, srsCellSubframe: %d \n", frame_parms->frame_type, TSFC, deltaTSFC, frame_tx, subframe_tx, pSoundingrs_ul_config_dedicated->srsCellSubframe);
+ LOG_D(PHY," SrsDedicatedSetup: %d \n",pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup);
+ if(pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup)
+ {
+ compute_srs_pos(frame_parms->frame_type, pSoundingrs_ul_config_dedicated->srs_ConfigIndex, &srsPeriodicity, &srsOffset);
+
+ LOG_D(PHY," srsPeriodicity: %d srsOffset: %d isSubframeSRS %d \n",srsPeriodicity,srsOffset,isSubframeSRS);
+
+ // transmit SRS if the four following constraints are respected:
+ // - UE is configured to transmit SRS
+ // - SRS are configured in current subframe
+ // - UE is configured to send SRS in this subframe
+
+ // 36.213 8.2
+ // 1- A UE shall not transmit SRS whenever SRS and PUCCH format 2/2a/2b transmissions happen to coincide in the same subframe
+ // 2- A UE shall not transmit SRS whenever SRS transmit
+ // on and PUCCH transmission carrying ACK/NACK and/or
+ // positive SR happen to coincide in the same subframe if the parameter
+ // Simultaneous-AN-and-SRS is FALSE
+
+ // check PUCCH format 2/2a/2b transmissions
+ is_pucch2_subframe = is_cqi_TXOp(ue,proc,eNB_id) && (ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0);
+ is_pucch2_subframe = (is_ri_TXOp(ue,proc,eNB_id) && (ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0)) || is_pucch2_subframe;
+
+ // check ACK/SR transmission
+ if(frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission == FALSE)
+ {
+ if(is_SR_TXOp(ue,proc,eNB_id))
+ {
+ uint32_t SR_payload = 0;
+ if (ue->mac_enabled==1)
+ {
+ int Mod_id = ue->Mod_id;
+ int CC_id = ue->CC_id;
+ SR_payload = mac_xface->ue_get_SR(Mod_id,
+ CC_id,
+ frame_tx,
+ eNB_id,
+ ue->pdcch_vars[eNB_id]->crnti,
+ subframe_tx); // subframe used for meas gap
+
+ if (SR_payload > 0)
+ is_sr_an_subframe = 1;
+ }
+ }
+
+ uint8_t pucch_ack_payload[2];
+ if (get_ack(&ue->frame_parms,
+ ue->dlsch[eNB_id][0]->harq_ack,
+ subframe_tx,pucch_ack_payload) > 0)
+ {
+ is_sr_an_subframe = 1;
+ }
+ }
+
+ // check SRS UE opportunity
+ if( isSubframeSRS &&
+ (((10*frame_tx+subframe_tx) % srsPeriodicity) == srsOffset)
+ )
+ {
+ if ((is_pucch2_subframe == 0) && (is_sr_an_subframe == 0))
+ {
+ pSoundingrs_ul_config_dedicated->srsUeSubframe = 1;
+ ue->ulsch[eNB_id]->srs_active = 1;
+ ue->ulsch[eNB_id]->Nsymb_pusch = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active;
+ }
+ else
+ {
+ LOG_I(PHY,"DROP UE-SRS-TX for this subframe %d.%d: collision with PUCCH2 or SR/AN: PUCCH2-occasion: %d, SR-AN-occasion[simSRS-SR-AN %d]: %d \n", frame_tx, subframe_tx, is_pucch2_subframe, frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, is_sr_an_subframe);
+ }
+ }
+ }
+ LOG_D(PHY," srsCellSubframe: %d, srsUeSubframe: %d, Nsymb-pusch: %d \n", pSoundingrs_ul_config_dedicated->srsCellSubframe, pSoundingrs_ul_config_dedicated->srsUeSubframe, ue->ulsch[eNB_id]->Nsymb_pusch);
+ }
+}
+
+void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id)
+{
+
+ CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic;
+ int cqi_PMI_ConfigIndex = cqirep->cqi_PMI_ConfigIndex;
+
+ if (ue->frame_parms.frame_type == FDD) {
+ if (cqi_PMI_ConfigIndex <= 1) { // 2 ms CQI_PMI period
+ cqirep->Npd = 2;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex;
+ } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period
+ cqirep->Npd = 5;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-2;
+ } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period
+ cqirep->Npd = 10;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-7;
+ } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
+ cqirep->Npd = 20;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-17;
+ } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
+ cqirep->Npd = 40;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-37;
+ } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period
+ cqirep->Npd = 80;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-77;
+ } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period
+ cqirep->Npd = 160;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-157;
+ }
+ else if (cqi_PMI_ConfigIndex > 317) {
+
+ if (cqi_PMI_ConfigIndex <= 349) { // 32 ms CQI_PMI period
+ cqirep->Npd = 32;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-318;
+ }
+ else if (cqi_PMI_ConfigIndex <= 413) { // 64 ms CQI_PMI period
+ cqirep->Npd = 64;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-350;
+ }
+ else if (cqi_PMI_ConfigIndex <= 541) { // 128 ms CQI_PMI period
+ cqirep->Npd = 128;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-414;
+ }
+ }
+ }
+ else { // TDD
+ if (cqi_PMI_ConfigIndex == 0) { // all UL subframes
+ cqirep->Npd = 1;
+ cqirep->N_OFFSET_CQI = 0;
+ } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period
+ cqirep->Npd = 5;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-1;
+ } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period
+ cqirep->Npd = 10;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-6;
+ } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
+ cqirep->Npd = 20;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-16;
+ } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
+ cqirep->Npd = 40;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-36;
+ } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period
+ cqirep->Npd = 80;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-76;
+ } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period
+ cqirep->Npd = 160;
+ cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-156;
+ }
+ }
+}
+
uint16_t get_n1_pucch(PHY_VARS_UE *ue,
UE_rxtx_proc_t *proc,
uint8_t eNB_id,
@@ -600,14 +949,25 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc) {
int dummy_tx_buffer[3840*4] __attribute__((aligned(16)));
#endif
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_IN);
+
start_meas(&ue->ofdm_mod_stats);
nsymb = (frame_parms->Ncp == 0) ? 14 : 12;
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)//this is the EXPRESS MIMO case
ulsch_start = (ue->rx_offset+subframe_tx*frame_parms->samples_per_tti-
- ue->hw_timing_advance-
- ue->timing_advance-
- ue->N_TA_offset+5)%(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);
+ ue->hw_timing_advance-
+ ue->timing_advance-
+ ue->N_TA_offset+5);
+ //LOG_E(PHY,"ul-signal [subframe: %d, ulsch_start %d]\n",subframe_tx, ulsch_start);
+
+ if(ulsch_start < 0)
+ ulsch_start = ulsch_start + (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);
+
+ if (ulsch_start > (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti))
+ ulsch_start = ulsch_start % (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);
+
+ //LOG_E(PHY,"ul-signal [subframe: %d, ulsch_start %d]\n",subframe_tx, ulsch_start);
#else //this is the normal case
ulsch_start = (frame_parms->samples_per_tti*subframe_tx)-ue->N_TA_offset; //-ue->timing_advance;
#endif //else EXMIMO
@@ -678,12 +1038,21 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc) {
}
#endif
#endif
+ /*
+ only for debug
+ LOG_I(PHY,"ul-signal [subframe: %d, ulsch_start %d, TA: %d, rxOffset: %d, timing_advance: %d, hw_timing_advance: %d]\n",subframe_tx, ulsch_start, ue->N_TA_offset, ue->rx_offset, ue->timing_advance, ue->hw_timing_advance);
+ if( (crash == 1) && (subframe_tx == 0) )
+ {
+ LOG_E(PHY,"***** DUMP TX Signal [ulsch_start %d] *****\n",ulsch_start);
+ write_output("txBuff.m","txSignal",&ue->common_vars.txdata[aa][ulsch_start],frame_parms->samples_per_tti,1,1);
+ }
+ */
} //nb_antennas_tx
stop_meas(&ue->ofdm_mod_stats);
-
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_OUT);
}
@@ -694,6 +1063,8 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
int prach_power;
PRACH_RESOURCES_t prach_resources_local;
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN);
+
ue->generate_prach=0;
if (ue->mac_enabled==0){
@@ -782,14 +1153,15 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
} else {
UE_transport_info[ue->Mod_id][ue->CC_id].cntl.prach_flag=1;
UE_transport_info[ue->Mod_id][ue->CC_id].cntl.prach_id=ue->prach_resources[eNB_id]->ra_PreambleIndex;
- if (ue->mac_enabled==1){
- mac_xface->Msg1_transmitted(ue->Mod_id,
- ue->CC_id,
- frame_tx,
- eNB_id);
- }
}
+ if (ue->mac_enabled==1){
+ mac_xface->Msg1_transmitted(ue->Mod_id,
+ ue->CC_id,
+ frame_tx,
+ eNB_id);
+ }
+
LOG_D(PHY,"[UE %d][RAPROC] Frame %d, subframe %d: Generating PRACH (eNB %d) preamble index %d for UL, TX power %d dBm (PL %d dB), l3msg \n",
ue->Mod_id,frame_tx,subframe_tx,eNB_id,
ue->prach_resources[eNB_id]->ra_PreambleIndex,
@@ -810,6 +1182,8 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
if (ue->prach_cnt==3)
ue->generate_prach=0;
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_OUT);
}
void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) {
@@ -829,6 +1203,8 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
uint8_t ulsch_input_buffer[5477] __attribute__ ((aligned(32)));
uint8_t access_mode;
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,VCD_FUNCTION_IN);
+
// get harq_pid from subframe relationship
harq_pid = subframe2harq_pid(&ue->frame_parms,
frame_tx,
@@ -857,8 +1233,8 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
} else {
if (harq_pid==255) {
- LOG_E(PHY,"[UE%d] Frame %d ulsch_decoding.c: FATAL ERROR: illegal harq_pid, returning\n",
- Mod_id,frame_tx);
+ LOG_E(PHY,"[UE%d] Frame %d subframe %d ulsch_decoding.c: FATAL ERROR: illegal harq_pid, returning\n",
+ Mod_id,frame_tx, subframe_tx);
mac_xface->macphy_exit("Error in ulsch_decoding");
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT);
stop_meas(&ue->phy_proc_tx);
@@ -874,7 +1250,14 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
ue->generate_ul_signal[eNB_id] = 1;
// deactivate service request
- ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
+ // ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
+ LOG_D(PHY,"Generating PUSCH (Abssubframe: %d.%d): harq-Id: %d, round: %d, MaxReTrans: %d \n",frame_tx,subframe_tx,harq_pid,ue->ulsch[eNB_id]->harq_processes[harq_pid]->round,ue->ulsch[eNB_id]->Mlimit);
+ if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round >= (ue->ulsch[eNB_id]->Mlimit - 1))
+ {
+ LOG_D(PHY,"PUSCH MAX Retransmission acheived ==> send last pusch (%d) \n");
+ ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
+ ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0;
+ }
ack_status = get_ack(&ue->frame_parms,
ue->dlsch[eNB_id][0]->harq_ack,
@@ -887,6 +1270,27 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
+
+ if (ack_status > 0) {
+
+ // check if we received a PDSCH at subframe_tx - 4
+ // ==> send ACK/NACK on PUSCH
+ if( (ue->dlsch[eNB_id][0]->harq_ack[proc->subframe_rx].send_harq_status) == 1)
+ {
+ ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK = 1;
+ }
+ else
+ {
+ ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK = 0;
+ }
+ LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d Generating ACK (%d,%d) for %d bits on PUSCH\n",
+ Mod_id,
+ ue->ulsch[eNB_id]->rnti,
+ frame_tx,subframe_tx,
+ ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1],
+ ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK);
+ }
+
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,
"[UE %d][PUSCH %d] Frame %d subframe %d Generating PUSCH : first_rb %d, nb_rb %d, round %d, mcs %d, rv %d, cyclic_shift %d (cyclic_shift_common %d,n_DMRS2 %d,n_PRS %d), ACK (%d,%d), O_ACK %d\n",
@@ -905,15 +1309,6 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK);
#endif
- if (ack_status > 0) {
- LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d Generating ACK (%d,%d) for %d bits on PUSCH\n",
- Mod_id,
- ue->ulsch[eNB_id]->rnti,
- frame_tx,subframe_tx,
- ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1],
- ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK);
- }
-
@@ -1076,17 +1471,98 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
ue->sr[subframe_tx]=0;
}
} // subframe_scheduling_flag==1
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,VCD_FUNCTION_OUT);
+
}
+void ue_srs_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag)
+{
+
+ //LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
+ //int8_t frame_tx = proc->frame_tx;
+ int8_t subframe_tx = proc->subframe_tx;
+ int16_t tx_amp;
+ int16_t Po_SRS;
+ uint8_t nb_rb_srs;
+
+ SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id];
+ uint8_t isSrsTxOccasion = pSoundingrs_ul_config_dedicated->srsUeSubframe;
+
+ if(isSrsTxOccasion)
+ {
+ ue->generate_ul_signal[eNB_id] = 1;
+ if (ue->mac_enabled==1)
+ {
+ srs_power_cntl(ue,proc,eNB_id, (uint8_t*)(&nb_rb_srs), abstraction_flag);
+ Po_SRS = ue->ulsch[eNB_id]->Po_SRS;
+ }
+ else
+ {
+ Po_SRS = ue->tx_power_max_dBm;
+ }
+
+#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
+ if (ue->mac_enabled==1)
+ {
+ tx_amp = get_tx_amp(Po_SRS,
+ ue->tx_power_max_dBm,
+ ue->frame_parms.N_RB_UL,
+ nb_rb_srs);
+ }
+ else
+ {
+ tx_amp = AMP;
+ }
+#else
+ tx_amp = AMP;
+#endif
+ LOG_D(PHY,"SRS PROC; TX_MAX_POWER %d, Po_SRS %d, NB_RB_UL %d, NB_RB_SRS %d TX_AMPL %d\n",ue->tx_power_max_dBm,
+ Po_SRS,
+ ue->frame_parms.N_RB_UL,
+ nb_rb_srs,
+ tx_amp);
+
+ generate_srs_tx(ue, eNB_id, tx_amp, subframe_tx);
+ }
+}
+
+int16_t get_pucch2_cqi(PHY_VARS_UE *ue,int eNB_id,int *len) {
+
+ if ((ue->transmission_mode[eNB_id]<4)||
+ (ue->transmission_mode[eNB_id]==7)) { // Mode 1-0 feedback
+ // 4-bit CQI message
+ *len=4;
+ return(sinr2cqi((double)ue->measurements.wideband_cqi_avg[eNB_id],
+ ue->transmission_mode[eNB_id]));
+ }
+ else { // Mode 1-1 feedback, later
+ *len=0;
+ // 2-antenna ports RI=1, 6 bits (2 PMI, 4 CQI)
+
+ // 2-antenna ports RI=2, 8 bits (1 PMI, 7 CQI/DIFF CQI)
+ return(0);
+ }
+}
+
+
+int16_t get_pucch2_ri(PHY_VARS_UE *ue,int eNB_id) {
+
+ return(1);
+}
void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) {
uint8_t pucch_ack_payload[2];
- uint8_t n1_pucch;
+ uint8_t n1_pucch,n2_pucch;
ANFBmode_t bundling_flag;
PUCCH_FMT_t format;
+
uint8_t SR_payload;
+ uint16_t CQI_payload;
+ uint16_t RI_payload;
+
LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
int frame_tx=proc->frame_tx;
int subframe_tx=proc->subframe_tx;
@@ -1095,6 +1571,28 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
int tx_amp;
int8_t Po_PUCCH;
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_IN);
+
+ SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id];
+
+ // 36.213 8.2
+ /*if ackNackSRS_SimultaneousTransmission == TRUE and in the cell specific SRS subframes UE shall transmit
+ ACK/NACK and SR using the shortened PUCCH format. This shortened PUCCH format shall be used in a cell
+ specific SRS subframe even if the UE does not transmit SRS in that subframe
+ */
+
+ int harq_pid = subframe2harq_pid(&ue->frame_parms,
+ frame_tx,
+ subframe_tx);
+
+ if(ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag)
+ {
+ LOG_D(PHY,"PUSCH is programmed on this subframe [pid %d] AbsSuframe %d.%d ==> Skip PUCCH transmission \n",harq_pid,frame_tx,subframe_tx);
+ return;
+ }
+
+ uint8_t isShortenPucch = (pSoundingrs_ul_config_dedicated->srsCellSubframe && frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission);
+
bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode;
if ((frame_parms->frame_type==FDD) ||
@@ -1167,19 +1665,23 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
#endif
if (SR_payload>0) {
- LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Generating PUCCH 1a/1b payload %d,%d (with SR for PUSCH), n1_pucch %d, Po_PUCCH, amp %d\n",
+ LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Generating PUCCH 1a/1b payload %d,%d (with SR for PUSCH), an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, Po_PUCCH, amp %d\n",
Mod_id,
ue->dlsch[eNB_id][0]->rnti,
+ frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission,
+ isShortenPucch,
frame_tx, subframe_tx,
pucch_ack_payload[0],pucch_ack_payload[1],
ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex,
Po_PUCCH,
tx_amp);
} else {
- LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d Generating PUCCH 1a/1b, n1_pucch %d, b[0]=%d,b[1]=%d (SR_Payload %d), Po_PUCCH %d, amp %d\n",
+ LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d Generating PUCCH 1a/1b, an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, b[0]=%d,b[1]=%d (SR_Payload %d), Po_PUCCH %d, amp %d\n",
Mod_id,
ue->dlsch[eNB_id][0]->rnti,
frame_tx, subframe_tx,
+ frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission,
+ isShortenPucch,
n1_pucch,pucch_ack_payload[0],pucch_ack_payload[1],SR_payload,
Po_PUCCH,
tx_amp);
@@ -1193,7 +1695,7 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
format,
&ue->pucch_config_dedicated[eNB_id],
n1_pucch,
- 1, // shortened format
+ isShortenPucch, // shortened format
pucch_ack_payload,
tx_amp,
subframe_tx);
@@ -1210,7 +1712,7 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
#endif
}
} else if (SR_payload==1) { // no ACK/NAK but SR is triggered by MAC
-
+
if (ue->mac_enabled == 1) {
Po_PUCCH = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,pucch_format1);
}
@@ -1228,10 +1730,12 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
#else
tx_amp = AMP;
#endif
- LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Generating PUCCH 1 (SR for PUSCH), n1_pucch %d, Po_PUCCH %d\n",
+ LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Generating PUCCH 1 (SR for PUSCH), an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, Po_PUCCH %d\n",
Mod_id,
ue->dlsch[eNB_id][0]->rnti,
frame_tx, subframe_tx,
+ frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission,
+ isShortenPucch,
ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex,
Po_PUCCH);
@@ -1243,7 +1747,7 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
pucch_format1,
&ue->pucch_config_dedicated[eNB_id],
ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex,
- 1, // shortened format
+ isShortenPucch, // shortened format
pucch_ack_payload, // this is ignored anyway, we just need a pointer
tx_amp,
subframe_tx);
@@ -1258,6 +1762,113 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
}
} // SR_Payload==1
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_OUT);
+
+ // PUCCH 2x
+
+ if (ue->generate_ul_signal[eNB_id] == 0) { // we have not generated ACK/NAK/SR in this subframe
+
+ n2_pucch = ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PUCCH_ResourceIndex;
+ // only use format2 for now, i.e. now ACK/NAK - CQI multiplexing
+ format = pucch_format2;
+
+ // Periodic CQI report
+ if ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0)&&
+ (is_cqi_TXOp(ue,proc,eNB_id)==1)){
+
+ if (ue->mac_enabled == 1) {
+ Po_PUCCH = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,format);
+ }
+ else {
+ Po_PUCCH = ue->tx_power_max_dBm;
+ }
+ ue->tx_power_dBm[subframe_tx] = Po_PUCCH;
+ ue->tx_total_RE[subframe_tx] = 12;
+
+#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
+ tx_amp = get_tx_amp(Po_PUCCH,
+ ue->tx_power_max_dBm,
+ ue->frame_parms.N_RB_UL,
+ 1);
+#else
+ tx_amp = AMP;
+#endif
+ LOG_D(PHY,"[UE %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2 (CQI), n2_pucch %d, Po_PUCCH %d, isShortenPucch %d, amp %d\n",
+ Mod_id,
+ ue->dlsch[eNB_id][0]->rnti,
+ frame_tx, subframe_tx,
+ n2_pucch,
+ Po_PUCCH,
+ isShortenPucch,
+ tx_amp);
+
+ int len;
+ // get the payload : < 12 bits, returned in len
+ CQI_payload = get_pucch2_cqi(ue,eNB_id,&len);
+ generate_pucch2x(ue->common_vars.txdataF,
+ &ue->frame_parms,
+ ue->ncs_cell,
+ format,
+ &ue->pucch_config_dedicated[eNB_id],
+ n2_pucch,
+ &CQI_payload,
+ len, // A
+ 0, // B2 not needed
+ tx_amp,
+ subframe_tx,
+ ue->pdcch_vars[eNB_id]->crnti);
+
+ ue->generate_ul_signal[eNB_id] = 1;
+ }
+ // Periodic RI report
+ else if ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0) &&
+ (is_ri_TXOp(ue,proc,eNB_id)==1)){
+
+ if (ue->mac_enabled == 1) {
+ Po_PUCCH = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,format);
+ }
+ else {
+ Po_PUCCH = ue->tx_power_max_dBm;
+ }
+ ue->tx_power_dBm[subframe_tx] = Po_PUCCH;
+ ue->tx_total_RE[subframe_tx] = 12;
+
+#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
+ tx_amp = get_tx_amp(Po_PUCCH,
+ ue->tx_power_max_dBm,
+ ue->frame_parms.N_RB_UL,
+ 1);
+#else
+ tx_amp = AMP;
+#endif
+ LOG_D(PHY,"[UE %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2 (RI), n2_pucch %d, Po_PUCCH %d, isShortenPucch %d, amp %d\n",
+ Mod_id,
+ ue->dlsch[eNB_id][0]->rnti,
+ frame_tx, subframe_tx,
+ n2_pucch,
+ Po_PUCCH,
+ isShortenPucch,
+ tx_amp);
+
+ RI_payload = get_pucch2_ri(ue,eNB_id);
+
+ generate_pucch2x(ue->common_vars.txdataF,
+ &ue->frame_parms,
+ ue->ncs_cell,
+ format,
+ &ue->pucch_config_dedicated[eNB_id],
+ n2_pucch,
+ &RI_payload,
+ 1, // A
+ 0, // B2 not needed
+ tx_amp,
+ subframe_tx,
+ ue->pdcch_vars[eNB_id]->crnti);
+
+ ue->generate_ul_signal[eNB_id] = 1;
+ }
+ }
}
void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type) {
@@ -1293,13 +1904,18 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui
}
if (ue->UE_mode[eNB_id] != PRACH) {
+ // check cell srs subframe and ue srs subframe. This has an impact on pusch encoding
+ ue_compute_srs_occasion(ue,proc,eNB_id);
ue_ulsch_uespec_procedures(ue,proc,eNB_id,abstraction_flag);
}
- if (ue->UE_mode[eNB_id] == PUSCH) { // check if we need to use PUCCH 1a/1b
- ue_pucch_procedures(ue,proc,eNB_id,abstraction_flag);
+ if (ue->UE_mode[eNB_id] == PUSCH) {
+ // check if we need to use PUCCH 1a/1b
+ ue_pucch_procedures(ue,proc,eNB_id,abstraction_flag);
+ // check if we need to use SRS
+ ue_srs_procedures(ue,proc,eNB_id,abstraction_flag);
} // UE_mode==PUSCH
@@ -1709,6 +2325,17 @@ void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uin
if ((pbch_tx_ant>0) && (pbch_tx_ant<=4)) {
+ if (opt_enabled) {
+ static uint8_t dummy[3];
+ dummy[0] = ue->pbch_vars[eNB_id]->decoded_output[2];
+ dummy[1] = ue->pbch_vars[eNB_id]->decoded_output[1];
+ dummy[2] = ue->pbch_vars[eNB_id]->decoded_output[0];
+ trace_pdu(1, dummy, 3, ue->Mod_id, 0, 0,
+ frame_rx, subframe_rx, 0, 0);
+ LOG_D(OPT,"[UE %d][PBCH] Frame %d trace pdu for PBCH\n",
+ ue->Mod_id, subframe_rx);
+ }
+
if (pbch_tx_ant>2) {
LOG_W(PHY,"[openair][SCHED][SYNCH] PBCH decoding: pbch_tx_ant>2 not supported\n");
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT);
@@ -1972,7 +2599,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
ue->pdsch_config_dedicated,
SI_RNTI,
0,
- P_RNTI)==0)) {
+ P_RNTI,
+ ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0)) {
ue->dlsch_received[eNB_id]++;
@@ -2015,7 +2643,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
ue->pdsch_config_dedicated,
SI_RNTI,
0,
- P_RNTI)==0) {
+ P_RNTI,
+ ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0) {
ue->dlsch_SI_received[eNB_id]++;
@@ -2037,14 +2666,15 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
if (generate_ue_dlsch_params_from_dci(frame_rx,
subframe_rx,
(void *)&dci_alloc_rx[i].dci_pdu,
- SI_RNTI,
+ P_RNTI,
dci_alloc_rx[i].format,
&ue->dlsch_SI[eNB_id],
&ue->frame_parms,
ue->pdsch_config_dedicated,
SI_RNTI,
0,
- P_RNTI)==0) {
+ P_RNTI,
+ ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0) {
ue->dlsch_p_received[eNB_id]++;
@@ -2078,7 +2708,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
ue->pdsch_config_dedicated,
SI_RNTI,
ue->prach_resources[eNB_id]->ra_RNTI,
- P_RNTI)==0) {
+ P_RNTI,
+ ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0) {
ue->dlsch_ra_received[eNB_id]++;
@@ -2227,7 +2858,9 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,int eNB_id,int abs
ue->dlsch_MCH[0]->harq_processes[0]->Qm,
1,
2,
- frame_rx,subframe_rx);
+ frame_rx,
+ subframe_rx,
+ 0);
dlsch_unscrambling(&ue->frame_parms,1,ue->dlsch_MCH[0],
ue->dlsch_MCH[0]->harq_processes[0]->G,
@@ -2338,7 +2971,18 @@ void ue_pdsch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, PDSC
eNB_id_i = eNB_id+1;
i_mod = 0;
}
-
+
+ //TM7 UE specific channel estimation here!!!
+ if (ue->transmission_mode[eNB_id]==7) {
+ if (ue->frame_parms.Ncp==0) {
+ if ((m==3) || (m==6) || (m==9) || (m==12))
+ //LOG_D(PHY,"[UE %d] dlsch->active in subframe %d => %d, l=%d\n",phy_vars_ue->Mod_id,subframe_rx,phy_vars_ue->dlsch_ue[eNB_id][0]->active, l);
+ lte_dl_bf_channel_estimation(ue,eNB_id,0,subframe_rx*2+(m>6?1:0),5,m);
+ } else {
+ LOG_E(PHY,"[UE %d]Beamforming channel estimation not supported yet for TM7 extented CP.\n",ue->Mod_id);
+ }
+ }
+
if ((m==s0) && (m<4))
first_symbol_flag = 1;
else
@@ -2387,6 +3031,7 @@ void process_rar(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, runmode_t mo
timing_advance = mac_xface->ue_process_rar(ue->Mod_id,
ue->CC_id,
frame_rx,
+ ue->prach_resources[eNB_id]->ra_RNTI,
dlsch0->harq_processes[0]->b,
&ue->pdcch_vars[eNB_id]->crnti,
ue->prach_resources[eNB_id]->ra_PreambleIndex);
@@ -2510,7 +3155,9 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
dlsch0->harq_processes[harq_pid]->Qm,
dlsch0->harq_processes[harq_pid]->Nl,
ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
- frame_rx,subframe_rx);
+ frame_rx,
+ subframe_rx,
+ ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]);
start_meas(&ue->dlsch_unscrambling_stats);
dlsch_unscrambling(&ue->frame_parms,
0,
@@ -2530,7 +3177,7 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
subframe_rx,
harq_pid,
pdsch==PDSCH?1:0,
- dlsch0->harq_processes[harq_pid]->nb_rb>10?1:0);
+ dlsch0->harq_processes[harq_pid]->TBS>256?1:0);
stop_meas(&ue->dlsch_decoding_stats);
}
@@ -2547,22 +3194,27 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
if (ret == (1+dlsch0->max_turbo_iterations)) {
*dlsch_errors=*dlsch_errors+1;
-
+ if(dlsch0->rnti != 0xffff)
+ {
LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d,TBS %d)\n",
ue->Mod_id,dlsch0->rnti,
harq_pid,frame_rx,subframe_rx,
dlsch0->harq_processes[harq_pid]->rvidx,
dlsch0->harq_processes[harq_pid]->mcs,
dlsch0->harq_processes[harq_pid]->TBS);
+ }
} else {
+ if(dlsch0->rnti != 0xffff)
+ {
LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d: Received DLSCH (rv %d,mcs %d,TBS %d)\n",
ue->Mod_id,dlsch0->rnti,
harq_pid,frame_rx,subframe_rx,
dlsch0->harq_processes[harq_pid]->rvidx,
dlsch0->harq_processes[harq_pid]->mcs,
dlsch0->harq_processes[harq_pid]->TBS);
+ }
#ifdef DEBUG_DLSCH
int j;
@@ -2701,11 +3353,19 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
l2 = (ue->frame_parms.symbols_per_tti/2)-1;
}
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- // RX processing of symbols l=1...l2 (l=0 is done in last scheduling epoch)
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- for (l=1; l<=l2; l++) {
+ int prev_subframe_rx = (subframe_rx - 1)<0? 9: (subframe_rx - 1);
+ if (subframe_select(&ue->frame_parms,prev_subframe_rx) != SF_DL) {
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // RX processing of symbols l=0...l2
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ l=0;
+ } else {
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // RX processing of symbols l=1...l2 (l=0 is done in last scheduling epoch)
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ l=1;
+ }
+ for (; l<=l2; l++) {
if (abstraction_flag == 0) {
start_meas(&ue->ofdm_demod_stats);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN);
@@ -2751,6 +3411,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
// do procedures for C-RNTI
if (ue->dlsch[eNB_id][0]->active == 1) {
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN);
ue_pdsch_procedures(ue,
proc,
eNB_id,
@@ -2760,9 +3421,11 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
ue->frame_parms.symbols_per_tti>>1,
abstraction_flag);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT);
}
// do procedures for SI-RNTI
if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) {
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN);
ue_pdsch_procedures(ue,
proc,
eNB_id,
@@ -2772,10 +3435,12 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
ue->frame_parms.symbols_per_tti>>1,
abstraction_flag);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT);
}
// do procedures for SI-RNTI
if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) {
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN);
ue_pdsch_procedures(ue,
proc,
eNB_id,
@@ -2785,10 +3450,12 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
ue->frame_parms.symbols_per_tti>>1,
abstraction_flag);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT);
}
// do procedures for RA-RNTI
if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) {
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN);
ue_pdsch_procedures(ue,
proc,
eNB_id,
@@ -2798,6 +3465,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
ue->frame_parms.symbols_per_tti>>1,
abstraction_flag);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT);
}
if (subframe_select(&ue->frame_parms,subframe_rx) != SF_S) { // do front-end processing for second slot, and first symbol of next subframe
@@ -2818,13 +3486,18 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
ue_measurement_procedures(l-1,ue,proc,eNB_id,abstraction_flag,mode);
} // for l=1..l2
- // do first symbol of next subframe for channel estimation
- slot_fep(ue,
- 0,
- (2+(subframe_rx<<1))%20,
- ue->rx_offset,
- 0,
- 0);
+
+ // do first symbol of next downlink subframe for channel estimation
+ int next_subframe_rx = (1+subframe_rx)%10;
+ if (subframe_select(&ue->frame_parms,next_subframe_rx) != SF_UL)
+ {
+ slot_fep(ue,
+ 0,
+ (next_subframe_rx<<1),
+ ue->rx_offset,
+ 0,
+ 0);
+ }
} // not an S-subframe
// run pbch procedures if subframe is 0
@@ -2833,6 +3506,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
// do procedures for C-RNTI
if (ue->dlsch[eNB_id][0]->active == 1) {
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN);
ue_pdsch_procedures(ue,
proc,
eNB_id,
@@ -2851,7 +3525,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
&ue->dlsch_errors[eNB_id],
mode,
abstraction_flag);
-
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT);
}
else {
@@ -2944,6 +3618,13 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n",
ue->Mod_id,frame_rx,ue->total_TBS[eNB_id],
ue->total_TBS_last[eNB_id],(float) ue->bitrate[eNB_id]/1000.0);
+
+ #if UE_AUTOTEST_TRACE
+ if ((frame_rx % 100 == 0)) {
+ LOG_I(PHY,"[UE %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[eNB_id]/1000.0, frame_rx);
+ }
+ #endif
+
}
@@ -3077,12 +3758,14 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,u
if (ue->mac_enabled==1) {
if (slot==0) {
- ret = mac_xface->ue_scheduler(ue->Mod_id,
- frame_tx,
- subframe_rx,
- subframe_select(&ue->frame_parms,subframe_tx),
- eNB_id,
- 0/*FIXME CC_id*/);
+ ret = mac_xface->ue_scheduler(ue->Mod_id,
+ frame_rx,
+ subframe_rx,
+ frame_tx,
+ subframe_tx,
+ subframe_select(&ue->frame_parms,subframe_tx),
+ eNB_id,
+ 0/*FIXME CC_id*/);
if (ret == CONNECTION_LOST) {
LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",ue->Mod_id,
diff --git a/openair1/SCHED/pucch_pc.c b/openair1/SCHED/pucch_pc.c
index 5afd57e6a0..2795fe65a9 100644
--- a/openair1/SCHED/pucch_pc.c
+++ b/openair1/SCHED/pucch_pc.c
@@ -88,7 +88,7 @@ int8_t pucch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t subframe,ui
}
if (pucch_fmt!=pucch_format1) {
- LOG_I(PHY,"[UE %d][PDSCH %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB, g_pucch %d dB\n",
+ LOG_D(PHY,"[UE %d][PDSCH %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB, g_pucch %d dB\n",
ue->Mod_id,
ue->dlsch[eNB_id][0]->rnti,proc->frame_tx,subframe,
Po_PUCCH,
@@ -96,7 +96,7 @@ int8_t pucch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t subframe,ui
get_PL(ue->Mod_id,ue->CC_id,eNB_id),
ue->dlsch[eNB_id][0]->g_pucch);
} else {
- LOG_I(PHY,"[UE %d][SR %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB g_pucch %d dB\n",
+ LOG_D(PHY,"[UE %d][SR %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB g_pucch %d dB\n",
ue->Mod_id,
ue->dlsch[eNB_id][0]->rnti,proc->frame_tx,subframe,
Po_PUCCH,
diff --git a/openair1/SCHED/srs_pc.c b/openair1/SCHED/srs_pc.c
new file mode 100644
index 0000000000..98049b2ed0
--- /dev/null
+++ b/openair1/SCHED/srs_pc.c
@@ -0,0 +1,100 @@
+/*
+ * 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.0 (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 srs_pc.c
+ * \brief Implementation of UE SRS Power Control procedures from 36.213 LTE specifications (Section
+ * \author H. Bilel
+ * \date 2016
+ * \version 0.1
+ * \company TCL
+ * \email: haithem.bilel@alcatelOneTouch.com
+ * \note
+ * \warning
+ */
+
+#include "PHY/defs.h"
+#include "PHY/LTE_TRANSPORT/proto.h"
+#include "PHY/extern.h"
+
+void srs_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t *pnb_rb_srs, uint8_t abstraction_flag)
+{
+
+ int16_t PL;
+ int8_t p0_NominalPUSCH;
+ int8_t p0_UE_PUSCH;
+ int8_t Psrs_offset;
+ int16_t P_srs;
+ int16_t f_pusch;
+ uint8_t alpha;
+ uint8_t Msrs = 0;
+
+
+ SOUNDINGRS_UL_CONFIG_DEDICATED *psoundingrs_ul_config_dedicated = &ue->soundingrs_ul_config_dedicated[eNB_id];
+ LTE_DL_FRAME_PARMS *pframe_parms = &ue->frame_parms;
+
+ uint8_t Bsrs = psoundingrs_ul_config_dedicated->srs_Bandwidth;
+ uint8_t Csrs = pframe_parms->soundingrs_ul_config_common.srs_BandwidthConfig;
+ LOG_D(PHY," SRS Power Control; AbsSubframe %d.%d, eNB_id %d, N_RB_UL %d, srs_Bandwidth %d, srs_BandwidthConfig %d \n",proc->frame_tx,proc->subframe_tx,eNB_id,pframe_parms->N_RB_UL,Bsrs,Csrs);
+
+ if (pframe_parms->N_RB_UL < 41)
+ {
+ Msrs = Nb_6_40[Csrs][Bsrs];
+ }
+ else if (pframe_parms->N_RB_UL < 61)
+ {
+ Msrs = Nb_41_60[Csrs][Bsrs];
+ }
+ else if (pframe_parms->N_RB_UL < 81)
+ {
+ Msrs = Nb_61_80[Csrs][Bsrs];
+ }
+ else if (pframe_parms->N_RB_UL <111)
+ {
+ Msrs = Nb_81_110[Csrs][Bsrs];
+ }
+
+ // SRS Power control 36.213 5.1.3.1
+ // P_srs = P_srs_offset+ 10log10(Msrs) + P_opusch(j) + alpha*PL + f(i))
+
+ p0_NominalPUSCH = ue->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
+ p0_UE_PUSCH = ue->ul_power_control_dedicated[eNB_id].p0_UE_PUSCH;
+ Psrs_offset = (ue->ul_power_control_dedicated[eNB_id].pSRS_Offset - 3);
+
+
+ f_pusch = ue->ulsch[eNB_id]->f_pusch;
+ alpha = alpha_lut[ue->frame_parms.ul_power_control_config_common.alpha];
+ PL = get_PL(ue->Mod_id,ue->CC_id,eNB_id);
+
+ LOG_D(PHY," SRS Power Control; eNB_id %d, p0_NominalPUSCH %d, p0_UE_PUSCH %d, alpha %d \n",eNB_id,p0_NominalPUSCH,p0_UE_PUSCH,alpha);
+ LOG_D(PHY," SRS Power Control; eNB_id %d, pSRS_Offset[dB] %d, Msrs %d, PL %d, f_pusch %d \n",eNB_id,Psrs_offset,Msrs,PL,f_pusch);
+
+ P_srs = (p0_NominalPUSCH + p0_UE_PUSCH) + Psrs_offset + f_pusch;
+ P_srs += (((int32_t)alpha * (int32_t)PL) + hundred_times_log10_NPRB[Msrs-1])/100 ;
+
+ ue->ulsch[eNB_id]->Po_SRS = P_srs;
+ if(ue->ulsch[eNB_id]->Po_SRS > ue->tx_power_max_dBm)
+ {
+ ue->ulsch[eNB_id]->Po_SRS = ue->tx_power_max_dBm;
+ }
+
+ pnb_rb_srs[0] = Msrs;
+ LOG_D(PHY," SRS Power Control; eNB_id %d, Psrs_pc[dBm] %d, Pcmax[dBm] %d, Psrs[dBm] %d\n",eNB_id,P_srs,ue->tx_power_max_dBm,ue->ulsch[eNB_id]->Po_SRS);
+}
diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c
index 96c533bde5..f9a8acfa85 100644
--- a/openair1/SIMULATION/LTE_PHY/dlsim.c
+++ b/openair1/SIMULATION/LTE_PHY/dlsim.c
@@ -275,6 +275,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
case 1:
case 2:
+
+ case 7:
if (common_flag == 0) {
if (eNB->frame_parms.frame_type == TDD) {
@@ -403,7 +405,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
SI_RNTI,
0,
P_RNTI,
- eNB->UE_stats[0].DL_pmi_single);
+ eNB->UE_stats[0].DL_pmi_single,
+ transmission_mode>=7?transmission_mode:0);
*num_dci = *num_dci+1;
*num_ue_spec_dci = *num_ue_spec_dci+1;
@@ -543,7 +546,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
SI_RNTI,
0,
P_RNTI,
- eNB->UE_stats[0].DL_pmi_single);
+ eNB->UE_stats[0].DL_pmi_single,
+ transmission_mode>=7?transmission_mode:0);
*num_common_dci=*num_common_dci+1;
*num_dci = *num_dci + 1;
@@ -710,7 +714,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
SI_RNTI,
0,
P_RNTI,
- eNB->UE_stats[0].DL_pmi_single);
+ eNB->UE_stats[0].DL_pmi_single,
+ transmission_mode>=7?transmission_mode:0);
*num_dci = *num_dci + 1;
*num_ue_spec_dci = *num_ue_spec_dci + 1;
@@ -850,7 +855,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
SI_RNTI,
0,
P_RNTI,
- eNB->UE_stats[0].DL_pmi_single);
+ eNB->UE_stats[0].DL_pmi_single,
+ transmission_mode>=7?transmission_mode:0);
*num_common_dci = *num_common_dci + 1;
*num_dci = *num_dci + 1;
@@ -1018,7 +1024,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
SI_RNTI,
0,
P_RNTI,
- eNB->UE_stats[0].DL_pmi_single);
+ eNB->UE_stats[0].DL_pmi_single,
+ transmission_mode>=7?transmission_mode:0);
*num_dci = *num_dci + 1;
*num_ue_spec_dci = *num_ue_spec_dci + 1;
@@ -1158,7 +1165,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
SI_RNTI,
0,
P_RNTI,
- eNB->UE_stats[0].DL_pmi_single);
+ eNB->UE_stats[0].DL_pmi_single,
+ transmission_mode>=7?transmission_mode:0);
*num_common_dci = *num_common_dci + 1;
*num_dci = *num_dci + 1;
@@ -1187,7 +1195,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
SI_RNTI,
0,
P_RNTI,
- eNB->UE_stats[k].DL_pmi_single);
+ eNB->UE_stats[k].DL_pmi_single,
+ transmission_mode>=7?transmission_mode:0);
dump_dci(&eNB->frame_parms,&dci_alloc[*num_dci]);
*num_ue_spec_dci = *num_ue_spec_dci + 1;
@@ -1252,6 +1261,7 @@ int main(int argc, char **argv)
int c;
int k,i,aa;
+ int re;
int s,Kr,Kr_bytes;
@@ -1268,7 +1278,7 @@ int main(int argc, char **argv)
double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel
- uint8_t extended_prefix_flag=0,transmission_mode=1,n_tx=1,n_rx=2;
+ uint8_t extended_prefix_flag=0,transmission_mode=1,n_tx_port=1,n_tx_phy=1,n_rx=2;
uint16_t Nid_cell=0;
int eNB_id = 0;
@@ -1409,7 +1419,7 @@ int main(int argc, char **argv)
// num_layers = 1;
perfect_ce = 0;
- while ((c = getopt (argc, argv, "ahdpZDe:Em:n:o:s:f:t:c:g:r:F:x:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:Pl:WXY")) != -1) {
+ while ((c = getopt (argc, argv, "ahdpZDe:Em:n:o:s:f:t:c:g:r:F:x:q:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:Pl:WXY")) != -1) {
switch (c) {
case 'a':
awgn_flag = 1;
@@ -1610,7 +1620,7 @@ int main(int argc, char **argv)
dual_stream_UE=1;
UE->use_ia_receiver = 1;
- if ((n_tx!=2) || (transmission_mode!=5)) {
+ if ((n_tx_port!=2) || (transmission_mode!=5)) {
msg("IA receiver only supported for TM5!");
exit(-1);
}
@@ -1631,6 +1641,17 @@ int main(int argc, char **argv)
print_perf=1;
break;
+ case 'q':
+ n_tx_port=atoi(optarg);
+
+ if ((n_tx_port==0) || ((n_tx_port>2))) {
+ msg("Unsupported number of cell specific antennas ports %d\n",n_tx_port);
+ exit(-1);
+ }
+
+ break;
+
+
case 'x':
transmission_mode=atoi(optarg);
@@ -1639,25 +1660,37 @@ int main(int argc, char **argv)
(transmission_mode!=3) &&
(transmission_mode!=4) &&
(transmission_mode!=5) &&
- (transmission_mode!=6)) {
+ (transmission_mode!=6) &&
+ (transmission_mode!=7)) {
msg("Unsupported transmission mode %d\n",transmission_mode);
exit(-1);
}
- if (transmission_mode>1) {
- n_tx = 2;
+ if (transmission_mode>1 && transmission_mode<7) {
+ n_tx_port = 2;
}
break;
case 'y':
- n_tx=atoi(optarg);
+ n_tx_phy=atoi(optarg);
- if ((n_tx==0) || (n_tx>2)) {
- msg("Unsupported number of tx antennas %d\n",n_tx);
+ if (n_tx_phy < n_tx_port) {
+ msg("n_tx_phy mush not be smaller than n_tx_port");
exit(-1);
}
+ if ((transmission_mode>1 && transmission_mode<7) && n_tx_port<2) {
+ msg("n_tx_port must be >1 for transmission_mode %d\n",transmission_mode);
+ exit(-1);
+ }
+
+ if (transmission_mode==7 && (n_tx_phy!=1 && n_tx_phy!=2 && n_tx_phy!=4 && n_tx_phy!=8 && n_tx_phy!=16 && n_tx_phy!=64 && n_tx_phy!=128)) {
+ msg("Physical number of antennas not supported for TM7.\n");
+ exit(-1);
+ }
+
+ break;
break;
case 'X':
@@ -1686,7 +1719,7 @@ int main(int argc, char **argv)
case 'h':
default:
- printf("%s -h(elp) -a(wgn on) -d(ci decoding on) -p(extended prefix on) -m mcs1 -M mcs2 -n n_frames -s snr0 -x transmission mode (1,2,5,6) -y TXant -z RXant -I trch_file\n",argv[0]);
+ printf("%s -h(elp) -a(wgn on) -d(ci decoding on) -p(extended prefix on) -m mcs1 -M mcs2 -n n_frames -s snr0 -x transmission mode (1,2,5,6,7) -y TXant -z RXant -I trch_file\n",argv[0]);
printf("-h This message\n");
printf("-a Use AWGN channel and not multipath\n");
printf("-c Number of PDCCH symbols\n");
@@ -1701,7 +1734,8 @@ int main(int argc, char **argv)
printf("-r ressource block allocation (see section 7.1.6.3 in 36.213\n");
printf("-g [A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'), Rice8('L'), Rice1('M')\n");
printf("-F forgetting factor (0 new channel every trial, 1 channel constant\n");
- printf("-x Transmission mode (1,2,6 for the moment)\n");
+ printf("-x Transmission mode (1,2,6,7 for the moment)\n");
+ printf("-q Number of TX antennas ports used in eNB\n");
printf("-y Number of TX antennas used in eNB\n");
printf("-z Number of RX antennas used in UE\n");
printf("-t MCS of interfering UE\n");
@@ -1740,9 +1774,6 @@ int main(int argc, char **argv)
} else
NB_RB = 4;
- if ((transmission_mode > 1) && (n_tx != 2))
- printf("n_tx must be >1 for transmission_mode %d\n",transmission_mode);
-
if (xforms==1) {
fl_initialize (&argc, argv, NULL, 0, 0);
form_ue = create_lte_phy_scope_ue();
@@ -1762,7 +1793,8 @@ int main(int argc, char **argv)
printf("dual_stream_UE=%d\n", dual_stream_UE);
}
- lte_param_init(n_tx,
+ lte_param_init(n_tx_port,
+ n_tx_phy,
n_rx,
transmission_mode,
extended_prefix_flag,
@@ -1774,6 +1806,12 @@ int main(int argc, char **argv)
osf,
perfect_ce);
+ if ((transmission_mode==1) || (transmission_mode==7)) {
+ for (aa=0; aaframe_parms.nb_antennas_tx; aa++)
+ for (re=0; reframe_parms.ofdm_symbol_size; re++)
+ eNB->common_vars.beam_weights[0][0][aa][re] = 0x00007fff/eNB->frame_parms.nb_antennas_tx;
+ }
+
eNB->mac_enabled=1;
if (two_thread_flag == 0) {
eNB->te = dlsch_encoding;
@@ -1795,7 +1833,7 @@ int main(int argc, char **argv)
printf("Setting mcs2 = %d\n",mcs2);
printf("NPRB = %d\n",NB_RB);
printf("n_frames = %d\n",n_frames);
- printf("Transmission mode %d with %dx%d antenna configuration, Extended Prefix %d\n",transmission_mode,n_tx,n_rx,extended_prefix_flag);
+ printf("Transmission mode %d with %dx%d antenna configuration, Extended Prefix %d\n",transmission_mode,n_tx_phy,n_rx,extended_prefix_flag);
snr1 = snr0+snr_int;
printf("SNR0 %f, SNR1 %f\n",snr0,snr1);
@@ -1830,7 +1868,7 @@ int main(int argc, char **argv)
//char dirname[FILENAME_MAX];
//sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname );
sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv",
- N_RB_DL,mcs1,n_tx,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode);
+ N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode);
//mkdir(dirname,0777);
time_meas_fd = fopen(time_meas_fname,"w");
if (time_meas_fd==NULL) {
@@ -2042,7 +2080,7 @@ int main(int argc, char **argv)
for (k=0; kdlsch[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0);
+ eNB->dlsch[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0,&eNB->frame_parms);
if (!eNB->dlsch[k][i]) {
printf("Can't get eNB dlsch structures\n");
@@ -2065,7 +2103,7 @@ int main(int argc, char **argv)
}
// structure for SIC at UE
- UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0);
+ UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0,&eNB->frame_parms);
if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) {
@@ -2159,7 +2197,9 @@ int main(int argc, char **argv)
get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs),
eNB->dlsch[0][0]->harq_processes[0]->Nl,
num_pdcch_symbols,
- 0,subframe);
+ 0,
+ subframe,
+ transmission_mode>=7?transmission_mode:0);
uncoded_ber_bit = (short*) malloc(sizeof(short)*coded_bits_per_codeword);
printf("uncoded_ber_bit=%p\n",uncoded_ber_bit);
@@ -2354,6 +2394,7 @@ int main(int argc, char **argv)
start_meas(&eNB->ofdm_mod_stats);
+ /*
do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id],
eNB->common_vars.txdata[eNB_id],
(subframe*2),
@@ -2363,7 +2404,19 @@ int main(int argc, char **argv)
eNB->common_vars.txdata[eNB_id],
(subframe*2)+1,
&eNB->frame_parms);
-
+ */
+
+ do_OFDM_mod_symbol(&eNB->common_vars,
+ eNB_id,
+ (subframe*2),
+ &eNB->frame_parms);
+
+ do_OFDM_mod_symbol(&eNB->common_vars,
+ eNB_id,
+ (subframe*2)+1,
+ &eNB->frame_parms);
+
+
stop_meas(&eNB->ofdm_mod_stats);
// generate next subframe for channel estimation
@@ -2393,11 +2446,15 @@ int main(int argc, char **argv)
if (n_frames==1) {
printf("tx_lev = %d (%d dB)\n",tx_lev,tx_lev_dB);
- write_output("txsig0.m","txs0", &eNB->common_vars.txdata[eNB_id][0][subframe* eNB->frame_parms.samples_per_tti],
- eNB->frame_parms.samples_per_tti,1,1);
- write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],
- nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+ write_output("txsig0.m","txs0", &eNB->common_vars.txdata[eNB_id][0][subframe* eNB->frame_parms.samples_per_tti], eNB->frame_parms.samples_per_tti,1,1);
+
+ if (transmission_mode<7) {
+ write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+ } else if (transmission_mode == 7) {
+ write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][5][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+ write_output("txsigF0_BF.m","txsF0_BF", &eNB->common_vars.txdataF_BF[eNB_id][0][0],eNB->frame_parms.ofdm_symbol_size,1,1);
+ }
}
}
diff --git a/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c
new file mode 100644
index 0000000000..66dea185de
--- /dev/null
+++ b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c
@@ -0,0 +1,4326 @@
+ /******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
+
+ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+ *******************************************************************************/
+
+/*! \file dlsim.c
+ \brief Top-level DL simulator
+ \author R. Knopp
+ \date 2011 - 2014
+ \version 0.1
+ \company Eurecom
+ \email: knopp@eurecom.fr
+ \note
+ \warning
+*/
+
+#include
+#include
+#include
+#include
+#include
+
+#include "SIMULATION/TOOLS/defs.h"
+#include "PHY/types.h"
+#include "PHY/defs.h"
+#include "PHY/vars.h"
+
+#include "SCHED/defs.h"
+#include "SCHED/vars.h"
+#include "LAYER2/MAC/vars.h"
+
+#include "OCG_vars.h"
+#include "UTIL/LOG/log.h"
+#include "UTIL/LISTS/list.h"
+
+#include "unitary_defs.h"
+
+extern unsigned int dlsch_tbs25[27][25],TBStable[27][110];
+extern unsigned char offset_mumimo_llr_drange_fix;
+
+#include "PHY/TOOLS/lte_phy_scope.h"
+
+PHY_VARS_eNB *eNB;
+PHY_VARS_UE *UE;
+
+int otg_enabled=0;
+/*the following parameters are used to control the processing times calculations*/
+double t_tx_max = -1000000000; /*!< \brief initial max process time for tx */
+double t_rx_max = -1000000000; /*!< \brief initial max process time for rx */
+double t_tx_min = 1000000000; /*!< \brief initial min process time for tx */
+double t_rx_min = 1000000000; /*!< \brief initial min process time for rx */
+int n_tx_dropped = 0; /*!< \brief initial max process time for tx */
+int n_rx_dropped = 0; /*!< \brief initial max process time for rx */
+
+void handler(int sig)
+{
+ void *array[10];
+ size_t size;
+
+ // get void*'s for all entries on the stack
+ size = backtrace(array, 10);
+
+ // print out all the frames to stderr
+ fprintf(stderr, "Error: signal %d:\n", sig);
+ backtrace_symbols_fd(array, size, 2);
+ exit(1);
+}
+
+
+
+//DCI2_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2_2A[2];
+
+DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2_1E[2];
+uint64_t DLSCH_alloc_pdu_1[2];
+
+#define UL_RB_ALLOC 0x1ff;
+#define CCCH_RB_ALLOC computeRIV(eNB->frame_parms.N_RB_UL,0,2)
+//#define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13
+//#define DLSCH_RB_ALLOC 0x0001
+
+int main(int argc, char **argv)
+{
+
+ int c;
+ int k,i,j,aa,aarx,aatx;
+ int re;
+
+ int s,Kr,Kr_bytes;
+
+ double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1,rate;
+ double snr_step=1,input_snr_step=1, snr_int=30;
+
+ LTE_DL_FRAME_PARMS *frame_parms;
+ double **s_re,**s_im,**r_re,**r_im;
+ double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel
+ double iqim=0.0;
+
+ uint8_t extended_prefix_flag=0,transmission_mode=1,n_tx_port=1,n_tx_phy=1,n_rx=1;
+ uint16_t Nid_cell=0;
+ int32_t **cell_spec_bf_weights;
+ int32_t *ue_spec_bf_weights;
+
+ int eNB_id = 0, eNB_id_i = 1;
+ unsigned char mcs1=0,mcs2=0,mcs_i=0,dual_stream_UE = 0,awgn_flag=0,round,dci_flag=0;
+ unsigned char i_mod = 2;
+ unsigned short NB_RB;
+ unsigned char Ns,l,m;
+ uint16_t tdd_config=3;
+ uint16_t n_rnti=0x1234;
+ int n_users = 1;
+
+ SCM_t channel_model=Rayleigh1;
+ // unsigned char *input_data,*decoded_output;
+
+ unsigned char *input_buffer0[2],*input_buffer1[2];
+ unsigned short input_buffer_length0,input_buffer_length1;
+ unsigned int ret;
+ unsigned int coded_bits_per_codeword=0,nsymb,dci_cnt,tbs=0;
+
+ unsigned int tx_lev=0,tx_lev_dB=0,trials,errs[4]= {0,0,0,0},errs2[4]= {0,0,0,0},round_trials[4]= {0,0,0,0},dci_errors=0,dlsch_active=0;//,num_layers;
+ int re_allocated;
+ char fname[32],vname[32];
+ FILE *bler_fd;
+ char bler_fname[256];
+ FILE *time_meas_fd;
+ char time_meas_fname[256];
+ // FILE *tikz_fd;
+ // char tikz_fname[256];
+
+ FILE *input_trch_fd=NULL;
+ unsigned char input_trch_file=0;
+ FILE *input_fd=NULL;
+ unsigned char input_file=0;
+ // char input_val_str[50],input_val_str2[50];
+
+ char input_trch_val[16];
+ double channelx,channely;
+
+ unsigned char pbch_pdu[6];
+
+ DCI_ALLOC_t dci_alloc[8],dci_alloc_rx[8];
+ int num_common_dci=0,num_ue_spec_dci=0,num_dci=0;
+
+ // FILE *rx_frame_file;
+
+ int n_frames;
+ int n_ch_rlz = 1;
+ channel_desc_t *eNB2UE[4];
+ uint8_t num_pdcch_symbols=1,num_pdcch_symbols_2=0;
+ uint8_t pilot1,pilot2,pilot3;
+ uint8_t rx_sample_offset = 0;
+ //char stats_buffer[4096];
+ //int len;
+ uint8_t num_rounds = 4;//,fix_rounds=0;
+ uint8_t subframe=7;
+ int u;
+ int n=0;
+ int abstx=0;
+ int iii;
+ FILE *csv_fd=NULL;
+ char csv_fname[512];
+ int ch_realization;
+ int pmi_feedback=0;
+ int hold_channel=0;
+
+ // void *data;
+ // int ii;
+ // int bler;
+ double blerr[4],uncoded_ber,avg_ber;
+ short *uncoded_ber_bit=NULL;
+ uint8_t N_RB_DL=25,osf=1;
+ frame_t frame_type = FDD;
+ int xforms=0;
+ FD_lte_phy_scope_ue *form_ue = NULL;
+ char title[255];
+ uint32_t DLSCH_RB_ALLOC = 0x1fff;
+ int numCCE=0;
+ int dci_length_bytes=0,dci_length=0;
+ //double channel_bandwidth = 5.0, sampling_rate=7.68;
+ int common_flag=0,TPC=0;
+
+ double cpu_freq_GHz;
+ // time_stats_t ts;//,sts,usts;
+ int avg_iter,iter_trials;
+ int rballocset=0;
+ int print_perf=0;
+ int test_perf=0;
+ int dump_table=0;
+ int llr8_flag=0;
+
+ double effective_rate=0.0;
+ char channel_model_input[10]="I";
+
+ int TB0_active = 1;
+ uint32_t perfect_ce = 0;
+
+ // LTE_DL_UE_HARQ_t *dlsch0_ue_harq;
+ // LTE_DL_eNB_HARQ_t *dlsch0_eNB_harq;
+ uint8_t Kmimo;
+ uint8_t ue_category=4;
+ uint32_t Nsoft;
+
+
+
+ int CCE_table[800];
+
+ int threequarter_fs=0;
+
+ opp_enabled=1; // to enable the time meas
+
+#if defined(__arm__)
+ FILE *proc_fd = NULL;
+ char buf[64];
+
+ proc_fd = fopen("/sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq", "r");
+ if(!proc_fd)
+ printf("cannot open /sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq");
+ else {
+ while(fgets(buf, 63, proc_fd))
+ printf("%s", buf);
+ }
+ fclose(proc_fd);
+ cpu_freq_GHz = ((double)atof(buf))/1e6;
+#else
+ cpu_freq_GHz = get_cpu_freq_GHz();
+#endif
+ printf("Detected cpu_freq %f GHz\n",cpu_freq_GHz);
+
+ //signal(SIGSEGV, handler);
+ //signal(SIGABRT, handler);
+
+ logInit();
+
+ // default parameters
+ n_frames = 1000;
+ snr0 = 0;
+ // num_layers = 1;
+ perfect_ce = 0;
+
+ while ((c = getopt (argc, argv, "ahdpZDe:Em:n:o:s:f:t:c:g:r:F:x:p:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:PLl:XY")) != -1) {
+ switch (c) {
+ case 'a':
+ awgn_flag = 1;
+ channel_model = AWGN;
+ break;
+
+ case 'A':
+ abstx = 1;
+ break;
+
+ case 'b':
+ tdd_config=atoi(optarg);
+ break;
+
+ case 'B':
+ N_RB_DL=atoi(optarg);
+ break;
+
+ case 'c':
+ num_pdcch_symbols=atoi(optarg);
+ break;
+
+ case 'C':
+ Nid_cell = atoi(optarg);
+ break;
+
+ case 'd':
+ dci_flag = 1;
+ break;
+
+ case 'D':
+ frame_type=TDD;
+ break;
+
+ case 'e':
+ num_rounds=1;
+ common_flag = 1;
+ TPC = atoi(optarg);
+ break;
+
+ case 'E':
+ threequarter_fs=1;
+ break;
+
+ case 'f':
+ input_snr_step= atof(optarg);
+ break;
+
+ case 'F':
+ forgetting_factor = atof(optarg);
+ break;
+
+ case 'i':
+ input_fd = fopen(optarg,"r");
+ input_file=1;
+ dci_flag = 1;
+ break;
+
+ case 'I':
+ input_trch_fd = fopen(optarg,"r");
+ input_trch_file=1;
+ break;
+
+ case 'L':
+ llr8_flag=1;
+ break;
+
+ case 'l':
+ offset_mumimo_llr_drange_fix=atoi(optarg);
+ break;
+
+ case 'm':
+ mcs1 = atoi(optarg);
+ break;
+
+ case 'M':
+ mcs2 = atoi(optarg);
+ break;
+
+ case 'O':
+ test_perf=atoi(optarg);
+ //print_perf =1;
+ break;
+
+ case 't':
+ mcs_i = atoi(optarg);
+ i_mod = get_Qm(mcs_i);
+ break;
+
+ case 'n':
+ n_frames = atoi(optarg);
+ break;
+
+ case 'o':
+ rx_sample_offset = atoi(optarg);
+ break;
+
+ case 'r':
+ DLSCH_RB_ALLOC = atoi(optarg);
+ rballocset = 1;
+ break;
+
+ case 's':
+ snr0 = atof(optarg);
+ break;
+
+ case 'w':
+ snr_int = atof(optarg);
+ break;
+
+ case 'N':
+ n_ch_rlz= atof(optarg);
+ break;
+
+ case 'p':
+ extended_prefix_flag=1;
+ break;
+
+ case 'g':
+ memcpy(channel_model_input,optarg,10);
+
+ switch((char)*optarg) {
+ case 'A':
+ channel_model=SCM_A;
+ break;
+
+ case 'B':
+ channel_model=SCM_B;
+ break;
+
+ case 'C':
+ channel_model=SCM_C;
+ break;
+
+ case 'D':
+ channel_model=SCM_D;
+ break;
+
+ case 'E':
+ channel_model=EPA;
+ break;
+
+ case 'F':
+ channel_model=EVA;
+ break;
+
+ case 'G':
+ channel_model=ETU;
+ break;
+
+ case 'H':
+ channel_model=Rayleigh8;
+ break;
+
+ case 'I':
+ channel_model=Rayleigh1;
+ break;
+
+ case 'J':
+ channel_model=Rayleigh1_corr;
+ break;
+
+ case 'K':
+ channel_model=Rayleigh1_anticorr;
+ break;
+
+ case 'L':
+ channel_model=Rice8;
+ break;
+
+ case 'M':
+ channel_model=Rice1;
+ break;
+
+ case 'N':
+ channel_model=AWGN;
+ break;
+ default:
+ msg("Unsupported channel model!\n");
+ exit(-1);
+ }
+
+ break;
+
+ case 'R':
+ num_rounds=atoi(optarg);
+ break;
+
+ case 'S':
+ subframe=atoi(optarg);
+ break;
+
+ case 'T':
+ n_rnti=atoi(optarg);
+ break;
+
+ case 'u':
+ dual_stream_UE=1;
+ UE->use_ia_receiver = 1;
+
+ if ((n_tx_port!=2) || (transmission_mode!=5)) {
+ msg("IA receiver only supported for TM5!");
+ exit(-1);
+ }
+
+ break;
+
+ case 'v':
+ i_mod = atoi(optarg);
+
+ if (i_mod!=2 && i_mod!=4 && i_mod!=6) {
+ msg("Wrong i_mod %d, should be 2,4 or 6\n",i_mod);
+ exit(-1);
+ }
+
+ break;
+
+ case 'P':
+ print_perf=1;
+ break;
+
+ case 'q':
+ n_tx_port=atoi(optarg);
+
+ if ((n_tx_port==0) || ((n_tx_port>2))) {
+ msg("Unsupported number of cell specific antennas ports %d\n",n_tx_port);
+ exit(-1);
+ }
+
+ break;
+
+
+ case 'x':
+ transmission_mode=atoi(optarg);
+
+ if ((transmission_mode!=1) &&
+ (transmission_mode!=2) &&
+ (transmission_mode!=3) &&
+ (transmission_mode!=4) &&
+ (transmission_mode!=5) &&
+ (transmission_mode!=6) &&
+ (transmission_mode!=7)) {
+ msg("Unsupported transmission mode %d\n",transmission_mode);
+ exit(-1);
+ }
+
+ if (transmission_mode>1 && transmission_mode<7) {
+ n_tx_port = 2;
+ }
+
+ break;
+
+ case 'y':
+ n_tx_phy=atoi(optarg);
+
+ if (transmission_mode>1&&transmission_mode<7) {
+ if(n_tx_phy==1) {
+ msg("n_tx_phy must be >1 for transmission_mode %d\n",transmission_mode);
+ exit(-1);
+ }
+ }
+
+ if (transmission_mode==7 && (n_tx_phy!=1 && n_tx_phy!=2 && n_tx_phy!=4 && n_tx_phy!=8 && n_tx_phy!=16 && n_tx_phy!=64 && n_tx_phy!=128)) {
+ msg("Physical number of antennas not supported for TM7.\n");
+ exit(-1);
+ }
+
+ break;
+
+ case 'X':
+ xforms=1;
+ break;
+
+ case 'Y':
+ perfect_ce=1;
+ break;
+
+ case 'z':
+ n_rx=atoi(optarg);
+
+ if ((n_rx==0) || (n_rx>2)) {
+ msg("Unsupported number of rx antennas %d\n",n_rx);
+ exit(-1);
+ }
+
+ break;
+
+ case 'Z':
+ dump_table=1;
+ break;
+
+
+
+ case 'h':
+ default:
+ printf("%s -h(elp) -a(wgn on) -d(ci decoding on) -p(extended prefix on) -m mcs1 -M mcs2 -n n_frames -s snr0 -x transmission mode (1,2,5,6,7) -y TXant -z RXant -I trch_file\n",argv[0]);
+ printf("-h This message\n");
+ printf("-a Use AWGN channel and not multipath\n");
+ printf("-c Number of PDCCH symbols\n");
+ printf("-m MCS1 for TB 1\n");
+ printf("-M MCS2 for TB 2\n");
+ printf("-d Transmit the DCI and compute its error statistics and the overall throughput\n");
+ printf("-p Use extended prefix mode\n");
+ printf("-n Number of frames to simulate\n");
+ printf("-o Sample offset for receiver\n");
+ printf("-s Starting SNR, runs from SNR to SNR+%.1fdB in steps of %.1fdB. If n_frames is 1 then just SNR is simulated and MATLAB/OCTAVE output is generated\n", snr_int, snr_step);
+ printf("-f step size of SNR, default value is 1.\n");
+ printf("-r ressource block allocation (see section 7.1.6.3 in 36.213\n");
+ printf("-g [A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'), Rice8('L'), Rice1('M')\n");
+ printf("-F forgetting factor (0 new channel every trial, 1 channel constant\n");
+ printf("-x Transmission mode (1,2,6,7 for the moment)\n");
+ printf("-q Number of TX antennas ports used in eNB\n");
+ printf("-y Number of physical TX antennas used in eNB\n");
+ printf("-z Number of RX antennas used in UE\n");
+ printf("-t MCS of interfering UE\n");
+ printf("-R Number of HARQ rounds (fixed)\n");
+ printf("-A Turns on calibration mode for abstraction.\n");
+ printf("-N Determines the number of Channel Realizations in Abstraction mode. Default value is 1. \n");
+ printf("-O Set the percenatge of effective rate to testbench the modem performance (typically 30 and 70, range 1-100) \n");
+ printf("-I Input filename for TrCH data (binary)\n");
+ printf("-u Enables the Interference Aware Receiver for TM5 (default is normal receiver)\n");
+ exit(1);
+ break;
+ }
+ }
+
+ if (common_flag == 0) {
+ switch (N_RB_DL) {
+ case 6:
+ if (rballocset==0) DLSCH_RB_ALLOC = 0x3f;
+ num_pdcch_symbols = 3;
+ break;
+
+ case 25:
+ if (rballocset==0) DLSCH_RB_ALLOC = 0x1fff;
+ break;
+
+ case 50:
+ if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffff;
+ break;
+
+ case 100:
+ if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffffff;
+ break;
+ }
+
+ NB_RB=conv_nprb(0,DLSCH_RB_ALLOC,N_RB_DL);
+ } else
+ NB_RB = 4;
+
+
+ if (xforms==1) {
+ fl_initialize (&argc, argv, NULL, 0, 0);
+ form_ue = create_lte_phy_scope_ue();
+ sprintf (title, "LTE PHY SCOPE eNB");
+ fl_show_form (form_ue->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
+
+ if (!dual_stream_UE==0) {
+ UE->use_ia_receiver = 1;
+ fl_set_button(form_ue->button_0,1);
+ fl_set_object_label(form_ue->button_0, "IA Receiver ON");
+ fl_set_object_color(form_ue->button_0, FL_GREEN, FL_GREEN);
+ }
+ }
+
+ if (transmission_mode==5) {
+ n_users = 2;
+ printf("dual_stream_UE=%d\n", dual_stream_UE);
+ }
+
+ lte_param_init(n_tx_port,n_tx_phy,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,tdd_config,N_RB_DL,threequarter_fs,osf,perfect_ce);
+
+ frame_parms = &eNB->frame_parms;
+
+ /*
+ cell_spec_bf_weights = eNB->common_vars.beam_weights[0][0];
+ for(aa=0;aaofdm_symbol_size;re++) {
+ if (n_tx_phy==1 || n_tx_phy==2)
+ cell_spec_bf_weights[aa][re] = 0x00007fff;
+ else if (n_tx_phy==4 || n_tx_phy==8)
+ cell_spec_bf_weights[aa][re] = 0x00007fff>>1;
+ else if (n_tx_phy==16)
+ cell_spec_bf_weights[aa][re] = 0x00007fff>>2;
+ else if (n_tx_phy==64)
+ cell_spec_bf_weights[aa][re] = 0x00007fff>>4;
+ }
+ }
+
+ if (transmission_mode==7){
+ lte_gold_ue_spec_port5(eNB->lte_gold_uespec_port5_table[0],Nid_cell,n_rnti);
+ lte_gold_ue_spec_port5(UE->lte_gold_uespec_port5_table,Nid_cell,n_rnti);
+ }*/
+
+
+ eNB_id_i = UE->n_connected_eNB;
+
+ printf("Setting mcs1 = %d\n",mcs1);
+ printf("Setting mcs2 = %d\n",mcs2);
+ printf("NPRB = %d\n",NB_RB);
+ printf("n_frames = %d\n",n_frames);
+ printf("Transmission mode %d with %dx%d antenna configuration, Extended Prefix %d\n",transmission_mode,n_tx_phy,n_rx,extended_prefix_flag);
+
+ snr1 = snr0+snr_int;
+ printf("SNR0 %f, SNR1 %f\n",snr0,snr1);
+
+
+ s_re = malloc(n_tx_phy*sizeof(double*));
+ s_im = malloc(n_tx_phy*sizeof(double*));
+ r_re = malloc(2*sizeof(double*));
+ r_im = malloc(2*sizeof(double*));
+ // r_re0 = malloc(2*sizeof(double*));
+ // r_im0 = malloc(2*sizeof(double*));
+
+ nsymb = (eNB->frame_parms.Ncp == 0) ? 14 : 12;
+
+ printf("Channel Model= (%s,%d)\n",channel_model_input, channel_model);
+ printf("SCM-A=%d, SCM-B=%d, SCM-C=%d, SCM-D=%d, EPA=%d, EVA=%d, ETU=%d, Rayleigh8=%d, Rayleigh1=%d, Rayleigh1_corr=%d, Rayleigh1_anticorr=%d, Rice1=%d, Rice8=%d\n",
+ SCM_A, SCM_B, SCM_C, SCM_D, EPA, EVA, ETU, Rayleigh8, Rayleigh1, Rayleigh1_corr, Rayleigh1_anticorr, Rice1, Rice8);
+
+ if(transmission_mode==5)
+ sprintf(bler_fname,"bler_tm%d_chan%d_perfce%d_ntx%d_nrx%d_mcs%d_mcsi%d_u%d_imod%d.csv",transmission_mode,channel_model,perfect_ce,n_tx_phy,n_rx,mcs1,mcs_i,dual_stream_UE,i_mod);
+ else
+ sprintf(bler_fname,"bler_tm%d_chan%d_perfce%d_ntx%d_nrx%d_mcs%d.csv",transmission_mode,channel_model,perfect_ce,n_tx_phy,n_rx,mcs1);
+
+ bler_fd = fopen(bler_fname,"w");
+ if (bler_fd==NULL) {
+ fprintf(stderr,"Cannot create file %s!\n",bler_fname);
+ exit(-1);
+ }
+ fprintf(bler_fd,"SNR; MCS; TBS; rate; err0; trials0; err1; trials1; err2; trials2; err3; trials3; dci_err\n");
+
+ if (test_perf != 0) {
+ char hostname[1024];
+ hostname[1023] = '\0';
+ gethostname(hostname, 1023);
+ printf("Hostname: %s\n", hostname);
+ //char dirname[FILENAME_MAX];
+ //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname );
+ sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv",
+ N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode);
+ //mkdir(dirname,0777);
+ time_meas_fd = fopen(time_meas_fname,"w");
+ if (time_meas_fd==NULL) {
+ fprintf(stderr,"Cannot create file %s!\n",time_meas_fname);
+ exit(-1);
+ }
+ }
+
+ if(abstx) {
+ // CSV file
+ sprintf(csv_fname,"dataout_tx%d_u2%d_mcs%d_chan%d_nsimus%d_R%d.m",transmission_mode,dual_stream_UE,mcs1,channel_model,n_frames,num_rounds);
+ csv_fd = fopen(csv_fname,"w");
+ fprintf(csv_fd,"data_all%d=[",mcs1);
+ if (csv_fd==NULL) {
+ fprintf(stderr,"Cannot create file %s!\n",csv_fname);
+ exit(-1);
+ }
+ }
+
+ /*
+ //sprintf(tikz_fname, "second_bler_tx%d_u2=%d_mcs%d_chan%d_nsimus%d.tex",transmission_mode,dual_stream_UE,mcs,channel_model,n_frames);
+ sprintf(tikz_fname, "second_bler_tx%d_u2%d_mcs%d_chan%d_nsimus%d",transmission_mode,dual_stream_UE,mcs,channel_model,n_frames);
+ tikz_fd = fopen(tikz_fname,"w");
+ //fprintf(tikz_fd,"\\addplot[color=red, mark=o] plot coordinates {");
+ switch (mcs)
+ {
+ case 0:
+ fprintf(tikz_fd,"\\addplot[color=blue, mark=star] plot coordinates {");
+ break;
+ case 1:
+ fprintf(tikz_fd,"\\addplot[color=red, mark=star] plot coordinates {");
+ break;
+ case 2:
+ fprintf(tikz_fd,"\\addplot[color=green, mark=star] plot coordinates {");
+ break;
+ case 3:
+ fprintf(tikz_fd,"\\addplot[color=yellow, mark=star] plot coordinates {");
+ break;
+ case 4:
+ fprintf(tikz_fd,"\\addplot[color=black, mark=star] plot coordinates {");
+ break;
+ case 5:
+ fprintf(tikz_fd,"\\addplot[color=blue, mark=o] plot coordinates {");
+ break;
+ case 6:
+ fprintf(tikz_fd,"\\addplot[color=red, mark=o] plot coordinates {");
+ break;
+ case 7:
+ fprintf(tikz_fd,"\\addplot[color=green, mark=o] plot coordinates {");
+ break;
+ case 8:
+ fprintf(tikz_fd,"\\addplot[color=yellow, mark=o] plot coordinates {");
+ break;
+ case 9:
+ fprintf(tikz_fd,"\\addplot[color=black, mark=o] plot coordinates {");
+ break;
+ case 10:
+ fprintf(tikz_fd,"\\addplot[color=blue, mark=square] plot coordinates {");
+ break;
+ case 11:
+ fprintf(tikz_fd,"\\addplot[color=red, mark=square] plot coordinates {");
+ break;
+ case 12:
+ fprintf(tikz_fd,"\\addplot[color=green, mark=square] plot coordinates {");
+ break;
+ case 13:
+ fprintf(tikz_fd,"\\addplot[color=yellow, mark=square] plot coordinates {");
+ break;
+ case 14:
+ fprintf(tikz_fd,"\\addplot[color=black, mark=square] plot coordinates {");
+ break;
+ case 15:
+ fprintf(tikz_fd,"\\addplot[color=blue, mark=diamond] plot coordinates {");
+ break;
+ case 16:
+ fprintf(tikz_fd,"\\addplot[color=red, mark=diamond] plot coordinates {");
+ break;
+ case 17:
+ fprintf(tikz_fd,"\\addplot[color=green, mark=diamond] plot coordinates {");
+ break;
+ case 18:
+ fprintf(tikz_fd,"\\addplot[color=yellow, mark=diamond] plot coordinates {");
+ break;
+ case 19:
+ fprintf(tikz_fd,"\\addplot[color=black, mark=diamond] plot coordinates {");
+ break;
+ case 20:
+ fprintf(tikz_fd,"\\addplot[color=blue, mark=x] plot coordinates {");
+ break;
+ case 21:
+ fprintf(tikz_fd,"\\addplot[color=red, mark=x] plot coordinates {");
+ break;
+ case 22:
+ fprintf(tikz_fd,"\\addplot[color=green, mark=x] plot coordinates {");
+ break;
+ case 23:
+ fprintf(tikz_fd,"\\addplot[color=yellow, mark=x] plot coordinates {");
+ break;
+ case 24:
+ fprintf(tikz_fd,"\\addplot[color=black, mark=x] plot coordinates {");
+ break;
+ case 25:
+ fprintf(tikz_fd,"\\addplot[color=blue, mark=x] plot coordinates {");
+ break;
+ case 26:
+ fprintf(tikz_fd,"\\addplot[color=red, mark=+] plot coordinates {");
+ break;
+ case 27:
+ fprintf(tikz_fd,"\\addplot[color=green, mark=+] plot coordinates {");
+ break;
+ case 28:
+ fprintf(tikz_fd,"\\addplot[color=yellow, mark=+] plot coordinates {");
+ break;
+ }
+ */
+
+ for (i=0; ipdcch_vars[0]->crnti = n_rnti;
+
+ // Fill in UL_alloc
+ UL_alloc_pdu.type = 0;
+ UL_alloc_pdu.hopping = 0;
+ UL_alloc_pdu.rballoc = UL_RB_ALLOC;
+ UL_alloc_pdu.mcs = 1;
+ UL_alloc_pdu.ndi = 1;
+ UL_alloc_pdu.TPC = 0;
+ UL_alloc_pdu.cqi_req = 1;
+
+ CCCH_alloc_pdu.type = 0;
+ CCCH_alloc_pdu.vrb_type = 0;
+ CCCH_alloc_pdu.rballoc = CCCH_RB_ALLOC;
+ CCCH_alloc_pdu.ndi = 1;
+ CCCH_alloc_pdu.mcs = 1;
+ CCCH_alloc_pdu.harq_pid = 0;
+
+ DLSCH_alloc_pdu2_1E[0].rah = 0;
+ DLSCH_alloc_pdu2_1E[0].rballoc = DLSCH_RB_ALLOC;
+ DLSCH_alloc_pdu2_1E[0].TPC = 0;
+ DLSCH_alloc_pdu2_1E[0].dai = 0;
+ DLSCH_alloc_pdu2_1E[0].harq_pid = 0;
+ //DLSCH_alloc_pdu2_1E[0].tb_swap = 0;
+ DLSCH_alloc_pdu2_1E[0].mcs = mcs1;
+ DLSCH_alloc_pdu2_1E[0].ndi = 1;
+ DLSCH_alloc_pdu2_1E[0].rv = 0;
+ // Forget second codeword
+ DLSCH_alloc_pdu2_1E[0].tpmi = (transmission_mode>=5 ? 5 : 0); // precoding
+ DLSCH_alloc_pdu2_1E[0].dl_power_off = (transmission_mode==5 ? 0 : 1);
+
+ DLSCH_alloc_pdu2_1E[1].rah = 0;
+ DLSCH_alloc_pdu2_1E[1].rballoc = DLSCH_RB_ALLOC;
+ DLSCH_alloc_pdu2_1E[1].TPC = 0;
+ DLSCH_alloc_pdu2_1E[1].dai = 0;
+ DLSCH_alloc_pdu2_1E[1].harq_pid = 0;
+ //DLSCH_alloc_pdu2_1E[1].tb_swap = 0;
+ DLSCH_alloc_pdu2_1E[1].mcs = mcs_i;
+ DLSCH_alloc_pdu2_1E[1].ndi = 1;
+ DLSCH_alloc_pdu2_1E[1].rv = 0;
+ // Forget second codeword
+ DLSCH_alloc_pdu2_1E[1].tpmi = (transmission_mode>=5 ? 5 : 0) ; // precoding
+ DLSCH_alloc_pdu2_1E[1].dl_power_off = (transmission_mode==5 ? 0 : 1);
+
+ eNB2UE[0] = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx,
+ UE->frame_parms.nb_antennas_rx,
+ channel_model,
+ N_RB2sampling_rate(eNB->frame_parms.N_RB_DL),
+ N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
+ forgetting_factor,
+ rx_sample_offset,
+ 0);
+
+ if(num_rounds>1) {
+ for(n=1; n<4; n++)
+ eNB2UE[n] = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx,
+ UE->frame_parms.nb_antennas_rx,
+ channel_model,
+ N_RB2sampling_rate(eNB->frame_parms.N_RB_DL),
+ N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
+ forgetting_factor,
+ rx_sample_offset,
+ 0);
+ }
+
+ if (eNB2UE[0]==NULL) {
+ msg("Problem generating channel model. Exiting.\n");
+ exit(-1);
+ }
+
+ if ((transmission_mode == 3) || (transmission_mode==4))
+ Kmimo=2;
+ else
+ Kmimo=1;
+
+ switch (ue_category) {
+ case 1:
+ Nsoft = 250368;
+ break;
+ case 2:
+ case 3:
+ Nsoft = 1237248;
+ break;
+ case 4:
+ Nsoft = 1827072;
+ break;
+ default:
+ printf("Unsupported UE category %d\n",ue_category);
+ exit(-1);
+ break;
+ }
+
+ for (k=0; kdlsch[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0,&eNB->frame_parms);
+
+ if (!eNB->dlsch[k][i]) {
+ printf("Can't get eNB dlsch structures\n");
+ exit(-1);
+ } else {
+ // this initilisation may should be moved to another place
+ for (j=0; j<4; j++) {
+ for (aa=0; aadlsch[k][i]->ue_spec_bf_weights[j][aa];
+
+ for (re=0;re>1;
+ else if (n_tx_phy==16)
+ ue_spec_bf_weights[re] = 0x00007fff>>2;
+ else if (n_tx_phy==64)
+ ue_spec_bf_weights[re] = 0x00007fff>>4;
+ }
+
+ }
+ }
+
+ }
+
+ eNB->dlsch[k][i]->rnti = n_rnti+k;
+ }
+ }
+
+ for (i=0; i<2; i++) {
+ UE->dlsch[0][i] = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0);
+
+ if (!UE->dlsch[0][i]) {
+ printf("Can't get ue dlsch structures\n");
+ exit(-1);
+ }
+
+ UE->dlsch[0][i]->rnti = n_rnti;
+ }
+
+ // structure for SIC at UE
+ UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0,&eNB->frame_parms);
+
+ if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) {
+
+ eNB->UE_stats[0].DL_pmi_single = (unsigned short)(taus()&0xffff);
+
+ if (n_users>1)
+ eNB->UE_stats[1].DL_pmi_single = (eNB->UE_stats[0].DL_pmi_single ^ 0x1555); //opposite PMI
+ } else {
+ eNB->UE_stats[0].DL_pmi_single = 0;
+
+ if (n_users>1)
+ eNB->UE_stats[1].DL_pmi_single = 0;
+ }
+
+ //TODO: allocate memory for calibration matrix and calib_dl_ch_estimates in init_lte.c
+ //for first tests initialze calibration matrix with idendity
+ //read_calibration_matrix(calib_fname, nb_ant, nb_freq, eNB->common_vars.tdd_calib_coeffs[0]);
+
+ if (input_fd==NULL) {
+
+
+ /*
+ // common DCI
+ memcpy(&dci_alloc[num_dci].dci_pdu[0],&CCCH_alloc_pdu,sizeof(DCI1A_5MHz_TDD_1_6_t));
+ dci_alloc[num_dci].dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
+ dci_alloc[num_dci].L = 2;
+ dci_alloc[num_dci].rnti = SI_RNTI;
+ num_dci++;
+ num_common_dci++;
+ */
+
+ // UE specific DCI
+ for(k=0; kframe_parms.frame_type == TDD) {
+
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI1_1_5MHz_TDD_t;
+ dci_length_bytes = sizeof(DCI1_1_5MHz_TDD_t);
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1;
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI1_5MHz_TDD_t;
+ dci_length_bytes = sizeof(DCI1_5MHz_TDD_t);
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1;
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI1_10MHz_TDD_t;
+ dci_length_bytes = sizeof(DCI1_10MHz_TDD_t);
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1;
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 100:
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1;
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ dci_length = sizeof_DCI1_20MHz_TDD_t;
+ dci_length_bytes = sizeof(DCI1_20MHz_TDD_t);
+ break;
+ }
+ } else {
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI1_1_5MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1_1_5MHz_FDD_t);
+ ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1;
+ ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI1_5MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1_5MHz_FDD_t);
+ ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1;
+ ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI1_10MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1_10MHz_FDD_t);
+ ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1;
+ ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 100:
+ dci_length = sizeof_DCI1_20MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1_20MHz_FDD_t);
+ ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 1;
+ ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+ }
+ }
+
+ memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+ dci_alloc[num_dci].dci_length = dci_length;
+ dci_alloc[num_dci].L = 1;
+ dci_alloc[num_dci].rnti = n_rnti+k;
+ dci_alloc[num_dci].format = format1;
+ dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+ printf("Generating dlsch params for user %d\n",k);
+ generate_eNB_dlsch_params_from_dci(0,
+ subframe,
+ &DLSCH_alloc_pdu_1[0],
+ n_rnti+k,
+ format1,
+ eNB->dlsch[0],
+ &eNB->frame_parms,
+ eNB->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI,
+ eNB->UE_stats[0].DL_pmi_single,
+ transmission_mode<7?0:transmission_mode);
+
+ /*if (transmission_mode == 7)
+ eNB->dlsch[0][0]->harq_processes[0]->mimo_mode = TM7; //Xiwen: to check about harq_pid*/
+
+ num_dci++;
+ num_ue_spec_dci++;
+ } else {
+ if (eNB->frame_parms.frame_type == TDD) {
+
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t);
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t);
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 1;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI1A_10MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t);
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 100:
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ dci_length = sizeof_DCI1A_20MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t);
+ break;
+ }
+ } else {
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI1A_1_5MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t);
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI1A_5MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t);
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI1A_10MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t);
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 100:
+ dci_length = sizeof_DCI1A_20MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t);
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+ }
+ }
+
+ memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+ dci_alloc[num_dci].dci_length = dci_length;
+ dci_alloc[num_dci].L = 1;
+ dci_alloc[num_dci].rnti = SI_RNTI;
+ dci_alloc[num_dci].format = format1A;
+ dci_alloc[num_dci].firstCCE = 0;
+ dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+ printf("Generating dlsch params for user %d\n",k);
+ generate_eNB_dlsch_params_from_dci(0,
+ subframe,
+ &DLSCH_alloc_pdu_1[0],
+ SI_RNTI,
+ format1A,
+ eNB->dlsch[0],
+ &eNB->frame_parms,
+ eNB->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI,
+ eNB->UE_stats[0].DL_pmi_single,
+ 0);
+
+ num_common_dci++;
+ num_dci++;
+
+ }
+
+ break;
+
+ case 3:
+ if (common_flag == 0) {
+
+ if (eNB->frame_parms.nb_antennas_tx == 2) {
+
+ if (eNB->frame_parms.frame_type == TDD) {
+
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI2A_1_5MHz_2A_TDD_t;
+ dci_length_bytes = sizeof(DCI2A_1_5MHz_2A_TDD_t);
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI2A_5MHz_2A_TDD_t;
+ dci_length_bytes = sizeof(DCI2A_5MHz_2A_TDD_t);
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI2A_10MHz_2A_TDD_t;
+ dci_length_bytes = sizeof(DCI2A_10MHz_2A_TDD_t);
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 100:
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ dci_length = sizeof_DCI2A_20MHz_2A_TDD_t;
+ dci_length_bytes = sizeof(DCI2A_20MHz_2A_TDD_t);
+ break;
+ }
+ }
+
+ else {
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI2A_1_5MHz_2A_FDD_t;
+ dci_length_bytes = sizeof(DCI2A_1_5MHz_2A_FDD_t);
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI2A_5MHz_2A_FDD_t;
+ dci_length_bytes = sizeof(DCI2A_5MHz_2A_FDD_t);
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI2A_10MHz_2A_FDD_t;
+ dci_length_bytes = sizeof(DCI2A_10MHz_2A_FDD_t);
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 100:
+ dci_length = sizeof_DCI2A_20MHz_2A_FDD_t;
+ dci_length_bytes = sizeof(DCI2A_20MHz_2A_FDD_t);
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+ }
+ }
+ } else if (eNB->frame_parms.nb_antennas_tx == 4) {
+
+ }
+
+ memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+ dci_alloc[num_dci].dci_length = dci_length;
+ dci_alloc[num_dci].L = 1;
+ dci_alloc[num_dci].rnti = n_rnti+k;
+ dci_alloc[num_dci].format = format2A;
+ dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+ printf("Generating dlsch params for user %d / format 2A (%d)\n",k,format2A);
+ generate_eNB_dlsch_params_from_dci(0,
+ subframe,
+ &DLSCH_alloc_pdu_1[0],
+ n_rnti+k,
+ format2A,
+ eNB->dlsch[0],
+ &eNB->frame_parms,
+ eNB->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI,
+ eNB->UE_stats[0].DL_pmi_single,
+ 0);
+
+ num_dci++;
+ num_ue_spec_dci++;
+ } else {
+ if (eNB->frame_parms.frame_type == TDD) {
+
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t);
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t);
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 1;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI1A_10MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t);
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 100:
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ dci_length = sizeof_DCI1A_20MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t);
+ break;
+ }
+ } else {
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI1A_1_5MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t);
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI1A_5MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t);
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI1A_10MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t);
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 100:
+ dci_length = sizeof_DCI1A_20MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t);
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+ }
+ }
+
+ memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+ dci_alloc[num_dci].dci_length = dci_length;
+ dci_alloc[num_dci].L = 1;
+ dci_alloc[num_dci].rnti = SI_RNTI;
+ dci_alloc[num_dci].format = format1A;
+ dci_alloc[num_dci].firstCCE = 0;
+ dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+ printf("Generating dlsch params for user %d\n",k);
+ generate_eNB_dlsch_params_from_dci(0,
+ subframe,
+ &DLSCH_alloc_pdu_1[0],
+ SI_RNTI,
+ format1A,
+ eNB->dlsch[0],
+ &eNB->frame_parms,
+ eNB->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI,
+ eNB->UE_stats[0].DL_pmi_single,
+ 0);
+
+ num_common_dci++;
+ num_dci++;
+
+ }
+
+ printf("Generated DCI format 2A (Transmission Mode 3)\n");
+ break;
+
+ case 4:
+ if (common_flag == 0) {
+
+ if (eNB->frame_parms.nb_antennas_tx == 2) {
+
+ if (eNB->frame_parms.frame_type == TDD) {
+
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI2_1_5MHz_2A_TDD_t;
+ dci_length_bytes = sizeof(DCI2_1_5MHz_2A_TDD_t);
+ ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI2_5MHz_2A_TDD_t;
+ dci_length_bytes = sizeof(DCI2_5MHz_2A_TDD_t);
+ ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI2_10MHz_2A_TDD_t;
+ dci_length_bytes = sizeof(DCI2_10MHz_2A_TDD_t);
+ ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 100:
+ ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ dci_length = sizeof_DCI2_20MHz_2A_TDD_t;
+ dci_length_bytes = sizeof(DCI2_20MHz_2A_TDD_t);
+ break;
+ }
+ }
+
+ else {
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI2_1_5MHz_2A_FDD_t;
+ dci_length_bytes = sizeof(DCI2_1_5MHz_2A_FDD_t);
+ ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI2_5MHz_2A_FDD_t;
+ dci_length_bytes = sizeof(DCI2_5MHz_2A_FDD_t);
+ ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI2_10MHz_2A_FDD_t;
+ dci_length_bytes = sizeof(DCI2_10MHz_2A_FDD_t);
+ ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+
+ case 100:
+ dci_length = sizeof_DCI2_20MHz_2A_FDD_t;
+ dci_length_bytes = sizeof(DCI2_20MHz_2A_FDD_t);
+ ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah = 0;
+ ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = DLSCH_RB_ALLOC;
+ ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = 0;
+ ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1 = mcs1;
+ ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1 = 1;
+ ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1 = 0;
+ ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2 = mcs2;
+ ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2 = 1;
+ ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2 = 0;
+ break;
+ }
+ }
+ } else if (eNB->frame_parms.nb_antennas_tx == 4) {
+
+ }
+
+ memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+ dci_alloc[num_dci].dci_length = dci_length;
+ dci_alloc[num_dci].L = 1;
+ dci_alloc[num_dci].rnti = n_rnti+k;
+ dci_alloc[num_dci].format = format2;
+ dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+ printf("Generating dlsch params for user %d\n",k);
+ generate_eNB_dlsch_params_from_dci(0,
+ subframe,
+ &DLSCH_alloc_pdu_1[0],
+ n_rnti+k,
+ format2,
+ eNB->dlsch[0],
+ &eNB->frame_parms,
+ eNB->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI,
+ eNB->UE_stats[0].DL_pmi_single,
+ 0);
+
+ num_dci++;
+ num_ue_spec_dci++;
+ } else {
+ if (eNB->frame_parms.frame_type == TDD) {
+
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t);
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t);
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 1;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI1A_10MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t);
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 100:
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ dci_length = sizeof_DCI1A_20MHz_TDD_1_6_t;
+ dci_length_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t);
+ break;
+ }
+ } else {
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ dci_length = sizeof_DCI1A_1_5MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t);
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 25:
+ dci_length = sizeof_DCI1A_5MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t);
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 50:
+ dci_length = sizeof_DCI1A_10MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t);
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+
+ case 100:
+ dci_length = sizeof_DCI1A_20MHz_FDD_t;
+ dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t);
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi = 0;
+ ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv = 0;
+ break;
+ }
+ }
+
+ memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+ dci_alloc[num_dci].dci_length = dci_length;
+ dci_alloc[num_dci].L = 1;
+ dci_alloc[num_dci].rnti = SI_RNTI;
+ dci_alloc[num_dci].format = format1A;
+ dci_alloc[num_dci].firstCCE = 0;
+ dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+ printf("Generating dlsch params for user %d\n",k);
+ generate_eNB_dlsch_params_from_dci(0,
+ subframe,
+ &DLSCH_alloc_pdu_1[0],
+ SI_RNTI,
+ format1A,
+ eNB->dlsch[0],
+ &eNB->frame_parms,
+ eNB->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI,
+ eNB->UE_stats[0].DL_pmi_single,
+ 0);
+
+ num_common_dci++;
+ num_dci++;
+
+ }
+
+ break;
+
+ case 5:
+ case 6:
+ memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu2_1E[k],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
+ dci_alloc[num_dci].dci_length = sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t;
+ dci_alloc[num_dci].L = 1;
+ dci_alloc[num_dci].rnti = n_rnti+k;
+ dci_alloc[num_dci].format = format1E_2A_M10PRB;
+ dci_alloc[num_dci].firstCCE = 4*k;
+ printf("Generating dlsch params for user %d\n",k);
+ generate_eNB_dlsch_params_from_dci(0,
+ subframe,
+ &DLSCH_alloc_pdu2_1E[k],
+ n_rnti+k,
+ format1E_2A_M10PRB,
+ eNB->dlsch[k],
+ &eNB->frame_parms,
+ eNB->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI,
+ eNB->UE_stats[k].DL_pmi_single,
+ 0);
+
+ dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+ num_ue_spec_dci++;
+ num_dci++;
+
+ break;
+
+ default:
+ printf("Unsupported Transmission Mode!!!");
+ exit(-1);
+ break;
+ }
+
+
+
+
+ /*
+ memcpy(&dci_alloc[1].dci_pdu[0],&UL_alloc_pdu,sizeof(DCI0_5MHz_TDD0_t));
+ dci_alloc[1].dci_length = sizeof_DCI0_5MHz_TDD_0_t;
+ dci_alloc[1].L = 2;
+ dci_alloc[1].rnti = n_rnti;
+ */
+ }
+
+ if (n_frames==1) printf("num_pdcch_symbols %d, numCCE %d => ",num_pdcch_symbols,numCCE);
+
+ numCCE = get_nCCE(num_pdcch_symbols,&eNB->frame_parms,get_mi(&eNB->frame_parms,subframe));
+
+ if (n_frames==1) printf("%d\n",numCCE);
+
+ // apply RNTI-based nCCE allocation
+ memset(CCE_table,0,800*sizeof(int));
+
+ for (i=num_common_dci; idlsch[k][0]->harq_processes[0]->TBS/8;
+ input_buffer0[k] = (unsigned char *)malloc(input_buffer_length0+4);
+ memset(input_buffer0[k],0,input_buffer_length0+4);
+ input_buffer_length1 = eNB->dlsch[k][1]->harq_processes[0]->TBS/8;
+ input_buffer1[k] = (unsigned char *)malloc(input_buffer_length1+4);
+ memset(input_buffer1[k],0,input_buffer_length1+4);
+
+ if (input_trch_file==0) {
+ for (i=0; i>3]+=(1<<(7-(i&7)));
+
+ if (i<16)
+ printf("input_trch_val %d : %c\n",i,input_trch_val[0]);
+
+ i++;
+
+ if (((i%8) == 0) && (i<17))
+ printf("%x\n",input_buffer0[k][(i-1)>>3]);
+ }
+
+ printf("Read in %d bits\n",i);
+ }
+ }
+ }
+
+ // this is for user 0 only
+ coded_bits_per_codeword = get_G(&eNB->frame_parms,
+ eNB->dlsch[0][0]->harq_processes[0]->nb_rb,
+ eNB->dlsch[0][0]->harq_processes[0]->rb_alloc,
+ get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs),
+ eNB->dlsch[0][0]->harq_processes[0]->Nl,
+ num_pdcch_symbols,
+ 0,
+ subframe,
+ (transmission_mode<7?0:transmission_mode));
+
+ uncoded_ber_bit = (short*) malloc(sizeof(short)*coded_bits_per_codeword);
+ printf("uncoded_ber_bit=%p\n",uncoded_ber_bit);
+
+ snr_step = input_snr_step;
+ UE->high_speed_flag = 0; //1
+ UE->ch_est_alpha=0;
+
+ for (ch_realization=0; ch_realizationproc.proc_rxtx[subframe&1].frame_rx=0;
+ errs[0]=0;
+ errs[1]=0;
+ errs[2]=0;
+ errs[3]=0;
+ errs2[0]=0;
+ errs2[1]=0;
+ errs2[2]=0;
+ errs2[3]=0;
+ round_trials[0] = 0;
+ round_trials[1] = 0;
+ round_trials[2] = 0;
+ round_trials[3] = 0;
+
+ dci_errors=0;
+ // avg_ber = 0;
+
+ round=0;
+ avg_iter = 0;
+ iter_trials=0;
+ reset_meas(&eNB->phy_proc_tx); // total eNB tx
+ reset_meas(&eNB->dlsch_scrambling_stats);
+ reset_meas(&UE->dlsch_unscrambling_stats);
+ reset_meas(&eNB->ofdm_mod_stats);
+ reset_meas(&eNB->dlsch_modulation_stats);
+ reset_meas(&eNB->dlsch_encoding_stats);
+ reset_meas(&eNB->dlsch_interleaving_stats);
+ reset_meas(&eNB->dlsch_rate_matching_stats);
+ reset_meas(&eNB->dlsch_turbo_encoding_stats);
+
+ reset_meas(&UE->phy_proc_rx); // total UE rx
+ reset_meas(&UE->ofdm_demod_stats);
+ reset_meas(&UE->dlsch_channel_estimation_stats);
+ reset_meas(&UE->dlsch_freq_offset_estimation_stats);
+ reset_meas(&UE->rx_dft_stats);
+ reset_meas(&UE->dlsch_decoding_stats);
+ reset_meas(&UE->dlsch_turbo_decoding_stats);
+ reset_meas(&UE->dlsch_deinterleaving_stats);
+ reset_meas(&UE->dlsch_rate_unmatching_stats);
+ reset_meas(&UE->dlsch_tc_init_stats);
+ reset_meas(&UE->dlsch_tc_alpha_stats);
+ reset_meas(&UE->dlsch_tc_beta_stats);
+ reset_meas(&UE->dlsch_tc_gamma_stats);
+ reset_meas(&UE->dlsch_tc_ext_stats);
+ reset_meas(&UE->dlsch_tc_intl1_stats);
+ reset_meas(&UE->dlsch_tc_intl2_stats);
+ // initialization
+ struct list time_vector_tx;
+ initialize(&time_vector_tx);
+ struct list time_vector_tx_ifft;
+ initialize(&time_vector_tx_ifft);
+ struct list time_vector_tx_mod;
+ initialize(&time_vector_tx_mod);
+ struct list time_vector_tx_enc;
+ initialize(&time_vector_tx_enc);
+
+ struct list time_vector_rx;
+ initialize(&time_vector_rx);
+ struct list time_vector_rx_fft;
+ initialize(&time_vector_rx_fft);
+ struct list time_vector_rx_demod;
+ initialize(&time_vector_rx_demod);
+ struct list time_vector_rx_dec;
+ initialize(&time_vector_rx_dec);
+
+ for (trials = 0; trialsfirst_run = 1;
+
+ ret = UE->dlsch[0][0]->max_turbo_iterations+1;
+
+ while ((round < num_rounds) && (ret > UE->dlsch[0][0]->max_turbo_iterations)) {
+ //printf("Trial %d, round %d\n",trials,round);
+ round_trials[round]++;
+
+ if(transmission_mode>=5&&transmission_mode<7)
+ pmi_feedback=1;
+ else
+ pmi_feedback=0;
+
+ if (abstx) {
+ if (trials==0 && round==0 && SNR==snr0) //generate a new channel
+ hold_channel = 0;
+ else
+ hold_channel = 1;
+ } else
+ hold_channel = 0;//(round==0) ? 0 : 1;
+
+PMI_FEEDBACK:
+
+ //make sure dlsim is called with perfect channel estimation option (for freq_channel)
+ //fill drs_ch_estimates with data from eNB2UE->chF
+ for(aa=0; aanb_antenna_ports_eNB; aa++) {
+ for (aarx=0; aarxnb_antennas_rx; aarx++) {
+ for (i=0; iN_RB_DL*12; i++) {
+ for (l=0; lsymbols_per_tti; l++) {
+ ((int16_t *) eNB->pusch_vars[0]->drs_ch_estimates[0][(aa<<1)+aarx])[2*i+(l*frame_parms->ofdm_symbol_size)*2]=(int16_t)(eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP);
+ //printf("x=%d,AMP=%d\n",eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x,AMP);
+ ((int16_t *) eNB->pusch_vars[0]->drs_ch_estimates[0][(aa<<1)+aarx])[2*i+1+(l*frame_parms->ofdm_symbol_size)*2]=(int16_t)(eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP);
+ }
+ }
+ }
+ }
+
+ estimate_DLCSI_from_ULCSI(eNB->dlsch[0][0]->calib_dl_ch_estimates,
+ &eNB->pusch_vars[0]->drs_ch_estimates[0][0/*position of second DMRS*/],
+ eNB->common_vars.tdd_calib_coeffs[0],
+ frame_parms->nb_antennas_tx,
+ frame_parms->N_RB_DL*12);
+
+ compute_BF_weights(eNB->dlsch[0][0]->ue_spec_bf_weights[0],
+ eNB->dlsch[0][0]->calib_dl_ch_estimates,
+ MRT,
+ frame_parms->nb_antennas_tx,
+ frame_parms->N_RB_DL*12);
+
+ //printf("Trial %d : Round %d, pmi_feedback %d \n",trials,round,pmi_feedback);
+ for (aa=0; aacommon_vars.txdataF[eNB_id][aa][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t));
+ }
+
+ if (input_fd==NULL) {
+
+ start_meas(&eNB->phy_proc_tx);
+
+ // Simulate HARQ procedures!!!
+ if (common_flag == 0) {
+
+ if (round == 0) { // First round
+ TB0_active = 1;
+
+ eNB->dlsch[0][0]->harq_processes[0]->rvidx = round&3;
+
+ if (eNB->frame_parms.frame_type == TDD) {
+
+ switch (transmission_mode) {
+ case 1:
+ case 2:
+ case 7:
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_TDD_t));
+ break;
+
+ case 25:
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_TDD_t));
+ break;
+
+ case 50:
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_TDD_t));
+ break;
+
+ case 100:
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_TDD_t));
+ break;
+ }
+
+ break;
+
+ case 3:
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_TDD_t));
+ break;
+
+ case 25:
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_TDD_t));
+ break;
+
+ case 50:
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_TDD_t));
+ break;
+
+ case 100:
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_TDD_t));
+ break;
+ }
+
+ break;
+
+ case 5:
+ DLSCH_alloc_pdu2_1E[0].ndi = trials&1;
+ DLSCH_alloc_pdu2_1E[0].rv = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
+ break;
+
+ }
+ } else { // FDD
+ switch (transmission_mode) {
+ case 1:
+ case 2:
+ case 7:
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_FDD_t));
+ break;
+
+ case 25:
+ ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_FDD_t));
+ break;
+
+ case 50:
+ ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_FDD_t));
+ break;
+
+ case 100:
+ ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_FDD_t));
+ break;
+ }
+
+ break;
+ case 3:
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_FDD_t));
+ break;
+
+ case 25:
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_FDD_t));
+ break;
+
+ case 50:
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_FDD_t));
+ break;
+
+ case 100:
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_FDD_t));
+ break;
+ }
+
+ break;
+
+ case 5:
+ DLSCH_alloc_pdu2_1E[0].ndi = trials&1;
+ DLSCH_alloc_pdu2_1E[0].rv = 0;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
+ break;
+ }
+
+ }
+ } else {
+ eNB->dlsch[0][0]->harq_processes[0]->rvidx = round&3;
+
+ if (eNB->frame_parms.frame_type == TDD) {
+
+
+ switch (transmission_mode) {
+ case 1:
+ case 2:
+ case 7:
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_TDD_t));
+ break;
+
+ case 25:
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_TDD_t));
+ break;
+
+ case 50:
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_TDD_t));
+ break;
+
+ case 100:
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_TDD_t));
+ break;
+ }
+
+ break;
+
+ case 3:
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ if (TB0_active==1) {
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ } else { // deactivate TB0
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ }
+
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_TDD_t));
+ break;
+
+ case 25:
+ if (TB0_active==1) {
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ } else { // deactivate TB0
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ }
+
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_TDD_t));
+ break;
+
+ case 50:
+ if (TB0_active==1) {
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ } else { // deactivate TB0
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ }
+
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_TDD_t));
+ break;
+
+ case 100:
+ if (TB0_active==1) {
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ } else { // deactivate TB0
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ }
+
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_TDD_t));
+ break;
+ }
+
+ break;
+
+ case 5:
+ DLSCH_alloc_pdu2_1E[0].ndi = trials&1;
+ DLSCH_alloc_pdu2_1E[0].rv = round&3;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
+ break;
+ }
+ } else {
+ switch (transmission_mode) {
+ case 1:
+ case 2:
+ case 7:
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_FDD_t));
+ break;
+
+ case 25:
+ ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_FDD_t));
+ break;
+
+ case 50:
+ ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_FDD_t));
+ break;
+
+ case 100:
+ ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1;
+ ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_FDD_t));
+ break;
+ }
+
+ break;
+
+ case 3:
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ if (TB0_active==1) {
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ } else { // deactivate TB0
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ }
+
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_FDD_t));
+ break;
+
+ case 25:
+ if (TB0_active==1) {
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ } else { // deactivate TB0
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ }
+
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_FDD_t));
+ break;
+
+ case 50:
+ if (TB0_active==1) {
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ } else { // deactivate TB0
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ }
+
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_FDD_t));
+ break;
+
+ case 100:
+ if (TB0_active==1) {
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = round&3;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ } else { // deactivate TB0
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1 = 0;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 1;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2 = trials&1;
+ ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2 = round&3;
+ }
+
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_FDD_t));
+ break;
+ }
+
+ break;
+
+ case 5:
+ DLSCH_alloc_pdu2_1E[0].ndi = trials&1;
+ DLSCH_alloc_pdu2_1E[0].rv = round&3;
+ memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
+ break;
+ }
+ }
+ }
+ }
+
+ num_pdcch_symbols_2 = generate_dci_top(num_ue_spec_dci,
+ num_common_dci,
+ dci_alloc,
+ 0,
+ AMP,
+ &eNB->frame_parms,
+ eNB->common_vars.txdataF[eNB_id],
+ subframe);
+
+ if (num_pdcch_symbols_2 > num_pdcch_symbols) {
+ msg("Error: given num_pdcch_symbols not big enough (%d > %d)\n",num_pdcch_symbols_2,num_pdcch_symbols);
+ exit(-1);
+ }
+
+ for (k=0; kframe_parms,
+ eNB->dlsch[k][cw]->harq_processes[0]->nb_rb,
+ eNB->dlsch[k][cw]->harq_processes[0]->rb_alloc,
+ get_Qm(eNB->dlsch[k][cw]->harq_processes[0]->mcs),
+ eNB->dlsch[k][cw]->harq_processes[0]->Nl,
+ num_pdcch_symbols,
+ 0,
+ subframe,
+ (transmission_mode<7?0:transmission_mode));
+
+#ifdef TBS_FIX // This is for MESH operation!!!
+ tbs = (double)3*TBStable[get_I_TBS(eNB->dlsch[k][cw]->harq_processes[0]->mcs)][eNB->dlsch[k][cw]->nb_rb-1]/4;
+#else
+ tbs = eNB->dlsch[k][cw]->harq_processes[0]->TBS;
+#endif
+ rate = (double)tbs/(double)coded_bits_per_codeword;
+
+ if ((SNR==snr0) && (trials==0) && (round==0))
+ printf("User %d, cw %d: Rate = %f (%f bits/dim) (G %d, TBS %d, mod %d, pdcch_sym %d, ndi %d)\n",
+ k,cw,rate,rate*get_Qm(eNB->dlsch[k][0]->harq_processes[0]->mcs),
+ coded_bits_per_codeword,
+ tbs,
+ get_Qm(eNB->dlsch[k][0]->harq_processes[0]->mcs),
+ num_pdcch_symbols,
+ eNB->dlsch[0][0]->harq_processes[0]->round);
+
+ // use the PMI from previous trial
+ if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) {
+ eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,eNB->frame_parms.N_RB_DL);
+ UE->dlsch[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,UE->frame_parms.N_RB_DL);
+
+ if (n_users>1)
+ eNB->dlsch[1][0]->harq_processes[0]->pmi_alloc = (eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc ^ 0x1555);
+
+ /*
+ if ((trials<10) && (round==0)) {
+ printf("tx PMI UE0 %x (pmi_feedback %d)\n",pmi2hex_2Ar1(eNB->dlsch[0][0]->pmi_alloc),pmi_feedback);
+ if (transmission_mode ==5)
+ printf("tx PMI UE1 %x\n",pmi2hex_2Ar1(eNB->dlsch[1][0]->pmi_alloc));
+ }
+ */
+ }
+
+
+ start_meas(&eNB->dlsch_encoding_stats);
+
+ if (dlsch_encoding(eNB,
+ ((cw==0) ? input_buffer0[k] : input_buffer1[k]),
+ num_pdcch_symbols,
+ eNB->dlsch[k][cw],
+ 0,subframe,
+ &eNB->dlsch_rate_matching_stats,
+ &eNB->dlsch_turbo_encoding_stats,
+ &eNB->dlsch_interleaving_stats)<0)
+ exit(-1);
+
+ /*
+ if (transmission_mode == 3) {
+ if (dlsch_encoding(input_buffer1[k],
+ &eNB->frame_parms,
+ num_pdcch_symbols,
+ eNB->dlsch[k][1],
+ 0,subframe,
+ &eNB->dlsch_rate_matching_stats,
+ &eNB->dlsch_turbo_encoding_stats,
+ &eNB->dlsch_interleaving_stats
+ )<0)
+ exit(-1);
+ }
+ */
+ stop_meas(&eNB->dlsch_encoding_stats);
+
+ eNB->dlsch[k][cw]->rnti = (common_flag==0) ? n_rnti+k : SI_RNTI;
+ start_meas(&eNB->dlsch_scrambling_stats);
+ dlsch_scrambling(&eNB->frame_parms,
+ 0,
+ eNB->dlsch[k][cw],
+ coded_bits_per_codeword,
+ 0,
+ subframe<<1);
+ stop_meas(&eNB->dlsch_scrambling_stats);
+
+ if (n_frames==1) {
+ for (s=0; sdlsch[k][cw]->harq_processes[0]->C; s++) {
+ if (sdlsch[k][cw]->harq_processes[0]->Cminus)
+ Kr = eNB->dlsch[k][cw]->harq_processes[0]->Kminus;
+ else
+ Kr = eNB->dlsch[k][cw]->harq_processes[0]->Kplus;
+
+ Kr_bytes = Kr>>3;
+
+ for (i=0; idlsch[k][cw]->harq_processes[0]->c[s][i]);
+ }
+ }
+ }
+
+ start_meas(&eNB->dlsch_modulation_stats);
+ re_allocated = dlsch_modulation(eNB,
+ eNB->common_vars.txdataF[eNB_id],
+ AMP,
+ subframe,
+ num_pdcch_symbols,
+ eNB->dlsch[k][0],
+ eNB->dlsch[k][1]);
+ /* avoid gcc warnings */
+ (void)re_allocated;
+
+ stop_meas(&eNB->dlsch_modulation_stats);
+ /*
+ if (trials==0 && round==0)
+ printf("RE count %d\n",re_allocated);
+ */
+ } //n_users
+
+
+ generate_pilots(eNB,
+ eNB->common_vars.txdataF[eNB_id],
+ AMP,
+ LTE_NUMBER_OF_SUBFRAMES_PER_FRAME);
+/*
+ //PSS/SSS
+ if (eNB->frame_parms.frame_type == FDD) {
+ generate_pss(eNB->common_vars.txdataF[0],
+ AMP,
+ &eNB->frame_parms,
+ (eNB->frame_parms.Ncp==NORMAL) ? 6 : 5,
+ 0);
+ generate_sss(eNB->common_vars.txdataF[0],
+ AMP,
+ &eNB->frame_parms,
+ (eNB->frame_parms.Ncp==NORMAL) ? 5 : 4,
+ 0);
+ generate_pss(eNB->common_vars.txdataF[0],
+ AMP,
+ &eNB->frame_parms,
+ (eNB->frame_parms.Ncp==NORMAL) ? 6 : 5,
+ 10);
+ generate_sss(eNB->common_vars.txdataF[0],
+ AMP,
+ &eNB->frame_parms,
+ (eNB->frame_parms.Ncp==NORMAL) ? 5 : 4,
+ 10);
+ }
+ else if (eNB->frame_parms.frame_type == TDD) {
+ generate_sss(eNB->common_vars.txdataF[0],
+ AMP,
+ &eNB->frame_parms,
+ (eNB->frame_parms.Ncp==NORMAL) ? 6 : 5,
+ 1);
+ generate_pss(eNB->common_vars.txdataF[0],
+ AMP,
+ &eNB->frame_parms,
+ 2,
+ 2);
+ generate_sss(eNB->common_vars.txdataF[0],
+ AMP,
+ &eNB->frame_parms,
+ (eNB->frame_parms.Ncp==NORMAL) ? 6 : 5,
+ 11);
+ generate_pss(eNB->common_vars.txdataF[0],
+ AMP,
+ &eNB->frame_parms,
+ 2,
+ 12);
+ }
+
+ //PBCH
+ pbch_pdu[2] = 0;
+
+ // FIXME setting pbch_pdu[2] to zero makes the switch statement easier: remove all the or-operators
+ switch (eNB->frame_parms.N_RB_DL) {
+ case 6:
+ pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (0<<5);
+ break;
+
+ case 15:
+ pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (1<<5);
+ break;
+
+ case 25:
+ pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5);
+ break;
+
+ case 50:
+ pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (3<<5);
+ break;
+
+ case 75:
+ pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (4<<5);
+ break;
+
+ case 100:
+ pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (5<<5);
+ break;
+
+ default:
+ // FIXME if we get here, this should be flagged as an error, right?
+ pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5);
+ break;
+ }
+
+ pbch_pdu[2] = (pbch_pdu[2]&0xef) |
+ ((eNB->frame_parms.phich_config_common.phich_duration << 4)&0x10);
+
+ switch (eNB->frame_parms.phich_config_common.phich_resource) {
+ case oneSixth:
+ pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (0<<2);
+ break;
+
+ case half:
+ pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (1<<2);
+ break;
+
+ case one:
+ pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (2<<2);
+ break;
+
+ case two:
+ pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (3<<2);
+ break;
+
+ default:
+ // unreachable
+ break;
+
+
+ pbch_pdu[2] = (pbch_pdu[2]&0xfc) | ((0>>8)&0x3);
+ pbch_pdu[1] = 0&0xfc;
+ pbch_pdu[0] = 0;
+ }
+
+ generate_pbch(&eNB->lte_eNB_pbch,
+ eNB->common_vars.txdataF[0],
+ AMP,
+ &eNB->frame_parms,
+ pbch_pdu,
+ 0&3);
+*/
+
+ start_meas(&eNB->ofdm_mod_stats);
+/*
+ for(i=0;i<20;i++){
+
+ do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id],
+ eNB->common_vars.txdata[eNB_id],
+ i,
+ &eNB->frame_parms);
+ }
+
+*/
+ do_OFDM_mod_symbol(&eNB->common_vars,
+ eNB_id,
+ (subframe*2),
+ &eNB->frame_parms);
+
+ do_OFDM_mod_symbol(&eNB->common_vars,
+ eNB_id,
+ (subframe*2)+1,
+ &eNB->frame_parms);
+
+ stop_meas(&eNB->ofdm_mod_stats);
+ stop_meas(&eNB->phy_proc_tx);
+
+ /* do_OFDM_mod_l(&eNB->common_vars,
+ eNB_id,
+ (subframe*2)+2,
+ &eNB->frame_parms); */
+
+ if (n_frames==1) {
+ if (transmission_mode<7)
+ write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],
+ nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+ else if (transmission_mode==7)
+ write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][5][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],
+ nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+ write_output("txsigF0_BF.m","txsF0_BF", &eNB->common_vars.txdataF_BF[eNB_id][0][0],
+ eNB->frame_parms.ofdm_symbol_size,1,1);
+
+ if (eNB->frame_parms.nb_antennas_tx>1)// to be updated
+ write_output("txsigF1.m","txsF1", &eNB->common_vars.txdataF[eNB_id][1][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],
+ nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+ }
+ tx_lev = 0;
+
+ for (aa=0; aaframe_parms.nb_antennas_tx; aa++) {
+ tx_lev += signal_energy(&eNB->common_vars.txdata[eNB_id][aa]
+ [subframe*eNB->frame_parms.samples_per_tti],
+ eNB->frame_parms.samples_per_tti);
+ }
+
+ tx_lev_dB = (unsigned int) dB_fixed(tx_lev);
+
+ if (n_frames==1) {
+ printf("tx_lev = %d (%d dB)\n",tx_lev,tx_lev_dB);
+ write_output("txsig0.m","txs0", &eNB->common_vars.txdata[eNB_id][0][subframe*eNB->frame_parms.samples_per_tti],eNB->frame_parms.samples_per_tti,1,1);
+ // write_output("txsig0.m","txs0",&eNB->common_vars.txdata[eNB_id][0][0*eNB->frame_parms.samples_per_tti],eNB->frame_parms.samples_per_tti*10,1,1);
+ }
+ }
+
+ /*
+ else { // Read signal from file
+ i=0;
+ while (!feof(input_fd)) {
+ fscanf(input_fd,"%s %s",input_val_str,input_val_str2);
+
+ if ((i%4)==0) {
+ ((short*)txdata[0])[i/2] = (short)((1<<15)*strtod(input_val_str,NULL));
+ ((short*)txdata[0])[(i/2)+1] = (short)((1<<15)*strtod(input_val_str2,NULL));
+ if ((i/4)<100)
+ printf("sample %d => %e + j%e (%d +j%d)\n",i/4,strtod(input_val_str,NULL),strtod(input_val_str2,NULL),((short*)txdata[0])[i/4],((short*)txdata[0])[(i/4)+1]);//1,input_val2,);
+ }
+ i++;
+ if (i>(FRAME_LENGTH_SAMPLES))
+ break;
+ }
+ printf("Read in %d samples\n",i/4);
+ write_output("txsig0.m","txs0", txdata[0],2*frame_parms->samples_per_tti,1,1);
+ // write_output("txsig1.m","txs1", txdata[1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1);
+ tx_lev = signal_energy(&txdata[0][0],
+ OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES);
+ tx_lev_dB = (unsigned int) dB_fixed(tx_lev);
+ }
+ */
+
+ // printf("Copying tx ..., nsymb %d (n_tx %d), awgn %d\n",nsymb,eNB->frame_parms.nb_antennas_tx,awgn_flag);
+ for (i=0; i<2*frame_parms->samples_per_tti; i++) {
+ for (aa=0; aaframe_parms.nb_antennas_tx; aa++) {
+ if (awgn_flag == 0) {
+ s_re[aa][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]);
+ s_im[aa][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]);
+ } else {
+ for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) {
+ if (aa==0) {
+ r_re[aarx][i] = (double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)];
+ r_im[aarx][i] = (double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1];
+ //printf("r[%d][%d]=> %f, %f\n",aarx,i,r_re[aarx][i],r_im[aarx][i]);
+ } else {
+ r_re[aarx][i] += (double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)];
+ r_im[aarx][i] += (double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1];
+ }
+
+ }
+ }
+ }
+ }
+
+ // Multipath channel
+ if (awgn_flag == 0) {
+ multipath_channel(eNB2UE[round],s_re,s_im,r_re,r_im,
+ 2*frame_parms->samples_per_tti,hold_channel);
+
+ // printf("amc: ****************** eNB2UE[%d]->n_rx = %d,dd %d\n",round,eNB2UE[round]->nb_rx,eNB2UE[round]->channel_offset);
+ if(abstx==1 && num_rounds>1)
+ if(round==0 && hold_channel==0) {
+ random_channel(eNB2UE[1],0);
+ random_channel(eNB2UE[2],0);
+ random_channel(eNB2UE[3],0);
+ }
+
+ if (UE->perfect_ce==1) {
+ // fill in perfect channel estimates
+ freq_channel(eNB2UE[round],UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1);
+ /*
+ write_output("channel.m","ch",eNB2UE[round]->ch[0],eNB2UE[round]->channel_length,1,8);
+ write_output("channelF.m","chF",eNB2UE[round]->chF[0],12*UE->frame_parms.N_RB_DL + 1,1,8);
+ */
+ }
+ }
+
+ if(abstx) {
+ if (trials==0 && round==0) {
+ // calculate freq domain representation to compute SINR
+ freq_channel(eNB2UE[0], NB_RB,2*NB_RB + 1);
+ // snr=pow(10.0,.1*SNR);
+ fprintf(csv_fd,"%f,",SNR);
+
+ for (u=0; u<2*NB_RB; u++) {
+ for (aarx=0; aarxnb_rx; aarx++) {
+ for (aatx=0; aatxnb_tx; aatx++) {
+ channelx = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].x;
+ channely = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].y;
+ fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
+ }
+ }
+ }
+
+ if(num_rounds>1) {
+ freq_channel(eNB2UE[1], NB_RB,2*NB_RB + 1);
+
+ for (u=0; u<2*NB_RB; u++) {
+ for (aarx=0; aarxnb_rx; aarx++) {
+ for (aatx=0; aatxnb_tx; aatx++) {
+ channelx = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].x;
+ channely = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].y;
+ fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
+ }
+ }
+ }
+
+ freq_channel(eNB2UE[2], NB_RB,2*NB_RB + 1);
+
+ for (u=0; u<2*NB_RB; u++) {
+ for (aarx=0; aarxnb_rx; aarx++) {
+ for (aatx=0; aatxnb_tx; aatx++) {
+ channelx = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].x;
+ channely = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].y;
+ fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
+ }
+ }
+ }
+
+ freq_channel(eNB2UE[3], NB_RB,2*NB_RB + 1);
+
+ for (u=0; u<2*NB_RB; u++) {
+ for (aarx=0; aarxnb_rx; aarx++) {
+ for (aatx=0; aatxnb_tx; aatx++) {
+ channelx = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].x;
+ channely = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].y;
+ fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //AWGN
+ // This is the SNR on the PDSCH for OFDM symbols without pilots -> rho_A
+ sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(NB_RB*12)) - SNR - get_pa_dB(eNB->pdsch_config_dedicated);
+ sigma2 = pow(10,sigma2_dB/10);
+
+ if (n_frames==1)
+ printf("Sigma2 %f (sigma2_dB %f,%f,%f )\n",sigma2,sigma2_dB,10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(NB_RB*12)),get_pa_dB(eNB->pdsch_config_dedicated));
+
+ for (i=0; i<2*frame_parms->samples_per_tti; i++) {
+ for (aa=0; aaframe_parms.nb_antennas_rx; aa++) {
+ // printf("s_re[0][%d]=> %f , r_re[0][%d]=> %f\n",i,s_re[aa][i],i,r_re[aa][i]);
+ ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i] =
+ (short) (r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0));
+ ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i+1] =
+ (short) (r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0));
+ //((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i] = (short) r_re[aa][i];
+ //((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i+1] = (short) r_im[aa][i];
+ //printf("rxdata[%d][%d]=> %d, %d\n",aa,subframe*UE->frame_parms.samples_per_tti+i,r_re[aa][i],r_im[aa][i]);
+ }
+ }
+
+
+ // lte_sync_time_init(eNB->frame_parms,common_vars);
+ // lte_sync_time(common_vars->rxdata, eNB->frame_parms);
+ // lte_sync_time_free();
+
+ /*
+ // optional: read rx_frame from file
+ if ((rx_frame_file = fopen("rx_frame.dat","r")) == NULL)
+ {
+ printf("Cannot open rx_frame.m data file\n");
+ exit(0);
+ }
+
+ result = fread((void *)PHY_vars->rx_vars[0].RX_DMA_BUFFER,4,FRAME_LENGTH_COMPLEX_SAMPLES,rx_frame_file);
+ printf("Read %d bytes\n",result);
+ result = fread((void *)PHY_vars->rx_vars[1].RX_DMA_BUFFER,4,FRAME_LENGTH_COMPLEX_SAMPLES,rx_frame_file);
+ printf("Read %d bytes\n",result);
+
+ fclose(rx_frame_file);
+ */
+
+ if (n_frames==1) {
+ printf("RX level in null symbol %d\n",dB_fixed(signal_energy(&UE->common_vars.rxdata[0][160+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2)));
+ printf("RX level in data symbol %d\n",dB_fixed(signal_energy(&UE->common_vars.rxdata[0][160+(2*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2)));
+ printf("rx_level Null symbol %f\n",10*log10(signal_energy_fp(r_re,r_im,1,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2,256+(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES))));
+ printf("rx_level data symbol %f\n",10*log10(signal_energy_fp(r_re,r_im,1,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2,256+(2*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES))));
+ }
+
+ if (eNB->frame_parms.Ncp == 0) { // normal prefix
+ pilot1 = 4;
+ pilot2 = 7;
+ pilot3 = 11;
+ } else { // extended prefix
+ pilot1 = 3;
+ pilot2 = 6;
+ pilot3 = 9;
+ }
+
+
+ start_meas(&UE->phy_proc_rx);
+
+ // Inner receiver scheduling for 3 slots
+
+ for (Ns=(2*subframe); Ns<((2*subframe)+3); Ns++) {
+ for (l=0; lofdm_demod_stats);
+ slot_fep(UE,
+ l,
+ Ns%20,
+ 0,
+ 0,
+ 0);
+ stop_meas(&UE->ofdm_demod_stats);
+
+ if (UE->perfect_ce==1) {
+ if (awgn_flag==0) {
+ for(k=0; knb_antenna_ports_eNB; aa++) {
+ for (aarx=0; aarxnb_antennas_rx; aarx++) {
+ for (i=0; iN_RB_DL*12; i++) {
+ ((int16_t *) UE->common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)(
+ eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP);
+ //printf("x=%d,AMP=%d\n",eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x,AMP);
+ ((int16_t *) UE->common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)(
+ eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP);
+
+ if (transmission_mode == 7){
+ //this should include the BF weights! Will not work for a random channel
+ if (UE->high_speed_flag==0) {
+ ((int16_t *)UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i]=(int16_t)(
+ eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP);
+ ((int16_t *)UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+1]=(int16_t)(
+ eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP);
+ //printf("**,x=%d,AMP=%d\n",eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x,AMP);
+ } else {
+ ((int16_t *)UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size)*2]=(int16_t)(
+ eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP);
+ ((int16_t *)UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size)*2]=(int16_t)(
+ eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP);
+
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ for(aa=0; aanb_antenna_ports_eNB; aa++) {
+ for (aarx=0; aarxnb_antennas_rx; aarx++) {
+ for (i=0; iN_RB_DL*12; i++) {
+ ((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP);
+ ((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0/2;
+ if (transmission_mode == 7) {
+ if (UE->high_speed_flag==0){
+ ((int16_t *) UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i]=(short)(AMP);
+ ((int16_t *) UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+1]=0/2;
+ } else {
+ ((int16_t *) UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size)*2]=(short)(AMP);
+ ((int16_t *) UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size)*2]=0/2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ if ((Ns==((2*subframe))) && (l==0)) {
+ lte_ue_measurements(UE,
+ subframe*UE->frame_parms.samples_per_tti,
+ 1,
+ 0);
+ /*
+ debug_msg("RX RSSI %d dBm, digital (%d, %d) dB, linear (%d, %d), avg rx power %d dB (%d lin), RX gain %d dB\n",
+ UE->measurements.rx_rssi_dBm[0] - ((UE->frame_parms.nb_antennas_rx==2) ? 3 : 0),
+ UE->measurements.wideband_cqi_dB[0][0],
+ UE->measurements.wideband_cqi_dB[0][1],
+ UE->measurements.wideband_cqi[0][0],
+ UE->measurements.wideband_cqi[0][1],
+ UE->measurements.rx_power_avg_dB[0],
+ UE->measurements.rx_power_avg[0],
+ UE->rx_total_gain_dB);
+ debug_msg("N0 %d dBm digital (%d, %d) dB, linear (%d, %d), avg noise power %d dB (%d lin)\n",
+ UE->measurements.n0_power_tot_dBm,
+ UE->measurements.n0_power_dB[0],
+ UE->measurements.n0_power_dB[1],
+ UE->measurements.n0_power[0],
+ UE->measurements.n0_power[1],
+ UE->measurements.n0_power_avg_dB,
+ UE->measurements.n0_power_avg);
+ debug_msg("Wideband CQI tot %d dB, wideband cqi avg %d dB\n",
+ UE->measurements.wideband_cqi_tot[0],
+ UE->measurements.wideband_cqi_avg[0]);
+ */
+
+ if (transmission_mode==5 || transmission_mode==6) {
+ if (pmi_feedback == 1) {
+ pmi_feedback = 0;
+ hold_channel = 1;
+ goto PMI_FEEDBACK;
+ }
+ }
+
+ }
+
+
+ if ((Ns==(2*subframe)) && (l==pilot1)) {// process symbols 0,1,2
+
+ if (dci_flag == 1) {
+ UE->UE_mode[0] = PUSCH;
+ start_meas(&UE->dlsch_rx_pdcch_stats);
+ rx_pdcch(&UE->common_vars,
+ UE->pdcch_vars,
+ &UE->frame_parms,
+ subframe,
+ 0,
+ (UE->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI,
+ UE->high_speed_flag,
+ 0);
+ stop_meas(&UE->dlsch_rx_pdcch_stats);
+ // overwrite number of pdcch symbols
+ UE->pdcch_vars[0]->num_pdcch_symbols = num_pdcch_symbols;
+
+ dci_cnt = dci_decoding_procedure(UE,
+ dci_alloc_rx,1,
+ eNB_id,
+ subframe);
+ //printf("dci_cnt %d\n",dci_cnt);
+
+ if (dci_cnt==0) {
+ dlsch_active = 0;
+
+ if (round==0) {
+ dci_errors++;
+ round=5;
+ errs[0]++;
+ //round_trials[0]++;
+
+ if (n_frames==1)
+ printf("DCI error trial %d errs[0] %d\n",trials,errs[0]);
+ }
+
+ // for (i=1;i<=round;i++)
+ // round_trials[i]--;
+ // round=5;
+ }
+
+ for (i=0; idlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->first_tx=1;
+
+ if ((dci_alloc_rx[i].rnti == n_rnti) &&
+ (generate_ue_dlsch_params_from_dci(0,
+ subframe,
+ dci_alloc_rx[i].dci_pdu,
+ dci_alloc_rx[i].rnti,
+ dci_alloc_rx[i].format,
+ UE->dlsch[0],
+ &UE->frame_parms,
+ UE->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI==0,
+ transmission_mode<7?0:transmission_mode))) {
+ //dump_dci(&UE->frame_parms,&dci_alloc_rx[i]);
+ coded_bits_per_codeword = get_G(&eNB->frame_parms,
+ UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->nb_rb,
+ UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->rb_alloc_even,
+ get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs),
+ UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->Nl,
+ UE->pdcch_vars[0]->num_pdcch_symbols,
+ 0,
+ subframe,
+ (transmission_mode<7?0:transmission_mode));
+ /*if (transmission_mode==7 && common_flag==0)
+ UE->dlsch[0][0]->harq_processes[0]->mimo_mode = TM7; */
+
+ /*
+ rate = (double)dlsch_tbs25[get_I_TBS(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs)][UE->dlsch[0][0]->nb_rb-1]/(coded_bits_per_codeword);
+ rate*=get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs);
+ */
+ printf("num_pdcch_symbols %d, G %d, TBS %d\n",UE->pdcch_vars[0]->num_pdcch_symbols,coded_bits_per_codeword,
+ UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->TBS);
+
+ dlsch_active = 1;
+ } else {
+ dlsch_active = 0;
+
+ if (round==0) {
+ dci_errors++;
+ errs[0]++;
+ //round_trials[0]++;
+ round=5;
+
+ if (n_frames==1)
+ printf("DCI misdetection trial %d\n",trials);
+
+ }
+
+ // for (i=1;i<=round;i++)
+ // round_trials[i]--;
+ // round=5;
+ }
+ }
+ } // if dci_flag==1
+ else { //dci_flag == 0
+
+ UE->pdcch_vars[0]->crnti = n_rnti;
+ UE->pdcch_vars[0]->num_pdcch_symbols = num_pdcch_symbols;
+
+ if (round == 0) UE->dlsch[0][0]->harq_processes[0]->first_tx=1;
+
+ switch (transmission_mode) {
+ case 1:
+ case 2:
+ case 7:
+ generate_ue_dlsch_params_from_dci(0,
+ subframe,
+ &DLSCH_alloc_pdu_1[0],
+ (common_flag==0)? C_RNTI : SI_RNTI,
+ (common_flag==0)? format1 : format1A,
+ UE->dlsch[0],
+ &UE->frame_parms,
+ UE->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI,
+ transmission_mode<7?0:transmission_mode);
+ /*if(transmission_mode==7 && common_flag==0)
+ UE->dlsch[0][0]->harq_processes[0]->mimo_mode = TM7;*/
+ break;
+
+ case 3:
+ // printf("Rate: TM3 (before) round %d (%d) first_tx %d\n",round,UE->dlsch[0][0]->harq_processes[0]->round,UE->dlsch[0][0]->harq_processes[0]->first_tx);
+ generate_ue_dlsch_params_from_dci(0,
+ subframe,
+ &DLSCH_alloc_pdu_1[0],
+ (common_flag==0)? C_RNTI : SI_RNTI,
+ (common_flag==0)? format2A : format1A,
+ UE->dlsch[0],
+ &UE->frame_parms,
+ UE->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI,
+ 0);
+ // printf("Rate: TM3 (after) round %d (%d) first_tx %d\n",round,UE->dlsch[0][0]->harq_processes[0]->round,UE->dlsch[0][0]->harq_processes[0]->first_tx);
+ break;
+
+ case 4:
+ generate_ue_dlsch_params_from_dci(0,
+ subframe,
+ &DLSCH_alloc_pdu_1[0],
+ (common_flag==0)? C_RNTI : SI_RNTI,
+ (common_flag==0)? format2 : format1A,
+ UE->dlsch[0],
+ &UE->frame_parms,
+ UE->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI,
+ 0);
+ break;
+
+ case 5:
+ case 6:
+ generate_ue_dlsch_params_from_dci(0,
+ subframe,
+ &DLSCH_alloc_pdu2_1E[0],
+ C_RNTI,
+ format1E_2A_M10PRB,
+ UE->dlsch[0],
+ &UE->frame_parms,
+ UE->pdsch_config_dedicated,
+ SI_RNTI,
+ 0,
+ P_RNTI,
+ 0);
+ break;
+
+ }
+
+ dlsch_active = 1;
+ } // if dci_flag == 1
+ }
+
+ if (dlsch_active == 1) {
+
+ if (transmission_mode==7) {
+ if (UE->frame_parms.Ncp==0) {
+ if ((Ns==(2*subframe) && ((l==3) || (l==6))) ||
+ (Ns==(1+2*subframe) && ((l==2) || (l==5)))) {
+ if (perfect_ce==0)
+ lte_dl_bf_channel_estimation(UE,eNB_id,0,Ns,5,l+7*(Ns%2==1));
+ }
+ } else {
+ msg("Beamforming channel estimation not supported yet for TM7 extented CP.\n");
+ }
+ }
+
+ if ((Ns==(1+(2*subframe))) && (l==0)) {// process PDSCH symbols 1,2,3,4,5,(6 Normal Prefix)
+
+ if ((transmission_mode == 5) &&
+ (UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->dl_power_off==0) &&
+ (UE->use_ia_receiver ==1)) {
+ dual_stream_UE = 1;
+ } else {
+ dual_stream_UE = 0;
+ }
+
+
+ start_meas(&UE->dlsch_llr_stats);
+
+ for (m=UE->pdcch_vars[0]->num_pdcch_symbols;
+ mpdcch_vars[0]->num_pdcch_symbols)?1:0,
+ dual_stream_UE,
+ i_mod,
+ UE->dlsch[0][0]->current_harq_pid)==-1) {
+ dlsch_active = 0;
+ break;
+ }
+ }
+
+ stop_meas(&UE->dlsch_llr_stats);
+ }
+
+ if ((Ns==(1+(2*subframe))) && (l==pilot1)) {
+ // process symbols (6 Extended Prefix),7,8,9
+ start_meas(&UE->dlsch_llr_stats);
+
+ for (m=pilot2;
+ mdlsch[0][0]->current_harq_pid)==-1) {
+ dlsch_active=0;
+ break;
+ }
+ }
+
+ stop_meas(&UE->dlsch_llr_stats);
+ }
+
+ if ((Ns==(2+(2*subframe))) && (l==0)) { // process symbols 10,11,(12,13 Normal Prefix) do deinterleaving for TTI
+ start_meas(&UE->dlsch_llr_stats);
+
+ for (m=pilot3;
+ mframe_parms.symbols_per_tti;
+ m++) {
+ //printf("m=%d\n",m);
+ if (rx_pdsch(UE,
+ PDSCH,
+ eNB_id,
+ eNB_id_i,
+ subframe,
+ m,
+ 0,
+ dual_stream_UE,
+ i_mod,
+ UE->dlsch[0][0]->current_harq_pid)==-1) {
+ dlsch_active=0;
+ break;
+ }
+ }
+
+ stop_meas(&UE->dlsch_llr_stats);
+ }
+
+
+ if (test_perf ==0 ) {
+ if ((n_frames==1) && (Ns==(2+(2*subframe))) && (l==0)) {
+ write_output("ch0.m","ch0",eNB2UE[0]->ch[0],eNB2UE[0]->channel_length,1,8);
+
+ if (eNB->frame_parms.nb_antennas_tx>1)
+ write_output("ch1.m","ch1",eNB2UE[0]->ch[eNB->frame_parms.nb_antennas_rx],eNB2UE[0]->channel_length,1,8);
+
+ //common vars
+ //write_output("rxsig0.m","rxs0", &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1);
+ write_output("rxsig0.m","rxs0", &UE->common_vars.rxdata[0][subframe*UE->frame_parms.samples_per_tti],UE->frame_parms.samples_per_tti,1,1);
+ //write_output("rxsigF0.m","rxsF0", &UE->common_vars.rxdataF[0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+ write_output("rxsigF0.m","rxsF0", &UE->common_vars.rxdataF[0][0],UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+
+ if (UE->frame_parms.nb_antennas_rx>1) {
+ write_output("rxsig1.m","rxs1", UE->common_vars.rxdata[1],UE->frame_parms.samples_per_tti,1,1);
+ write_output("rxsigF1.m","rxsF1", UE->common_vars.rxdataF[1],UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+ }
+
+ write_output("dlsch00_r0.m","dl00_r0",
+ &(UE->common_vars.dl_ch_estimates[eNB_id][0][0]),
+ UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+
+ if (UE->frame_parms.nb_antennas_rx>1)
+ write_output("dlsch01_r0.m","dl01_r0",
+ &(UE->common_vars.dl_ch_estimates[eNB_id][1][0]),
+ UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+
+ if (eNB->frame_parms.nb_antennas_tx>1)
+ write_output("dlsch10_r0.m","dl10_r0",
+ &(UE->common_vars.dl_ch_estimates[eNB_id][2][0]),
+ UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+
+ if ((UE->frame_parms.nb_antennas_rx>1) && (eNB->frame_parms.nb_antennas_tx>1))
+ write_output("dlsch11_r0.m","dl11_r0",
+ &(UE->common_vars.dl_ch_estimates[eNB_id][3][0]),
+ UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1);
+
+ //pdsch_vars
+ dump_dlsch2(UE,eNB_id,coded_bits_per_codeword,round);
+ //dump_dlsch2(UE,eNB_id_i,coded_bits_per_codeword);
+ write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4);
+
+ //pdcch_vars
+ write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1);
+ write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[eNB_id]->dl_ch_estimates_ext[0],300*3,1,1);
+
+ write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[eNB_id]->rxdataF_comp[0],4*300,1,1);
+ write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[eNB_id]->llr,2400,1,4);
+
+ }
+ }
+ }
+ }
+ }
+
+ //saving PMI in case of Transmission Mode > 5
+
+ if(abstx) {
+ if (trials==0 && round==0 && transmission_mode>=5 && transmission_mode<7) {
+ for (iii=0; iiipdsch_vars[eNB_id]->pmi_ext[iii]),(UE->pdsch_vars[eNB_id_i]->pmi_ext[iii]));
+ fprintf(csv_fd,"%x,%x,",(UE->pdsch_vars[eNB_id]->pmi_ext[iii]),(UE->pdsch_vars[eNB_id]->pmi_ext[iii]));
+ printf("%x ",(UE->pdsch_vars[eNB_id]->pmi_ext[iii]));
+ }
+ }
+ }
+
+ for (int cw=Kmimo-1; cw>=0; cw--) {
+ UE->dlsch[0][cw]->rnti = (common_flag==0) ? n_rnti: SI_RNTI;
+ coded_bits_per_codeword = get_G(&eNB->frame_parms,
+ eNB->dlsch[0][cw]->harq_processes[0]->nb_rb,
+ eNB->dlsch[0][cw]->harq_processes[0]->rb_alloc,
+ get_Qm(eNB->dlsch[0][cw]->harq_processes[0]->mcs),
+ eNB->dlsch[0][cw]->harq_processes[0]->Nl,
+ num_pdcch_symbols,
+ 0,
+ subframe,
+ (transmission_mode<7?0:transmission_mode));
+
+ UE->dlsch[0][cw]->harq_processes[UE->dlsch[0][cw]->current_harq_pid]->G = coded_bits_per_codeword;
+
+
+
+ // calculate uncoded BLER
+ uncoded_ber=0;
+ for (i=0;idlsch[0][0]->harq_processes[0]->e[i] != (UE->pdsch_vars[0]->llr[0][i]<0)) {
+ uncoded_ber_bit[i] = 1;
+ uncoded_ber++;
+ }
+ else
+ uncoded_ber_bit[i] = 0;
+
+ uncoded_ber/=coded_bits_per_codeword;
+ avg_ber += uncoded_ber;
+
+ if (n_frames==1)
+ write_output("uncoded_ber_bit.m","uncoded_ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0);
+
+
+ start_meas(&UE->dlsch_unscrambling_stats);
+ dlsch_unscrambling(&UE->frame_parms,
+ 0,
+ UE->dlsch[0][cw],
+ coded_bits_per_codeword,
+ UE->pdsch_vars[eNB_id]->llr[cw],
+ 0,
+ subframe<<1);
+ stop_meas(&UE->dlsch_unscrambling_stats);
+
+ start_meas(&UE->dlsch_decoding_stats);
+ ret = dlsch_decoding(UE,
+ UE->pdsch_vars[eNB_id]->llr[cw],
+ &UE->frame_parms,
+ UE->dlsch[0][cw],
+ UE->dlsch[0][cw]->harq_processes[UE->dlsch[0][cw]->current_harq_pid],
+ subframe,
+ UE->dlsch[0][cw]->current_harq_pid,
+ 1,llr8_flag);
+ stop_meas(&UE->dlsch_decoding_stats);
+
+ if (cw==1) {
+ if (ret <= UE->dlsch[0][cw]->max_turbo_iterations) {
+ } else {
+ errs2[round]++;
+ }
+ }
+ }
+
+
+ stop_meas(&UE->phy_proc_rx);
+
+
+ if (ret <= UE->dlsch[0][0]->max_turbo_iterations) {
+
+ avg_iter += ret;
+ iter_trials++;
+
+ if (n_frames==1)
+ printf("No DLSCH errors found (round %d),uncoded ber %f\n",round,uncoded_ber);
+
+ UE->total_TBS[eNB_id] = UE->total_TBS[eNB_id] + UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->TBS;
+ TB0_active = 0;
+
+ if (UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->mimo_mode == LARGE_CDD) { //try to decode second stream using SIC
+ /*
+ for (round = 0 ; round < UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->round ; round++) {
+ // re-encoding of first stream
+ dlsch0_ue_harq = UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid];
+ dlsch0_eNB_harq = UE->dlsch[eNB_id]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid];
+ dlsch0_eNB_harq->mimo_mode = LARGE_CDD;
+ dlsch0_eNB_harq->rb_alloc[0] = dlsch0_ue_harq->rb_alloc_even[0];
+ dlsch0_eNB_harq->nb_rb = dlsch0_ue_harq->nb_rb;
+ dlsch0_eNB_harq->mcs = dlsch0_ue_harq->mcs;
+ dlsch0_eNB_harq->rvidx = dlsch0_ue_harq->rvidx;
+ dlsch0_eNB_harq->Nl = dlsch0_ue_harq->Nl;
+
+ dlsch0_eNB_harq->TBS = dlsch0_ue_harq->TBS;
+ dlsch0_eNB_harq->dl_power_off = dlsch0_ue_harq->dl_power_off;
+ dlsch0_eNB_harq->status = dlsch0_ue_harq->status;
+
+ UE->dlsch[eNB_id]->active = UE->dlsch[eNB_id][0]->active;
+ UE->dlsch[eNB_id]->rnti = UE->dlsch[eNB_id][0]->rnti;
+
+ dlsch_encoding(UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->b,
+ &UE->frame_parms,
+ num_pdcch_symbols,
+ UE->dlsch[0],
+ 0,subframe,
+ &UE->dlsch_rate_matching_stats,
+ &UE->dlsch_turbo_encoding_stats,
+ &UE->dlsch_interleaving_stats
+ );
+
+ //scrambling
+
+ //modulation
+
+ //stripping (from matched filter output?)
+
+ //detection of second stream
+ }
+ */
+ }
+ } else {
+ errs[round]++;
+
+ avg_iter += ret-1;
+ iter_trials++;
+
+ if (n_frames==1) {
+ //if ((n_frames==1) || (SNR>=30))
+ printf("DLSCH errors found (round %d), uncoded ber %f\n",round,uncoded_ber);
+
+ for (s=0; sdlsch[0][0]->harq_processes[0]->C; s++) {
+ if (sdlsch[0][0]->harq_processes[0]->Cminus)
+ Kr = UE->dlsch[0][0]->harq_processes[0]->Kminus;
+ else
+ Kr = UE->dlsch[0][0]->harq_processes[0]->Kplus;
+
+ Kr_bytes = Kr>>3;
+
+ printf("Decoded_output (Segment %d):\n",s);
+
+ for (i=0; idlsch[0][0]->harq_processes[0]->c[s][i],UE->dlsch[0][0]->harq_processes[0]->c[s][i]^eNB->dlsch[0][0]->harq_processes[0]->c[s][i]);
+ }
+
+ sprintf(fname,"rxsig0_r%d.m",round);
+ sprintf(vname,"rxs0_r%d",round);
+ write_output(fname,vname, &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1);
+ sprintf(fname,"rxsigF0_r%d.m",round);
+ sprintf(vname,"rxs0F_r%d",round);
+ write_output(fname,vname, &UE->common_vars.rxdataF[0][0],2*UE->frame_parms.ofdm_symbol_size*nsymb,2,1);
+
+ if (UE->frame_parms.nb_antennas_rx>1) {
+ sprintf(fname,"rxsig1_r%d.m",round);
+ sprintf(vname,"rxs1_r%d.m",round);
+ write_output(fname,vname, UE->common_vars.rxdata[1],UE->frame_parms.samples_per_tti,1,1);
+ sprintf(fname,"rxsig1F_r%d.m",round);
+ sprintf(vname,"rxs1F_r%d.m",round);
+ write_output(fname,vname, UE->common_vars.rxdataF[1],2*UE->frame_parms.ofdm_symbol_size*nsymb,2,1);
+ }
+
+ sprintf(fname,"dlsch00_r%d.m",round);
+ sprintf(vname,"dl00_r%d",round);
+ write_output(fname,vname,
+ &(UE->common_vars.dl_ch_estimates[eNB_id][0][0]),
+ UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+
+ if (UE->frame_parms.nb_antennas_rx>1) {
+ sprintf(fname,"dlsch01_r%d.m",round);
+ sprintf(vname,"dl01_r%d",round);
+ write_output(fname,vname,
+ &(UE->common_vars.dl_ch_estimates[eNB_id][1][0]),
+ UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1);
+ }
+
+ if (eNB->frame_parms.nb_antennas_tx>1) {
+ sprintf(fname,"dlsch10_r%d.m",round);
+ sprintf(vname,"dl10_r%d",round);
+ write_output(fname,vname,
+ &(UE->common_vars.dl_ch_estimates[eNB_id][2][0]),
+ UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1);
+ }
+
+ if ((UE->frame_parms.nb_antennas_rx>1) && (eNB->frame_parms.nb_antennas_tx>1)) {
+ sprintf(fname,"dlsch11_r%d.m",round);
+ sprintf(vname,"dl11_r%d",round);
+ write_output(fname,vname,
+ &(UE->common_vars.dl_ch_estimates[eNB_id][3][0]),
+ UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1);
+ }
+
+ //pdsch_vars
+ dump_dlsch2(UE,eNB_id,coded_bits_per_codeword,round);
+ /*
+ write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4);
+ write_output("dlsch_ber_bit.m","ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0);
+ write_output("dlsch_w.m","w",eNB->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,4);
+ write_output("dlsch_w.m","w",UE->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,0);
+ */
+
+ if (round == 3) exit(-1);
+ }
+
+ // printf("round %d errors %d/%d\n",round,errs[round],trials);
+
+ round++;
+ // UE->dlsch[0][0]->harq_processes[0]->round++;
+ }
+
+ if (xforms==1) {
+ phy_scope_UE(form_ue,
+ UE,
+ eNB_id,
+ 0,// UE_id
+ subframe);
+ }
+
+ } //round
+
+ // printf("\n");
+
+ if ((errs[0]>=n_frames/10) && (trials>(n_frames/2)))
+ break;
+
+ //len = chbch_stats_read(stats_buffer,NULL,0,4096);
+ //printf("%s\n\n",stats_buffer);
+
+ if (UE->proc.proc_rxtx[subframe&1].frame_rx % 10 == 0) {
+ UE->bitrate[eNB_id] = (UE->total_TBS[eNB_id] - UE->total_TBS_last[eNB_id])*10;
+ LOG_D(PHY,"[UE %d] Calculating bitrate: total_TBS = %d, total_TBS_last = %d, bitrate = %d kbits/s\n",UE->Mod_id,UE->total_TBS[eNB_id],UE->total_TBS_last[eNB_id],
+ UE->bitrate[eNB_id]/1000);
+ UE->total_TBS_last[eNB_id] = UE->total_TBS[eNB_id];
+ }
+
+
+ UE->proc.proc_rxtx[subframe&1].frame_rx++;
+
+ /* calculate the total processing time for each packet,
+ * get the max, min, and number of packets that exceed t>2000us
+ */
+ double t_tx = (double)eNB->phy_proc_tx.p_time/cpu_freq_GHz/1000.0;
+ double t_tx_ifft = (double)eNB->ofdm_mod_stats.p_time/cpu_freq_GHz/1000.0;
+ double t_tx_mod = (double)eNB->dlsch_modulation_stats.p_time/cpu_freq_GHz/1000.0;
+ double t_tx_enc = (double)eNB->dlsch_encoding_stats.p_time/cpu_freq_GHz/1000.0;
+
+
+ double t_rx = (double)UE->phy_proc_rx.p_time/cpu_freq_GHz/1000.0;
+ double t_rx_fft = (double)UE->ofdm_demod_stats.p_time/cpu_freq_GHz/1000.0;
+ double t_rx_demod = (double)UE->dlsch_rx_pdcch_stats.p_time/cpu_freq_GHz/1000.0;
+ double t_rx_dec = (double)UE->dlsch_decoding_stats.p_time/cpu_freq_GHz/1000.0;
+
+ if (t_tx > t_tx_max)
+ t_tx_max = t_tx;
+
+ if (t_tx < t_tx_min)
+ t_tx_min = t_tx;
+
+ if (t_rx > t_rx_max)
+ t_rx_max = t_rx;
+
+ if (t_rx < t_rx_min)
+ t_rx_min = t_rx;
+
+ if (t_tx > 2000)
+ n_tx_dropped++;
+
+ if (t_rx > 2000)
+ n_rx_dropped++;
+
+ push_front(&time_vector_tx, t_tx);
+ push_front(&time_vector_tx_ifft, t_tx_ifft);
+ push_front(&time_vector_tx_mod, t_tx_mod);
+ push_front(&time_vector_tx_enc, t_tx_enc);
+
+ push_front(&time_vector_rx, t_rx);
+ push_front(&time_vector_rx_fft, t_rx_fft);
+ push_front(&time_vector_rx_demod, t_rx_demod);
+ push_front(&time_vector_rx_dec, t_rx_dec);
+
+
+ } //trials
+
+ // round_trials[0]: number of code word : goodput the protocol
+ double table_tx[time_vector_tx.size];
+ totable(table_tx, &time_vector_tx);
+ double table_tx_ifft[time_vector_tx_ifft.size];
+ totable(table_tx_ifft, &time_vector_tx_ifft);
+ double table_tx_mod[time_vector_tx_mod.size];
+ totable(table_tx_mod, &time_vector_tx_mod);
+ double table_tx_enc[time_vector_tx_enc.size];
+ totable(table_tx_enc, &time_vector_tx_enc);
+
+ double table_rx[time_vector_rx.size];
+ totable(table_rx, &time_vector_rx);
+ double table_rx_fft[time_vector_rx_fft.size];
+ totable(table_rx_fft, &time_vector_rx_fft);
+ double table_rx_demod[time_vector_rx_demod.size];
+ totable(table_rx_demod, &time_vector_rx_demod);
+ double table_rx_dec[time_vector_rx_dec.size];
+ totable(table_rx_dec, &time_vector_rx_dec);
+
+
+ // sort table
+ qsort (table_tx, time_vector_tx.size, sizeof(double), &compare);
+ qsort (table_rx, time_vector_rx.size, sizeof(double), &compare);
+
+ if (dump_table == 1 ) {
+ set_component_filelog(USIM); // file located in /tmp/usim.txt
+ int n;
+ LOG_F(USIM,"The transmitter raw data: \n");
+
+ for (n=0; n< time_vector_tx.size; n++) {
+ printf("%f ", table_tx[n]);
+ LOG_F(USIM,"%f ", table_tx[n]);
+ }
+
+ LOG_F(USIM,"\n");
+ LOG_F(USIM,"The receiver raw data: \n");
+
+ for (n=0; n< time_vector_rx.size; n++) {
+ // printf("%f ", table_rx[n]);
+ LOG_F(USIM,"%f ", table_rx[n]);
+ }
+
+ LOG_F(USIM,"\n");
+ }
+
+ double tx_median = table_tx[time_vector_tx.size/2];
+ double tx_q1 = table_tx[time_vector_tx.size/4];
+ double tx_q3 = table_tx[3*time_vector_tx.size/4];
+
+ double tx_ifft_median = table_tx_ifft[time_vector_tx_ifft.size/2];
+ double tx_ifft_q1 = table_tx_ifft[time_vector_tx_ifft.size/4];
+ double tx_ifft_q3 = table_tx_ifft[3*time_vector_tx_ifft.size/4];
+
+ double tx_mod_median = table_tx_mod[time_vector_tx_mod.size/2];
+ double tx_mod_q1 = table_tx_mod[time_vector_tx_mod.size/4];
+ double tx_mod_q3 = table_tx_mod[3*time_vector_tx_mod.size/4];
+
+ double tx_enc_median = table_tx_enc[time_vector_tx_enc.size/2];
+ double tx_enc_q1 = table_tx_enc[time_vector_tx_enc.size/4];
+ double tx_enc_q3 = table_tx_enc[3*time_vector_tx_enc.size/4];
+
+ double rx_median = table_rx[time_vector_rx.size/2];
+ double rx_q1 = table_rx[time_vector_rx.size/4];
+ double rx_q3 = table_rx[3*time_vector_rx.size/4];
+
+ double rx_fft_median = table_rx_fft[time_vector_rx_fft.size/2];
+ double rx_fft_q1 = table_rx_fft[time_vector_rx_fft.size/4];
+ double rx_fft_q3 = table_rx_fft[3*time_vector_rx_fft.size/4];
+
+ double rx_demod_median = table_rx_demod[time_vector_rx_demod.size/2];
+ double rx_demod_q1 = table_rx_demod[time_vector_rx_demod.size/4];
+ double rx_demod_q3 = table_rx_demod[3*time_vector_rx_demod.size/4];
+
+ double rx_dec_median = table_rx_dec[time_vector_rx_dec.size/2];
+ double rx_dec_q1 = table_rx_dec[time_vector_rx_dec.size/4];
+ double rx_dec_q3 = table_rx_dec[3*time_vector_rx_dec.size/4];
+
+ double std_phy_proc_tx=0;
+ double std_phy_proc_tx_ifft=0;
+ double std_phy_proc_tx_mod=0;
+ double std_phy_proc_tx_enc=0;
+
+ double std_phy_proc_rx=0;
+ double std_phy_proc_rx_fft=0;
+ double std_phy_proc_rx_demod=0;
+ double std_phy_proc_rx_dec=0;
+
+ effective_rate = ((double)(round_trials[0]-dci_errors)/((double)round_trials[0] + round_trials[1] + round_trials[2] + round_trials[3]));
+
+ printf("\n**********************SNR = %f dB (tx_lev %f, sigma2_dB %f)**************************\n",
+ SNR,
+ (double)tx_lev_dB+10*log10(UE->frame_parms.ofdm_symbol_size/(NB_RB*12)),
+ sigma2_dB);
+
+ printf("Errors (%d(%d)/%d %d/%d %d/%d %d/%d), Pe = (%e,%e,%e,%e), dci_errors %d/%d, Pe = %e => effective rate %f (%2.1f%%,%f, %f), normalized delay %f (%f)\n",
+ errs[0],
+ errs2[0],
+ round_trials[0],
+ errs[1],
+ round_trials[0],
+ errs[2],
+ round_trials[0],
+ errs[3],
+ round_trials[0],
+ (double)errs[0]/(round_trials[0]),
+ (double)errs[1]/(round_trials[0]),
+ (double)errs[2]/(round_trials[0]),
+ (double)errs[3]/(round_trials[0]),
+ dci_errors,
+ round_trials[0],
+ (double)dci_errors/(round_trials[0]),
+ rate*effective_rate,
+ 100*effective_rate,
+ rate,
+ rate*get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs),
+ (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/
+ (double)eNB->dlsch[0][0]->harq_processes[0]->TBS,
+ (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0]));
+
+ if (print_perf==1) {
+ printf("eNB TX function statistics (per 1ms subframe)\n\n");
+ std_phy_proc_tx = sqrt((double)eNB->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+ 2)/eNB->phy_proc_tx.trials - pow((double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000,2));
+ printf("Total PHY proc tx :%f us (%d trials)\n",(double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000.0,eNB->phy_proc_tx.trials);
+ printf("|__ Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3,
+ n_tx_dropped);
+ std_phy_proc_tx_ifft = sqrt((double)eNB->ofdm_mod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+ 2)/eNB->ofdm_mod_stats.trials - pow((double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000,2));
+ printf("OFDM_mod time :%f us (%d trials)\n",(double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,eNB->ofdm_mod_stats.trials);
+ printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_ifft, tx_ifft_median, tx_ifft_q1, tx_ifft_q3);
+ std_phy_proc_tx_mod = sqrt((double)eNB->dlsch_modulation_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+ 2)/eNB->dlsch_modulation_stats.trials - pow((double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000,2));
+ printf("DLSCH modulation time :%f us (%d trials)\n",(double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000.0,
+ eNB->dlsch_modulation_stats.trials);
+ printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_mod, tx_mod_median, tx_mod_q1, tx_mod_q3);
+ printf("DLSCH scrambling time :%f us (%d trials)\n",(double)eNB->dlsch_scrambling_stats.diff/eNB->dlsch_scrambling_stats.trials/cpu_freq_GHz/1000.0,
+ eNB->dlsch_scrambling_stats.trials);
+ std_phy_proc_tx_enc = sqrt((double)eNB->dlsch_encoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+ 2)/eNB->dlsch_encoding_stats.trials - pow((double)eNB->dlsch_encoding_stats.diff/eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000,2));
+ printf("DLSCH encoding time :%f us (%d trials)\n",(double)eNB->dlsch_encoding_stats.diff/eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000.0,
+ eNB->dlsch_modulation_stats.trials);
+ printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_enc, tx_enc_median, tx_enc_q1, tx_enc_q3);
+ printf("|__ DLSCH turbo encoding time :%f us (%d trials)\n",
+ ((double)eNB->dlsch_turbo_encoding_stats.trials/eNB->dlsch_encoding_stats.trials)*(double)
+ eNB->dlsch_turbo_encoding_stats.diff/eNB->dlsch_turbo_encoding_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_turbo_encoding_stats.trials);
+ printf("|__ DLSCH rate-matching time :%f us (%d trials)\n",
+ ((double)eNB->dlsch_rate_matching_stats.trials/eNB->dlsch_encoding_stats.trials)*(double)
+ eNB->dlsch_rate_matching_stats.diff/eNB->dlsch_rate_matching_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_rate_matching_stats.trials);
+ printf("|__ DLSCH sub-block interleaving time :%f us (%d trials)\n",
+ ((double)eNB->dlsch_interleaving_stats.trials/eNB->dlsch_encoding_stats.trials)*(double)
+ eNB->dlsch_interleaving_stats.diff/eNB->dlsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_interleaving_stats.trials);
+
+ printf("\n\nUE RX function statistics (per 1ms subframe)\n\n");
+ std_phy_proc_rx = sqrt((double)UE->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+ 2)/UE->phy_proc_rx.trials - pow((double)UE->phy_proc_rx.diff/UE->phy_proc_rx.trials/cpu_freq_GHz/1000,2));
+ printf("Total PHY proc rx :%f us (%d trials)\n",(double)UE->phy_proc_rx.diff/UE->phy_proc_rx.trials/cpu_freq_GHz/1000.0,
+ UE->phy_proc_rx.trials*2/3);
+ printf("|__Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median,
+ rx_q1, rx_q3, n_rx_dropped);
+ std_phy_proc_rx_fft = sqrt((double)UE->ofdm_demod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+ 2)/UE->ofdm_demod_stats.trials - pow((double)UE->ofdm_demod_stats.diff/UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000,2));
+ printf("DLSCH OFDM demodulation and channel_estimation time :%f us (%d trials)\n",(nsymb)*(double)UE->ofdm_demod_stats.diff/UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0,
+ UE->ofdm_demod_stats.trials*2/3);
+ printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_fft, rx_fft_median, rx_fft_q1, rx_fft_q3);
+ printf("|__ DLSCH rx dft :%f us (%d trials)\n",
+ (nsymb*UE->frame_parms.nb_antennas_rx)*(double)UE->rx_dft_stats.diff/UE->rx_dft_stats.trials/cpu_freq_GHz/1000.0,UE->rx_dft_stats.trials*2/3);
+ printf("|__ DLSCH channel estimation time :%f us (%d trials)\n",
+ (4.0)*(double)UE->dlsch_channel_estimation_stats.diff/UE->dlsch_channel_estimation_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_channel_estimation_stats.trials*2/3);
+ printf("|__ DLSCH frequency offset estimation time :%f us (%d trials)\n",
+ (4.0)*(double)UE->dlsch_freq_offset_estimation_stats.diff/UE->dlsch_freq_offset_estimation_stats.trials/cpu_freq_GHz/1000.0,
+ UE->dlsch_freq_offset_estimation_stats.trials*2/3);
+ printf("DLSCH rx pdcch :%f us (%d trials)\n",(double)UE->dlsch_rx_pdcch_stats.diff/UE->dlsch_rx_pdcch_stats.trials/cpu_freq_GHz/1000.0,
+ UE->dlsch_rx_pdcch_stats.trials);
+ std_phy_proc_rx_demod = sqrt((double)UE->dlsch_llr_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+ 2)/UE->dlsch_llr_stats.trials - pow((double)UE->dlsch_llr_stats.diff/UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000,2));
+ printf("DLSCH Channel Compensation and LLR generation time :%f us (%d trials)\n",(3)*(double)UE->dlsch_llr_stats.diff/UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000.0,
+ UE->dlsch_llr_stats.trials/3);
+ printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_demod, rx_demod_median, rx_demod_q1, rx_demod_q3);
+ printf("DLSCH unscrambling time :%f us (%d trials)\n",(double)UE->dlsch_unscrambling_stats.diff/UE->dlsch_unscrambling_stats.trials/cpu_freq_GHz/1000.0,
+ UE->dlsch_unscrambling_stats.trials);
+ std_phy_proc_rx_dec = sqrt((double)UE->dlsch_decoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+ 2)/UE->dlsch_decoding_stats.trials - pow((double)UE->dlsch_decoding_stats.diff/UE->dlsch_decoding_stats.trials/cpu_freq_GHz/1000,2));
+ printf("DLSCH Decoding time (%02.2f Mbit/s, avg iter %1.2f) :%f us (%d trials, max %f)\n",
+ eNB->dlsch[0][0]->harq_processes[0]->TBS/1000.0,(double)avg_iter/iter_trials,
+ (double)UE->dlsch_decoding_stats.diff/UE->dlsch_decoding_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_decoding_stats.trials,
+ (double)UE->dlsch_decoding_stats.max/cpu_freq_GHz/1000.0);
+ printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_dec, rx_dec_median, rx_dec_q1, rx_dec_q3);
+ printf("|__ DLSCH Rate Unmatching :%f us (%d trials)\n",
+ (double)UE->dlsch_rate_unmatching_stats.diff/UE->dlsch_rate_unmatching_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_rate_unmatching_stats.trials);
+ printf("|__ DLSCH Turbo Decoding(%d bits) :%f us (%d trials)\n",
+ UE->dlsch[0][0]->harq_processes[0]->Cminus ? UE->dlsch[0][0]->harq_processes[0]->Kminus : UE->dlsch[0][0]->harq_processes[0]->Kplus,
+ (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_turbo_decoding_stats.trials);
+ printf(" |__ init %f us (cycles/iter %f, %d trials)\n",
+ (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/cpu_freq_GHz/1000.0,
+ (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/((double)avg_iter/iter_trials),
+ UE->dlsch_tc_init_stats.trials);
+ printf(" |__ alpha %f us (cycles/iter %f, %d trials)\n",
+ (double)UE->dlsch_tc_alpha_stats.diff/UE->dlsch_tc_alpha_stats.trials/cpu_freq_GHz/1000.0,
+ (double)UE->dlsch_tc_alpha_stats.diff/UE->dlsch_tc_alpha_stats.trials*2,
+ UE->dlsch_tc_alpha_stats.trials);
+ printf(" |__ beta %f us (cycles/iter %f,%d trials)\n",
+ (double)UE->dlsch_tc_beta_stats.diff/UE->dlsch_tc_beta_stats.trials/cpu_freq_GHz/1000.0,
+ (double)UE->dlsch_tc_beta_stats.diff/UE->dlsch_tc_beta_stats.trials*2,
+ UE->dlsch_tc_beta_stats.trials);
+ printf(" |__ gamma %f us (cycles/iter %f,%d trials)\n",
+ (double)UE->dlsch_tc_gamma_stats.diff/UE->dlsch_tc_gamma_stats.trials/cpu_freq_GHz/1000.0,
+ (double)UE->dlsch_tc_gamma_stats.diff/UE->dlsch_tc_gamma_stats.trials*2,
+ UE->dlsch_tc_gamma_stats.trials);
+ printf(" |__ ext %f us (cycles/iter %f,%d trials)\n",
+ (double)UE->dlsch_tc_ext_stats.diff/UE->dlsch_tc_ext_stats.trials/cpu_freq_GHz/1000.0,
+ (double)UE->dlsch_tc_ext_stats.diff/UE->dlsch_tc_ext_stats.trials*2,
+ UE->dlsch_tc_ext_stats.trials);
+ printf(" |__ intl1 %f us (cycles/iter %f,%d trials)\n",
+ (double)UE->dlsch_tc_intl1_stats.diff/UE->dlsch_tc_intl1_stats.trials/cpu_freq_GHz/1000.0,
+ (double)UE->dlsch_tc_intl1_stats.diff/UE->dlsch_tc_intl1_stats.trials,
+ UE->dlsch_tc_intl1_stats.trials);
+ printf(" |__ intl2+HD+CRC %f us (cycles/iter %f,%d trials)\n",
+ (double)UE->dlsch_tc_intl2_stats.diff/UE->dlsch_tc_intl2_stats.trials/cpu_freq_GHz/1000.0,
+ (double)UE->dlsch_tc_intl2_stats.diff/UE->dlsch_tc_intl2_stats.trials,
+ UE->dlsch_tc_intl2_stats.trials);
+ }
+
+ if ((transmission_mode != 3) && (transmission_mode != 4)) {
+ fprintf(bler_fd,"%f;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d\n",
+ SNR,
+ mcs1,
+ eNB->dlsch[0][0]->harq_processes[0]->TBS,
+ rate,
+ errs[0],
+ round_trials[0],
+ errs[1],
+ round_trials[1],
+ errs[2],
+ round_trials[2],
+ errs[3],
+ round_trials[3],
+ dci_errors);
+ } else {
+ fprintf(bler_fd,"%f;%d;%d;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d\n",
+ SNR,
+ mcs1,mcs2,
+ eNB->dlsch[0][0]->harq_processes[0]->TBS,
+ eNB->dlsch[0][1]->harq_processes[0]->TBS,
+ rate,
+ errs[0],
+ round_trials[0],
+ errs[1],
+ round_trials[1],
+ errs[2],
+ round_trials[2],
+ errs[3],
+ round_trials[3],
+ dci_errors);
+ }
+
+
+ if(abstx) { //ABSTRACTION
+ blerr[0] = (double)errs[0]/(round_trials[0]);
+
+ if(num_rounds>1) {
+ blerr[1] = (double)errs[1]/(round_trials[1]);
+ blerr[2] = (double)errs[2]/(round_trials[2]);
+ blerr[3] = (double)errs[3]/(round_trials[3]);
+ fprintf(csv_fd,"%e,%e,%e,%e;\n",blerr[0],blerr[1],blerr[2],blerr[3]);
+ } else {
+ fprintf(csv_fd,"%e;\n",blerr[0]);
+ }
+ } //ABStraction
+
+ if ( (test_perf != 0) && (100 * effective_rate > test_perf )) {
+ //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; err0; trials0; err1; trials1; err2; trials2; err3; trials3; dci_err\n");
+ if ((transmission_mode != 3) && (transmission_mode != 4)) {
+ fprintf(time_meas_fd,"%f;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d;",
+ SNR,
+ mcs1,
+ eNB->dlsch[0][0]->harq_processes[0]->TBS,
+ rate,
+ errs[0],
+ round_trials[0],
+ errs[1],
+ round_trials[1],
+ errs[2],
+ round_trials[2],
+ errs[3],
+ round_trials[3],
+ dci_errors);
+
+ //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n");
+ fprintf(time_meas_fd,"%f;%d;%d;%f; %2.1f%%;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;",
+ SNR,
+ mcs1,
+ eNB->dlsch[0][0]->harq_processes[0]->TBS,
+ rate*effective_rate,
+ 100*effective_rate,
+ rate,
+ (double)avg_iter/iter_trials,
+ errs[0],
+ round_trials[0],
+ errs[1],
+ round_trials[1],
+ errs[2],
+ round_trials[2],
+ errs[3],
+ round_trials[3],
+ (double)errs[0]/(round_trials[0]),
+ (double)errs[1]/(round_trials[0]),
+ (double)errs[2]/(round_trials[0]),
+ (double)errs[3]/(round_trials[0]),
+ dci_errors,
+ round_trials[0],
+ (double)dci_errors/(round_trials[0]),
+ (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/
+ (double)eNB->dlsch[0][0]->harq_processes[0]->TBS,
+ (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0]));
+ } else {
+ fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d;",
+ SNR,
+ mcs1,mcs2,
+ eNB->dlsch[0][0]->harq_processes[0]->TBS,
+ eNB->dlsch[0][1]->harq_processes[0]->TBS,
+ rate,
+ errs[0],
+ round_trials[0],
+ errs[1],
+ round_trials[1],
+ errs[2],
+ round_trials[2],
+ errs[3],
+ round_trials[3],
+ dci_errors);
+
+ //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n");
+ fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%2.1f;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;",
+ SNR,
+ mcs1,mcs2,
+ eNB->dlsch[0][0]->harq_processes[0]->TBS,
+ eNB->dlsch[0][1]->harq_processes[0]->TBS,
+ rate*effective_rate,
+ 100*effective_rate,
+ rate,
+ (double)avg_iter/iter_trials,
+ errs[0],
+ round_trials[0],
+ errs[1],
+ round_trials[1],
+ errs[2],
+ round_trials[2],
+ errs[3],
+ round_trials[3],
+ (double)errs[0]/(round_trials[0]),
+ (double)errs[1]/(round_trials[0]),
+ (double)errs[2]/(round_trials[0]),
+ (double)errs[3]/(round_trials[0]),
+ dci_errors,
+ round_trials[0],
+ (double)dci_errors/(round_trials[0]),
+ (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/
+ (double)eNB->dlsch[0][0]->harq_processes[0]->TBS,
+ (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0]));
+ }
+
+ //fprintf(time_meas_fd,"eNB_PROC_TX(%d); OFDM_MOD(%d); DL_MOD(%d); DL_SCR(%d); DL_ENC(%d); UE_PROC_RX(%d); OFDM_DEMOD_CH_EST(%d); RX_PDCCH(%d); CH_COMP_LLR(%d); DL_USCR(%d); DL_DECOD(%d);\n",
+ fprintf(time_meas_fd,"%d; %d; %d; %d; %d; %d; %d; %d; %d; %d; %d;",
+ eNB->phy_proc_tx.trials,
+ eNB->ofdm_mod_stats.trials,
+ eNB->dlsch_modulation_stats.trials,
+ eNB->dlsch_scrambling_stats.trials,
+ eNB->dlsch_encoding_stats.trials,
+ UE->phy_proc_rx.trials,
+ UE->ofdm_demod_stats.trials,
+ UE->dlsch_rx_pdcch_stats.trials,
+ UE->dlsch_llr_stats.trials,
+ UE->dlsch_unscrambling_stats.trials,
+ UE->dlsch_decoding_stats.trials
+ );
+ fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;",
+ get_time_meas_us(&eNB->phy_proc_tx),
+ get_time_meas_us(&eNB->ofdm_mod_stats),
+ get_time_meas_us(&eNB->dlsch_modulation_stats),
+ get_time_meas_us(&eNB->dlsch_scrambling_stats),
+ get_time_meas_us(&eNB->dlsch_encoding_stats),
+ get_time_meas_us(&UE->phy_proc_rx),
+ nsymb*get_time_meas_us(&UE->ofdm_demod_stats),
+ get_time_meas_us(&UE->dlsch_rx_pdcch_stats),
+ 3*get_time_meas_us(&UE->dlsch_llr_stats),
+ get_time_meas_us(&UE->dlsch_unscrambling_stats),
+ get_time_meas_us(&UE->dlsch_decoding_stats)
+ );
+ //fprintf(time_meas_fd,"eNB_PROC_TX_STD;eNB_PROC_TX_MAX;eNB_PROC_TX_MIN;eNB_PROC_TX_MED;eNB_PROC_TX_Q1;eNB_PROC_TX_Q3;eNB_PROC_TX_DROPPED;\n");
+ fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;", std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped);
+
+ //fprintf(time_meas_fd,"IFFT;\n");
+ fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_ifft, tx_ifft_median, tx_ifft_q1, tx_ifft_q3);
+
+ //fprintf(time_meas_fd,"MOD;\n");
+ fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_mod, tx_mod_median, tx_mod_q1, tx_mod_q3);
+
+ //fprintf(time_meas_fd,"ENC;\n");
+ fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_enc, tx_enc_median, tx_enc_q1, tx_enc_q3);
+
+
+ //fprintf(time_meas_fd,"UE_PROC_RX_STD;UE_PROC_RX_MAX;UE_PROC_RX_MIN;UE_PROC_RX_MED;UE_PROC_RX_Q1;UE_PROC_RX_Q3;UE_PROC_RX_DROPPED;\n");
+ fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped);
+
+ //fprintf(time_meas_fd,"FFT;\n");
+ fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_rx_fft, rx_fft_median, rx_fft_q1, rx_fft_q3);
+
+ //fprintf(time_meas_fd,"DEMOD;\n");
+ fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_rx_demod,rx_demod_median, rx_demod_q1, rx_demod_q3);
+
+ //fprintf(time_meas_fd,"DEC;\n");
+ fprintf(time_meas_fd,"%f;%f;%f;%f\n", std_phy_proc_rx_dec, rx_dec_median, rx_dec_q1, rx_dec_q3);
+
+
+ /*
+ fprintf(time_meas_fd,"%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;",
+ eNB->phy_proc_tx.trials,
+ eNB->ofdm_mod_stats.trials,
+ eNB->dlsch_modulation_stats.trials,
+ eNB->dlsch_scrambling_stats.trials,
+ eNB->dlsch_encoding_stats.trials,
+ UE->phy_proc_rx.trials,
+ UE->ofdm_demod_stats.trials,
+ UE->dlsch_rx_pdcch_stats.trials,
+ UE->dlsch_llr_stats.trials,
+ UE->dlsch_unscrambling_stats.trials,
+ UE->dlsch_decoding_stats.trials);
+ */
+ printf("[passed] effective rate : %f (%2.1f%%,%f)): log and break \n",rate*effective_rate, 100*effective_rate, rate );
+ break;
+ } else if (test_perf !=0 ) {
+ printf("[continue] effective rate : %f (%2.1f%%,%f)): increase snr \n",rate*effective_rate, 100*effective_rate, rate);
+ }
+
+ if (((double)errs[0]/(round_trials[0]))<(10.0/n_frames))
+ break;
+ }// SNR
+
+
+ } //ch_realization
+
+
+ fclose(bler_fd);
+
+ if (test_perf !=0)
+ fclose (time_meas_fd);
+
+ //fprintf(tikz_fd,"};\n");
+ //fclose(tikz_fd);
+
+ if (input_trch_file==1)
+ fclose(input_trch_fd);
+
+ if (input_file==1)
+ fclose(input_fd);
+
+ if(abstx) { // ABSTRACTION
+ fprintf(csv_fd,"];");
+ fclose(csv_fd);
+ }
+
+ if (uncoded_ber_bit)
+ free(uncoded_ber_bit);
+
+ uncoded_ber_bit = NULL;
+
+ for (k=0; kdlsch[0][i]);
+ printf("UE %d\n",i);
+ free_ue_dlsch(UE->dlsch[0][i]);
+ }
+
+
+ printf("Freeing channel I/O\n");
+
+ for (i=0; iNid_cell = Nid_cell;
lte_frame_parms->nushift = Nid_cell%6;
lte_frame_parms->nb_antennas_tx = (transmission_mode == 1) ? 1 : 2;
- lte_frame_parms->nb_antennas_tx_eNB = (transmission_mode == 1) ? 1 : 2;
+ lte_frame_parms->nb_antenna_ports_eNB = (transmission_mode == 1) ? 1 : 2;
lte_frame_parms->nb_antennas_rx = (transmission_mode == 1) ? 1 : 2;
lte_frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0;
lte_frame_parms->phich_config_common.phich_resource = oneSixth;
diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c
index 11c1760cb3..7849dec1ab 100644
--- a/openair1/SIMULATION/LTE_PHY/mbmssim.c
+++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c
@@ -238,6 +238,7 @@ int main(int argc, char **argv)
n_tx=2;
lte_param_init(n_tx,
+ n_tx,
n_rx,
transmission_mode,
extended_prefix_flag,
@@ -301,7 +302,7 @@ int main(int argc, char **argv)
0);
// Create transport channel structures for 2 transport blocks (MIMO)
- eNB->dlsch_MCH = new_eNB_dlsch(1,8,Nsoft,N_RB_DL,0);
+ eNB->dlsch_MCH = new_eNB_dlsch(1,8,Nsoft,N_RB_DL,0,&eNB->frame_parms);
if (!eNB->dlsch_MCH) {
printf("Can't get eNB dlsch structures\n");
@@ -475,11 +476,11 @@ int main(int argc, char **argv)
}
UE->dlsch_MCH[0]->harq_processes[0]->G = get_G(&UE->frame_parms,
- UE->dlsch_MCH[0]->harq_processes[0]->nb_rb,
- UE->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even,
- get_Qm(UE->dlsch_MCH[0]->harq_processes[0]->mcs),
- 1,2,
- UE->proc.proc_rxtx[0].frame_tx,subframe);
+ UE->dlsch_MCH[0]->harq_processes[0]->nb_rb,
+ UE->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even,
+ get_Qm(UE->dlsch_MCH[0]->harq_processes[0]->mcs),
+ 1,2,
+ UE->proc.proc_rxtx[0].frame_tx,subframe,0);
UE->dlsch_MCH[0]->harq_processes[0]->Qm = get_Qm(UE->dlsch_MCH[0]->harq_processes[0]->mcs);
dlsch_unscrambling(&UE->frame_parms,1,UE->dlsch_MCH[0],
diff --git a/openair1/SIMULATION/LTE_PHY/pbchsim.c b/openair1/SIMULATION/LTE_PHY/pbchsim.c
index f696cc8da4..83906d7322 100644
--- a/openair1/SIMULATION/LTE_PHY/pbchsim.c
+++ b/openair1/SIMULATION/LTE_PHY/pbchsim.c
@@ -325,7 +325,7 @@ int main(int argc, char **argv)
if (transmission_mode>=2)
n_tx=2;
- lte_param_init(n_tx,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,3,N_RB_DL,0,osf,0);
+ lte_param_init(n_tx, n_tx,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,3,N_RB_DL,0,osf,0);
eNB1 = malloc(sizeof(PHY_VARS_eNB));
eNB2 = malloc(sizeof(PHY_VARS_eNB));
diff --git a/openair1/SIMULATION/LTE_PHY/pdcchsim.c b/openair1/SIMULATION/LTE_PHY/pdcchsim.c
index 0b79ec52ba..04b9d304b3 100644
--- a/openair1/SIMULATION/LTE_PHY/pdcchsim.c
+++ b/openair1/SIMULATION/LTE_PHY/pdcchsim.c
@@ -694,6 +694,7 @@ int main(int argc, char **argv)
n_tx=2;
lte_param_init(n_tx,
+ n_tx,
n_rx,
transmission_mode,
extended_prefix_flag,
@@ -737,7 +738,7 @@ int main(int argc, char **argv)
subframe,NUMBER_OF_OFDM_CARRIERS,
eNB->frame_parms.Ncp,eNB->frame_parms.samples_per_tti,nsymb);
- eNB2UE = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx_eNB,
+ eNB2UE = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx,
UE->frame_parms.nb_antennas_rx,
channel_model,
N_RB2sampling_rate(eNB->frame_parms.N_RB_DL),
@@ -812,7 +813,7 @@ int main(int argc, char **argv)
for (trial=0; trialcommon_vars.txdataF[eNb_id][aa][512*14*subframe],&eNB->common_vars.txdataF[eNb_id][aa][0]);
- for (aa=0; aaframe_parms.nb_antennas_tx_eNB; aa++) {
+ for (aa=0; aaframe_parms.nb_antennas_tx; aa++) {
memset(&eNB->common_vars.txdataF[eNb_id][aa][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t));
}
@@ -951,15 +952,14 @@ int main(int argc, char **argv)
if (n_frames==1) {
write_output("txsigF0.m","txsF0", eNB->common_vars.txdataF[eNb_id][0],4*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX,1,1);
- if (eNB->frame_parms.nb_antennas_tx_eNB > 1)
+ if (eNB->frame_parms.nb_antenna_ports_eNB > 1)
write_output("txsigF1.m","txsF1", eNB->common_vars.txdataF[eNb_id][1],4*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX,1,1);
}
tx_lev = 0;
-
- for (aa=0; aaframe_parms.nb_antennas_tx_eNB; aa++) {
+ for (aa=0; aaframe_parms.nb_antenna_ports_eNB; aa++) {
if (eNB->frame_parms.Ncp == 1)
PHY_ofdm_mod(&eNB->common_vars.txdataF[eNb_id][aa][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size], // input,
&txdata[aa][subframe*eNB->frame_parms.samples_per_tti], // output
@@ -982,7 +982,7 @@ int main(int argc, char **argv)
}
for (i=0; i<2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++) {
- for (aa=0; aaframe_parms.nb_antennas_tx_eNB; aa++) {
+ for (aa=0; aaframe_parms.nb_antenna_ports_eNB; aa++) {
if (awgn_flag == 0) {
s_re[aa][i] = ((double)(((short *)txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]);
s_im[aa][i] = ((double)(((short *)txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)+1]);
@@ -1069,7 +1069,7 @@ int main(int argc, char **argv)
}
}
} else {
- for(aa=0; aanb_antennas_tx_eNB; aa++) {
+ for(aa=0; aanb_antenna_ports_eNB; aa++) {
for (aarx=0; aarxnb_antennas_rx; aarx++) {
for (i=0; iN_RB_DL*12; i++) {
((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP);
diff --git a/openair1/SIMULATION/LTE_PHY/prachsim.c b/openair1/SIMULATION/LTE_PHY/prachsim.c
index ad57d17507..7acc07528c 100644
--- a/openair1/SIMULATION/LTE_PHY/prachsim.c
+++ b/openair1/SIMULATION/LTE_PHY/prachsim.c
@@ -308,6 +308,7 @@ int main(int argc, char **argv)
n_tx=2;
lte_param_init(n_tx,
+ n_tx,
n_rx,
transmission_mode,
extended_prefix_flag,
diff --git a/openair1/SIMULATION/LTE_PHY/pucchsim.c b/openair1/SIMULATION/LTE_PHY/pucchsim.c
index 843cd27a54..77bfcb18cf 100644
--- a/openair1/SIMULATION/LTE_PHY/pucchsim.c
+++ b/openair1/SIMULATION/LTE_PHY/pucchsim.c
@@ -296,6 +296,7 @@ int main(int argc, char **argv)
n_tx=2;
lte_param_init(n_tx,
+ n_tx,
n_rx,
transmission_mode,
extended_prefix_flag,
diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c
index 2bf96c3020..cf9e5aaa30 100644
--- a/openair1/SIMULATION/LTE_PHY/ulsim.c
+++ b/openair1/SIMULATION/LTE_PHY/ulsim.c
@@ -20,7 +20,7 @@
*/
/*! \file ulsim.c
- \brief Top-level DL simulator
+ \brief Top-level UL simulator
\author R. Knopp
\date 2011 - 2014
\version 0.1
@@ -554,6 +554,7 @@ int main(int argc, char **argv)
}
lte_param_init(1,
+ 1,
n_rx,
1,
extended_prefix_flag,
@@ -679,7 +680,7 @@ int main(int argc, char **argv)
}
// Create transport channel structures for 2 transport blocks (MIMO)
for (i=0; i<2; i++) {
- eNB->dlsch[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0);
+ eNB->dlsch[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0,&eNB->frame_parms);
UE->dlsch[0][i] = new_ue_dlsch(1,8,1827072,MAX_TURBO_ITERATIONS,N_RB_DL,0);
if (!eNB->dlsch[0][i]) {
diff --git a/openair2/COMMON/as_message.h b/openair2/COMMON/as_message.h
index c8cd92b060..acc9ae6ba1 100644
--- a/openair2/COMMON/as_message.h
+++ b/openair2/COMMON/as_message.h
@@ -211,6 +211,14 @@ typedef struct broadcast_info_ind_s {
#define AS_HSDUPA (1 << NET_ACCESS_HSDUPA)
#define AS_EUTRAN (1 << NET_ACCESS_EUTRAN)
+/*
+ * NAS->AS -K_eNB refresh request
+ * NAS request AS to refresh its KeNB key
+ */
+typedef struct kenb_refresh_req_s {
+ Byte_t kenb[32];
+} kenb_refresh_req_t;
+
/*
* NAS->AS - Cell Information request
* NAS request AS to search for a suitable cell belonging to the selected
diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h
index 18a7678436..04b1182482 100644
--- a/openair2/COMMON/rrc_messages_def.h
+++ b/openair2/COMMON/rrc_messages_def.h
@@ -56,6 +56,7 @@ MESSAGE_DEF(RRC_STATE_IND, MESSAGE_PRIORITY_MED, RrcStateInd,
MESSAGE_DEF(RRC_CONFIGURATION_REQ, MESSAGE_PRIORITY_MED, RrcConfigurationReq, rrc_configuration_req)
// UE: NAS -> RRC messages
+MESSAGE_DEF(NAS_KENB_REFRESH_REQ, MESSAGE_PRIORITY_MED, NasKenbRefreshReq, nas_kenb_refresh_req)
MESSAGE_DEF(NAS_CELL_SELECTION_REQ, MESSAGE_PRIORITY_MED, NasCellSelectionReq, nas_cell_selection_req)
MESSAGE_DEF(NAS_CONN_ESTABLI_REQ, MESSAGE_PRIORITY_MED, NasConnEstabliReq, nas_conn_establi_req)
MESSAGE_DEF(NAS_UPLINK_DATA_REQ, MESSAGE_PRIORITY_MED, NasUlDataReq, nas_ul_data_req)
diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h
index c2df8bab38..8a4c27f5eb 100644
--- a/openair2/COMMON/rrc_messages_types.h
+++ b/openair2/COMMON/rrc_messages_types.h
@@ -62,6 +62,7 @@ typedef UL_DCCH_Message_t RrcUlDcchMessage;
#define RRC_CONFIGURATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_configuration_req
+#define NAS_KENB_REFRESH_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_kenb_refresh_req
#define NAS_CELL_SELECTION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_cell_selection_req
#define NAS_CONN_ESTABLI_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_conn_establi_req
#define NAS_UPLINK_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_ul_data_req
@@ -175,6 +176,7 @@ typedef struct RrcConfigurationReq_s {
} RrcConfigurationReq;
// UE: NAS -> RRC messages
+typedef kenb_refresh_req_t NasKenbRefreshReq;
typedef cell_info_req_t NasCellSelectionReq;
typedef nas_establish_req_t NasConnEstabliReq;
typedef ul_info_transfer_req_t NasUlDataReq;
diff --git a/openair2/COMMON/tasks_def.h b/openair2/COMMON/tasks_def.h
index 5fe555e117..c9e210fd1f 100644
--- a/openair2/COMMON/tasks_def.h
+++ b/openair2/COMMON/tasks_def.h
@@ -55,6 +55,8 @@ TASK_DEF(TASK_X2AP, TASK_PRIORITY_MED, 200)
TASK_DEF(TASK_SCTP, TASK_PRIORITY_MED, 200)
/// eNB APP task
TASK_DEF(TASK_ENB_APP, TASK_PRIORITY_MED, 200)
+/// eNB Agent task
+TASK_DEF(TASK_FLEXRAN_AGENT, TASK_PRIORITY_MED, 200)
// UE tasks and sub-tasks:
//// Layer 2 and Layer 1 sub-tasks
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c
new file mode 100644
index 0000000000..b9cad28278
--- /dev/null
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c
@@ -0,0 +1,1493 @@
+/*
+ * 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.0 (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.c
+ * \brief FlexRAN agent message handler for MAC layer
+ * \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+#include "flexran_agent_mac.h"
+#include "flexran_agent_extern.h"
+#include "flexran_agent_common.h"
+#include "flexran_agent_mac_internal.h"
+
+#include "LAYER2/MAC/proto.h"
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+#include "LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h"
+
+#include "liblfds700.h"
+
+#include "log.h"
+
+
+/*Flags showing if a mac agent has already been registered*/
+unsigned int mac_agent_registered[NUM_MAX_ENB];
+
+/*Array containing the Agent-MAC interfaces*/
+AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];
+
+/* Ringbuffer related structs used for maintaining the dl mac config messages */
+//message_queue_t *dl_mac_config_queue;
+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];
+
+
+int flexran_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg){
+
+ // TODO: Must deal with sanitization of input
+ // TODO: Must check if RNTIs and cell ids of the request actually exist
+ // TODO: Must resolve conflicts among stats requests
+
+ int i;
+ void *buffer;
+ int size;
+ err_code_t err_code;
+ xid_t xid;
+ uint32_t usec_interval, sec_interval;
+
+ //TODO: We do not deal with multiple CCs at the moment and eNB id is 0
+ int cc_id = 0;
+ int enb_id = mod_id;
+
+ //eNB_MAC_INST *eNB = &eNB_mac_inst[enb_id];
+ //UE_list_t *eNB_UE_list= &eNB->UE_list;
+
+ report_config_t report_config;
+
+ uint32_t ue_flags = 0;
+ uint32_t c_flags = 0;
+
+ Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+
+ Protocol__FlexStatsRequest *stats_req = input->stats_request_msg;
+ xid = (stats_req->header)->xid;
+
+ // Check the type of request that is made
+ switch(stats_req->body_case) {
+ case PROTOCOL__FLEX_STATS_REQUEST__BODY_COMPLETE_STATS_REQUEST: ;
+ Protocol__FlexCompleteStatsRequest *comp_req = stats_req->complete_stats_request;
+ if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_OFF) {
+ /*Disable both periodic and continuous updates*/
+ flexran_agent_disable_cont_mac_stats_update(mod_id);
+ flexran_agent_destroy_timer_by_task_id(xid);
+ *msg = NULL;
+ return 0;
+ } else { //One-off, periodical or continuous reporting
+ //Set the proper flags
+ ue_flags = comp_req->ue_report_flags;
+ c_flags = comp_req->cell_report_flags;
+ //Create a list of all eNB RNTIs and cells
+
+ //Set the number of UEs and create list with their RNTIs stats configs
+ report_config.nr_ue = flexran_get_num_ues(mod_id); //eNB_UE_list->num_UEs
+ report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t) * report_config.nr_ue);
+ if (report_config.ue_report_type == NULL) {
+ // TODO: Add appropriate error code
+ err_code = -100;
+ 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;
+ }
+ //Set the number of CCs and create a list with the cell stats configs
+ report_config.nr_cc = MAX_NUM_CCs;
+ report_config.cc_report_type = (cc_report_type_t *) malloc(sizeof(cc_report_type_t) * report_config.nr_cc);
+ if (report_config.cc_report_type == NULL) {
+ // TODO: Add appropriate error code
+ err_code = -100;
+ goto error;
+ }
+ for (i = 0; i < report_config.nr_cc; i++) {
+ //TODO: Must fill in the proper cell ids
+ report_config.cc_report_type[i].cc_id = i;
+ report_config.cc_report_type[i].cc_report_flags = c_flags;
+ }
+ /* Check if request was periodical */
+ if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_PERIODICAL) {
+ /* Create a one off flexran message as an argument for the periodical task */
+ Protocol__FlexranMessage *timer_msg;
+ stats_request_config_t request_config;
+ request_config.report_type = PROTOCOL__FLEX_STATS_TYPE__FLST_COMPLETE_STATS;
+ request_config.report_frequency = PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_ONCE;
+ request_config.period = 0;
+ /* Need to make sure that the ue flags are saved (Bug) */
+ if (report_config.nr_ue == 0) {
+ report_config.nr_ue = 1;
+ report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t));
+ if (report_config.ue_report_type == NULL) {
+ // TODO: Add appropriate error code
+ err_code = -100;
+ goto error;
+ }
+ report_config.ue_report_type[0].ue_rnti = 0; // Dummy value
+ report_config.ue_report_type[0].ue_report_flags = ue_flags;
+ }
+ request_config.config = &report_config;
+ flexran_agent_mac_stats_request(enb_id, xid, &request_config, &timer_msg);
+ /* Create a timer */
+ long timer_id = 0;
+ flexran_agent_timer_args_t *timer_args;
+ timer_args = malloc(sizeof(flexran_agent_timer_args_t));
+ memset (timer_args, 0, sizeof(flexran_agent_timer_args_t));
+ timer_args->mod_id = enb_id;
+ timer_args->msg = timer_msg;
+ /*Convert subframes to usec time*/
+ usec_interval = 1000*comp_req->sf;
+ sec_interval = 0;
+ /*add seconds if required*/
+ if (usec_interval >= 1000*1000) {
+ sec_interval = usec_interval/(1000*1000);
+ usec_interval = usec_interval%(1000*1000);
+ }
+ flexran_agent_create_timer(sec_interval, usec_interval, FLEXRAN_AGENT_DEFAULT, enb_id, FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, xid, flexran_agent_handle_timed_task,(void*) timer_args, &timer_id);
+ } else if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_CONTINUOUS) {
+ /*If request was for continuous updates, disable the previous configuration and
+ set up a new one*/
+ flexran_agent_disable_cont_mac_stats_update(mod_id);
+ stats_request_config_t request_config;
+ request_config.report_type = PROTOCOL__FLEX_STATS_TYPE__FLST_COMPLETE_STATS;
+ request_config.report_frequency = PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_ONCE;
+ request_config.period = 0;
+ /* Need to make sure that the ue flags are saved (Bug) */
+ if (report_config.nr_ue == 0) {
+ report_config.nr_ue = 1;
+ report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t));
+ if (report_config.ue_report_type == NULL) {
+ // TODO: Add appropriate error code
+ err_code = -100;
+ goto error;
+ }
+ report_config.ue_report_type[0].ue_rnti = 0; // Dummy value
+ report_config.ue_report_type[0].ue_report_flags = ue_flags;
+ }
+ request_config.config = &report_config;
+ flexran_agent_enable_cont_mac_stats_update(enb_id, xid, &request_config);
+ }
+ }
+ break;
+ case PROTOCOL__FLEX_STATS_REQUEST__BODY_CELL_STATS_REQUEST:;
+ Protocol__FlexCellStatsRequest *cell_req = stats_req->cell_stats_request;
+ // UE report config will be blank
+ report_config.nr_ue = 0;
+ report_config.ue_report_type = NULL;
+ report_config.nr_cc = cell_req->n_cell;
+ report_config.cc_report_type = (cc_report_type_t *) malloc(sizeof(cc_report_type_t) * report_config.nr_cc);
+ if (report_config.cc_report_type == NULL) {
+ // TODO: Add appropriate error code
+ err_code = -100;
+ goto error;
+ }
+ for (i = 0; i < report_config.nr_cc; i++) {
+ //TODO: Must fill in the proper cell ids
+ report_config.cc_report_type[i].cc_id = cell_req->cell[i];
+ report_config.cc_report_type[i].cc_report_flags = cell_req->flags;
+ }
+ break;
+ case PROTOCOL__FLEX_STATS_REQUEST__BODY_UE_STATS_REQUEST:;
+ Protocol__FlexUeStatsRequest *ue_req = stats_req->ue_stats_request;
+ // Cell report config will be blank
+ report_config.nr_cc = 0;
+ report_config.cc_report_type = NULL;
+ report_config.nr_ue = ue_req->n_rnti;
+ report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t) * report_config.nr_ue);
+ if (report_config.ue_report_type == NULL) {
+ // TODO: Add appropriate error code
+ err_code = -100;
+ goto error;
+ }
+ for (i = 0; i < report_config.nr_ue; i++) {
+ report_config.ue_report_type[i].ue_rnti = ue_req->rnti[i];
+ report_config.ue_report_type[i].ue_report_flags = ue_req->flags;
+ }
+ break;
+ default:
+ //TODO: Add appropriate error code
+ err_code = -100;
+ goto error;
+ }
+
+ if (flexran_agent_mac_stats_reply(enb_id, xid, &report_config, msg) < 0 ){
+ err_code = PROTOCOL__FLEXRAN_ERR__MSG_BUILD;
+ goto error;
+ }
+
+ free(report_config.ue_report_type);
+ free(report_config.cc_report_type);
+
+ return 0;
+
+ error :
+ LOG_E(FLEXRAN_AGENT, "errno %d occured\n", err_code);
+ return err_code;
+}
+
+int flexran_agent_mac_stats_request(mid_t mod_id,
+ xid_t xid,
+ const stats_request_config_t *report_config,
+ Protocol__FlexranMessage **msg) {
+ Protocol__FlexHeader *header;
+ int i;
+
+ if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_STATS_REQUEST, &header) != 0)
+ goto error;
+
+ Protocol__FlexStatsRequest *stats_request_msg;
+ stats_request_msg = malloc(sizeof(Protocol__FlexStatsRequest));
+ if(stats_request_msg == NULL)
+ goto error;
+
+ protocol__flex_stats_request__init(stats_request_msg);
+ stats_request_msg->header = header;
+
+ stats_request_msg->type = report_config->report_type;
+ stats_request_msg->has_type = 1;
+
+ switch (report_config->report_type) {
+ case PROTOCOL__FLEX_STATS_TYPE__FLST_COMPLETE_STATS:
+ stats_request_msg->body_case = PROTOCOL__FLEX_STATS_REQUEST__BODY_COMPLETE_STATS_REQUEST;
+ Protocol__FlexCompleteStatsRequest *complete_stats;
+ complete_stats = malloc(sizeof(Protocol__FlexCompleteStatsRequest));
+ if(complete_stats == NULL)
+ goto error;
+ protocol__flex_complete_stats_request__init(complete_stats);
+ complete_stats->report_frequency = report_config->report_frequency;
+ complete_stats->has_report_frequency = 1;
+ complete_stats->sf = report_config->period;
+ complete_stats->has_sf = 1;
+ complete_stats->has_cell_report_flags = 1;
+ complete_stats->has_ue_report_flags = 1;
+ if (report_config->config->nr_cc > 0) {
+ complete_stats->cell_report_flags = report_config->config->cc_report_type[0].cc_report_flags;
+ }
+ if (report_config->config->nr_ue > 0) {
+ complete_stats->ue_report_flags = report_config->config->ue_report_type[0].ue_report_flags;
+ }
+ stats_request_msg->complete_stats_request = complete_stats;
+ break;
+ case PROTOCOL__FLEX_STATS_TYPE__FLST_CELL_STATS:
+ stats_request_msg->body_case = PROTOCOL__FLEX_STATS_REQUEST__BODY_CELL_STATS_REQUEST;
+ Protocol__FlexCellStatsRequest *cell_stats;
+ cell_stats = malloc(sizeof(Protocol__FlexCellStatsRequest));
+ if(cell_stats == NULL)
+ goto error;
+ protocol__flex_cell_stats_request__init(cell_stats);
+ cell_stats->n_cell = report_config->config->nr_cc;
+ cell_stats->has_flags = 1;
+ if (cell_stats->n_cell > 0) {
+ uint32_t *cells;
+ cells = (uint32_t *) malloc(sizeof(uint32_t)*cell_stats->n_cell);
+ for (i = 0; i < cell_stats->n_cell; i++) {
+ cells[i] = report_config->config->cc_report_type[i].cc_id;
+ }
+ cell_stats->cell = cells;
+ cell_stats->flags = report_config->config->cc_report_type[i].cc_report_flags;
+ }
+ stats_request_msg->cell_stats_request = cell_stats;
+ break;
+ case PROTOCOL__FLEX_STATS_TYPE__FLST_UE_STATS:
+ stats_request_msg->body_case = PROTOCOL__FLEX_STATS_REQUEST__BODY_UE_STATS_REQUEST;
+ Protocol__FlexUeStatsRequest *ue_stats;
+ ue_stats = malloc(sizeof(Protocol__FlexUeStatsRequest));
+ if(ue_stats == NULL)
+ goto error;
+ protocol__flex_ue_stats_request__init(ue_stats);
+ ue_stats->n_rnti = report_config->config->nr_ue;
+ ue_stats->has_flags = 1;
+ if (ue_stats->n_rnti > 0) {
+ uint32_t *ues;
+ ues = (uint32_t *) malloc(sizeof(uint32_t)*ue_stats->n_rnti);
+ for (i = 0; i < ue_stats->n_rnti; i++) {
+ ues[i] = report_config->config->ue_report_type[i].ue_rnti;
+ }
+ ue_stats->rnti = ues;
+ ue_stats->flags = report_config->config->ue_report_type[i].ue_report_flags;
+ }
+ stats_request_msg->ue_stats_request = ue_stats;
+ break;
+ default:
+ goto error;
+ }
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if(*msg == NULL)
+ goto error;
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REQUEST_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+ (*msg)->stats_request_msg = stats_request_msg;
+ return 0;
+
+ error:
+ // TODO: Need to make proper error handling
+ if (header != NULL)
+ free(header);
+ if (stats_request_msg != NULL)
+ free(stats_request_msg);
+ if(*msg != NULL)
+ free(*msg);
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_mac_destroy_stats_request(Protocol__FlexranMessage *msg) {
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REQUEST_MSG)
+ goto error;
+ free(msg->stats_request_msg->header);
+ if (msg->stats_request_msg->body_case == PROTOCOL__FLEX_STATS_REQUEST__BODY_CELL_STATS_REQUEST) {
+ free(msg->stats_request_msg->cell_stats_request->cell);
+ }
+ if (msg->stats_request_msg->body_case == PROTOCOL__FLEX_STATS_REQUEST__BODY_UE_STATS_REQUEST) {
+ free(msg->stats_request_msg->ue_stats_request->rnti);
+ }
+ free(msg->stats_request_msg);
+ free(msg);
+ return 0;
+
+ error:
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_mac_stats_reply(mid_t mod_id,
+ xid_t xid,
+ const report_config_t *report_config,
+ Protocol__FlexranMessage **msg) {
+ Protocol__FlexHeader *header;
+ int i, j, k;
+ int cc_id = 0;
+ int enb_id = mod_id;
+ //eNB_MAC_INST *eNB = &eNB_mac_inst[enb_id];
+ //UE_list_t *eNB_UE_list= &eNB->UE_list;
+
+
+ if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_STATS_REPLY, &header) != 0)
+ goto error;
+
+ Protocol__FlexStatsReply *stats_reply_msg;
+ stats_reply_msg = malloc(sizeof(Protocol__FlexStatsReply));
+ if (stats_reply_msg == NULL)
+ goto error;
+ protocol__flex_stats_reply__init(stats_reply_msg);
+ stats_reply_msg->header = header;
+
+ stats_reply_msg->n_ue_report = report_config->nr_ue;
+ stats_reply_msg->n_cell_report = report_config->nr_cc;
+
+ Protocol__FlexUeStatsReport **ue_report;
+ Protocol__FlexCellStatsReport **cell_report;
+
+
+ /* Allocate memory for list of UE reports */
+ if (report_config->nr_ue > 0) {
+ ue_report = malloc(sizeof(Protocol__FlexUeStatsReport *) * report_config->nr_ue);
+ if (ue_report == NULL)
+ goto error;
+ for (i = 0; i < report_config->nr_ue; i++) {
+ ue_report[i] = malloc(sizeof(Protocol__FlexUeStatsReport));
+ protocol__flex_ue_stats_report__init(ue_report[i]);
+ ue_report[i]->rnti = report_config->ue_report_type[i].ue_rnti;
+ ue_report[i]->has_rnti = 1;
+ ue_report[i]->flags = report_config->ue_report_type[i].ue_report_flags;
+ ue_report[i]->has_flags = 1;
+ /* Check the types of reports that need to be constructed based on flag values */
+
+ /* Check flag for creation of buffer status report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_BSR) {
+ ue_report[i]->n_bsr = 4;
+ uint32_t *elem;
+ elem = (uint32_t *) malloc(sizeof(uint32_t)*ue_report[i]->n_bsr);
+ if (elem == NULL)
+ goto error;
+ for (j = 0; j++; j < ue_report[i]->n_bsr) {
+ // NN: we need to know the cc_id here, consider the first one
+ elem[j] = flexran_get_ue_bsr (enb_id, i, j);
+ }
+ ue_report[i]->bsr = elem;
+ }
+
+ /* Check flag for creation of PRH report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PRH) {
+ 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]->has_phr = 1;
+ }
+
+ /* Check flag for creation of RLC buffer status report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RLC_BS) {
+ ue_report[i]->n_rlc_report = 3; // Set this to the number of LCs for this UE. This needs to be generalized for for LCs
+ Protocol__FlexRlcBsr ** rlc_reports;
+ rlc_reports = malloc(sizeof(Protocol__FlexRlcBsr *) * ue_report[i]->n_rlc_report);
+ if (rlc_reports == NULL)
+ goto error;
+
+ // NN: see LAYER2/openair2_proc.c for rlc status
+ for (j = 0; j < ue_report[i]->n_rlc_report; j++) {
+ rlc_reports[j] = malloc(sizeof(Protocol__FlexRlcBsr));
+ if (rlc_reports[j] == NULL)
+ goto error;
+ 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]->has_tx_queue_size = 1;
+
+ //TODO:Set tx queue head of line delay in ms
+ rlc_reports[j]->tx_queue_hol_delay = 100;
+ rlc_reports[j]->has_tx_queue_hol_delay = 0;
+ //TODO:Set retransmission queue size in bytes
+ rlc_reports[j]->retransmission_queue_size = 10;
+ rlc_reports[j]->has_retransmission_queue_size = 0;
+ //TODO:Set retransmission queue head of line delay in ms
+ rlc_reports[j]->retransmission_queue_hol_delay = 100;
+ rlc_reports[j]->has_retransmission_queue_hol_delay = 0;
+ //TODO:Set current size of the pending message in bytes
+ rlc_reports[j]->status_pdu_size = 100;
+ rlc_reports[j]->has_status_pdu_size = 0;
+ }
+ // Add RLC buffer status reports to the full report
+ if (ue_report[i]->n_rlc_report > 0)
+ ue_report[i]->rlc_report = rlc_reports;
+ }
+
+ /* 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; /* 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
+ flex_ce_type in FlexRAN specification */
+ ue_report[i]->has_pending_mac_ces = 1;
+ }
+
+ /* Check flag for creation of DL CQI report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) {
+ // TODO: Fill in the actual DL CQI report for the UE based on its configuration
+ Protocol__FlexDlCqiReport * dl_report;
+ dl_report = malloc(sizeof(Protocol__FlexDlCqiReport));
+ if (dl_report == NULL)
+ goto error;
+ protocol__flex_dl_cqi_report__init(dl_report);
+
+ 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);
+
+ //Create the actual CSI reports.
+ Protocol__FlexDlCsi **csi_reports;
+ csi_reports = malloc(sizeof(Protocol__FlexDlCsi *)*dl_report->n_csi_report);
+ if (csi_reports == NULL)
+ goto error;
+ for (j = 0; j < dl_report->n_csi_report; j++) {
+ csi_reports[j] = malloc(sizeof(Protocol__FlexDlCsi));
+ if (csi_reports[j] == NULL)
+ goto error;
+ protocol__flex_dl_csi__init(csi_reports[j]);
+ //The servCellIndex for this report
+ 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]->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
+ //The full set of types can be found in stats_common.pb-c.h and
+ //in the FlexRAN specifications
+ csi_reports[j]->type = PROTOCOL__FLEX_CSI_TYPE__FLCSIT_P10;
+ csi_reports[j]->has_type = 1;
+ csi_reports[j]->report_case = PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI;
+ if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI){
+ Protocol__FlexCsiP10 *csi10;
+ csi10 = malloc(sizeof(Protocol__FlexCsiP10));
+ if (csi10 == NULL)
+ goto error;
+ 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->has_wb_cqi = 1;
+ //Add the type of measurements to the csi report in the proper union type
+ csi_reports[j]->p10csi = csi10;
+ }
+ else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI){
+
+ }
+ else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI){
+
+ }
+ else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI){
+
+ }
+ else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI){
+
+ }
+ else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI){
+
+ }
+ else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI){
+
+ }
+ else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI){
+
+ }
+ else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI){
+
+ }
+ }
+ //Add the csi reports to the full DL CQI report
+ dl_report->csi_report = csi_reports;
+ //Add the DL CQI report to the stats report
+ ue_report[i]->dl_cqi_report = dl_report;
+ }
+
+ /* Check flag for creation of paging buffer status report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) {
+ //TODO: Fill in the actual paging buffer status report. For this field to be valid, the RNTI
+ //set in the report must be a P-RNTI
+ Protocol__FlexPagingBufferReport *paging_report;
+ paging_report = malloc(sizeof(Protocol__FlexPagingBufferReport));
+ if (paging_report == NULL)
+ goto error;
+ protocol__flex_paging_buffer_report__init(paging_report);
+ //Set the number of pending paging messages
+ paging_report->n_paging_info = 1;
+ //Provide a report for each pending paging message
+ Protocol__FlexPagingInfo **p_info;
+ p_info = malloc(sizeof(Protocol__FlexPagingInfo *) * paging_report->n_paging_info);
+ if (p_info == NULL)
+ goto error;
+ for (j = 0; j < paging_report->n_paging_info; j++) {
+ p_info[j] = malloc(sizeof(Protocol__FlexPagingInfo));
+ if(p_info[j] == NULL)
+ goto error;
+ protocol__flex_paging_info__init(p_info[j]);
+ //TODO: Set paging index. This index is the same that will be used for the scheduling of the
+ //paging message by the controller
+ p_info[j]->paging_index = 10;
+ p_info[j]->has_paging_index = 0;
+ //TODO:Set the paging message size
+ p_info[j]->paging_message_size = 100;
+ p_info[j]->has_paging_message_size = 0;
+ //TODO: Set the paging subframe
+ p_info[j]->paging_subframe = 10;
+ p_info[j]->has_paging_subframe = 0;
+ //TODO: Set the carrier index for the pending paging message
+ p_info[j]->carrier_index = 0;
+ p_info[j]->has_carrier_index = 0;
+ }
+ //Add all paging info to the paging buffer rerport
+ paging_report->paging_info = p_info;
+ //Add the paging report to the UE report
+ ue_report[i]->pbr = paging_report;
+ }
+
+ /* Check flag for creation of UL CQI report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) {
+ //Fill in the full UL CQI report of the UE
+ Protocol__FlexUlCqiReport *full_ul_report;
+ full_ul_report = malloc(sizeof(Protocol__FlexUlCqiReport));
+ if(full_ul_report == NULL)
+ goto error;
+ protocol__flex_ul_cqi_report__init(full_ul_report);
+ //TODO:Set the SFN and SF of the generated report
+ full_ul_report->sfn_sn = flexran_get_sfn_sf(enb_id);
+ full_ul_report->has_sfn_sn = 1;
+ //TODO:Set the number of UL measurement reports based on the types of measurements
+ //configured for this UE and on the servCellIndex
+ full_ul_report->n_cqi_meas = 1;
+ Protocol__FlexUlCqi **ul_report;
+ ul_report = malloc(sizeof(Protocol__FlexUlCqi *) * full_ul_report->n_cqi_meas);
+ if(ul_report == NULL)
+ goto error;
+ //Fill each UL report of the UE for each of the configured report types
+ for(j = 0; j < full_ul_report->n_cqi_meas; j++) {
+ ul_report[j] = malloc(sizeof(Protocol__FlexUlCqi));
+ if(ul_report[j] == NULL)
+ goto error;
+ protocol__flex_ul_cqi__init(ul_report[j]);
+ //TODO: Set the type of the UL report. As an example set it to SRS UL report
+ // See enum flex_ul_cqi_type in FlexRAN specification for more details
+ ul_report[j]->type = PROTOCOL__FLEX_UL_CQI_TYPE__FLUCT_SRS;
+ ul_report[j]->has_type = 1;
+ //TODO:Set the number of SINR measurements based on the report type
+ //See struct flex_ul_cqi in FlexRAN specification for more details
+ ul_report[j]->n_sinr = 0;
+ uint32_t *sinr_meas;
+ sinr_meas = (uint32_t *) malloc(sizeof(uint32_t) * ul_report[j]->n_sinr);
+ if (sinr_meas == NULL)
+ goto error;
+ //TODO:Set the SINR measurements for the specified type
+ for (k = 0; k < ul_report[j]->n_sinr; k++) {
+ sinr_meas[k] = 10;
+ }
+ ul_report[j]->sinr = sinr_meas;
+ //TODO: Set the servCellIndex for this report
+ ul_report[j]->serv_cell_index = 0;
+ ul_report[j]->has_serv_cell_index = 1;
+
+ //Set the list of UL reports of this UE to the full UL report
+ full_ul_report->cqi_meas = ul_report;
+
+ full_ul_report->n_pucch_dbm = MAX_NUM_CCs;
+ full_ul_report->pucch_dbm = malloc(sizeof(Protocol__FlexPucchDbm *) * full_ul_report->n_pucch_dbm);
+
+ for (j = 0; j < MAX_NUM_CCs; j++) {
+ full_ul_report->pucch_dbm[j] = malloc(sizeof(Protocol__FlexPucchDbm));
+ protocol__flex_pucch_dbm__init(full_ul_report->pucch_dbm[j]);
+ 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);
+ full_ul_report->pucch_dbm[j]->has_p0_pucch_dbm = 1;
+ }
+ }
+
+ //Add full UL CQI report to the UE report
+ ue_report[i]->ul_cqi_report = full_ul_report;
+ }
+ }
+ }
+ /* Add list of all UE reports to the message */
+ stats_reply_msg->ue_report = ue_report;
+ }
+
+ /* Allocate memory for list of cell reports */
+ if (report_config->nr_cc > 0) {
+ cell_report = malloc(sizeof(Protocol__FlexCellStatsReport *) * report_config->nr_cc);
+ if (cell_report == NULL)
+ goto error;
+ // Fill in the Cell reports
+ for (i = 0; i < report_config->nr_cc; i++) {
+ cell_report[i] = malloc(sizeof(Protocol__FlexCellStatsReport));
+ if(cell_report[i] == NULL)
+ goto error;
+ protocol__flex_cell_stats_report__init(cell_report[i]);
+ cell_report[i]->carrier_index = report_config->cc_report_type[i].cc_id;
+ cell_report[i]->has_carrier_index = 1;
+ cell_report[i]->flags = report_config->cc_report_type[i].cc_report_flags;
+ cell_report[i]->has_flags = 1;
+
+ /* Check flag for creation of noise and interference report */
+ if(report_config->cc_report_type[i].cc_report_flags & PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE) {
+ // TODO: Fill in the actual noise and interference report for this cell
+ Protocol__FlexNoiseInterferenceReport *ni_report;
+ ni_report = malloc(sizeof(Protocol__FlexNoiseInterferenceReport));
+ if(ni_report == NULL)
+ goto error;
+ protocol__flex_noise_interference_report__init(ni_report);
+ // Current frame and subframe number
+ ni_report->sfn_sf = flexran_get_sfn_sf(enb_id);
+ ni_report->has_sfn_sf = 1;
+ //TODO:Received interference power in dbm
+ ni_report->rip = 0;
+ ni_report->has_rip = 0;
+ //TODO:Thermal noise power in dbm
+ ni_report->tnp = 0;
+ ni_report->has_tnp = 0;
+
+ ni_report->p0_nominal_pucch = flexran_get_p0_nominal_pucch(enb_id, 0);
+ ni_report->has_p0_nominal_pucch = 1;
+ cell_report[i]->noise_inter_report = ni_report;
+ }
+ }
+ /* Add list of all cell reports to the message */
+ stats_reply_msg->cell_report = cell_report;
+ }
+
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if(*msg == NULL)
+ goto error;
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+ (*msg)->stats_reply_msg = stats_reply_msg;
+ return 0;
+
+ error:
+ // TODO: Need to make proper error handling
+ if (header != NULL)
+ free(header);
+ if (stats_reply_msg != NULL)
+ free(stats_reply_msg);
+ if(*msg != NULL)
+ free(*msg);
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_mac_destroy_stats_reply(Protocol__FlexranMessage *msg) {
+ //TODO: Need to deallocate memory for the stats reply message
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG)
+ goto error;
+ free(msg->stats_reply_msg->header);
+ int i, j, k;
+
+ Protocol__FlexStatsReply *reply = msg->stats_reply_msg;
+ Protocol__FlexDlCqiReport *dl_report;
+ Protocol__FlexUlCqiReport *ul_report;
+ Protocol__FlexPagingBufferReport *paging_report;
+
+ // Free the memory for the UE reports
+ for (i = 0; i < reply->n_ue_report; i++) {
+ free(reply->ue_report[i]->bsr);
+ for (j = 0; j < reply->ue_report[i]->n_rlc_report; j++) {
+ free(reply->ue_report[i]->rlc_report[j]);
+ }
+ free(reply->ue_report[i]->rlc_report);
+ // If DL CQI report flag was set
+ if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) {
+ dl_report = reply->ue_report[i]->dl_cqi_report;
+ // Delete all CSI reports
+ for (j = 0; j < dl_report->n_csi_report; j++) {
+ //Must free memory based on the type of report
+ switch(dl_report->csi_report[j]->report_case) {
+ case PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI:
+ free(dl_report->csi_report[j]->p10csi);
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI:
+ free(dl_report->csi_report[j]->p11csi->wb_cqi);
+ free(dl_report->csi_report[j]->p11csi);
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI:
+ free(dl_report->csi_report[j]->p20csi);
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI:
+ free(dl_report->csi_report[j]->p21csi->wb_cqi);
+ free(dl_report->csi_report[j]->p21csi->sb_cqi);
+ free(dl_report->csi_report[j]->p21csi);
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI:
+ free(dl_report->csi_report[j]->a12csi->wb_cqi);
+ free(dl_report->csi_report[j]->a12csi->sb_pmi);
+ free(dl_report->csi_report[j]->a12csi);
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI:
+ free(dl_report->csi_report[j]->a22csi->wb_cqi);
+ free(dl_report->csi_report[j]->a22csi->sb_cqi);
+ free(dl_report->csi_report[j]->a22csi->sb_list);
+ free(dl_report->csi_report[j]->a22csi);
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI:
+ free(dl_report->csi_report[j]->a20csi->sb_list);
+ free(dl_report->csi_report[j]->a20csi);
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI:
+ free(dl_report->csi_report[j]->a30csi->sb_cqi);
+ free(dl_report->csi_report[j]->a30csi);
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI:
+ free(dl_report->csi_report[j]->a31csi->wb_cqi);
+ for (k = 0; k < dl_report->csi_report[j]->a31csi->n_sb_cqi; k++) {
+ free(dl_report->csi_report[j]->a31csi->sb_cqi[k]);
+ }
+ free(dl_report->csi_report[j]->a31csi->sb_cqi);
+ break;
+ }
+
+ free(dl_report->csi_report[j]);
+ }
+ free(dl_report->csi_report);
+ free(dl_report);
+ }
+ // If Paging buffer report flag was set
+ if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) {
+ paging_report = reply->ue_report[i]->pbr;
+ // Delete all paging buffer reports
+ for (j = 0; j < paging_report->n_paging_info; j++) {
+ free(paging_report->paging_info[j]);
+ }
+ free(paging_report->paging_info);
+ free(paging_report);
+ }
+ // If UL CQI report flag was set
+ if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) {
+ ul_report = reply->ue_report[i]->ul_cqi_report;
+ for (j = 0; j < ul_report->n_cqi_meas; j++) {
+ free(ul_report->cqi_meas[j]->sinr);
+ free(ul_report->cqi_meas[j]);
+ }
+ free(ul_report->cqi_meas);
+ for (j = 0; j < ul_report->n_pucch_dbm; j++) {
+ free(ul_report->pucch_dbm[j]);
+ }
+ free(ul_report->pucch_dbm);
+ }
+ free(reply->ue_report[i]);
+ }
+ free(reply->ue_report);
+
+ // Free memory for all Cell reports
+ for (i = 0; i < reply->n_cell_report; i++) {
+ free(reply->cell_report[i]->noise_inter_report);
+ free(reply->cell_report[i]);
+ }
+ free(reply->cell_report);
+
+ free(reply);
+ free(msg);
+ return 0;
+
+ error:
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_mac_sr_info(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+ Protocol__FlexHeader *header;
+ int i;
+ const int xid = *((int *)params);
+ if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_UL_SR_INFO, &header) != 0)
+ goto error;
+
+ Protocol__FlexUlSrInfo *ul_sr_info_msg;
+ ul_sr_info_msg = malloc(sizeof(Protocol__FlexUlSrInfo));
+ if (ul_sr_info_msg == NULL) {
+ goto error;
+ }
+ protocol__flex_ul_sr_info__init(ul_sr_info_msg);
+
+ ul_sr_info_msg->header = header;
+ ul_sr_info_msg->has_sfn_sf = 1;
+ ul_sr_info_msg->sfn_sf = flexran_get_sfn_sf(mod_id);
+ /*TODO: Set the number of UEs that sent an SR */
+ ul_sr_info_msg->n_rnti = 1;
+ ul_sr_info_msg->rnti = (uint32_t *) malloc(ul_sr_info_msg->n_rnti * sizeof(uint32_t));
+
+ if(ul_sr_info_msg->rnti == NULL) {
+ goto error;
+ }
+ /*TODO:Set the rnti of the UEs that sent an SR */
+ for (i = 0; i < ul_sr_info_msg->n_rnti; i++) {
+ ul_sr_info_msg->rnti[i] = 1;
+ }
+
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if(*msg == NULL)
+ goto error;
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+ (*msg)->ul_sr_info_msg = ul_sr_info_msg;
+ return 0;
+
+ error:
+ // TODO: Need to make proper error handling
+ if (header != NULL)
+ free(header);
+ if (ul_sr_info_msg != NULL) {
+ free(ul_sr_info_msg->rnti);
+ free(ul_sr_info_msg);
+ }
+ if(*msg != NULL)
+ free(*msg);
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_mac_destroy_sr_info(Protocol__FlexranMessage *msg) {
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG)
+ goto error;
+
+ free(msg->ul_sr_info_msg->header);
+ free(msg->ul_sr_info_msg->rnti);
+ free(msg->ul_sr_info_msg);
+ free(msg);
+ return 0;
+
+ error:
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+ Protocol__FlexHeader *header;
+ int i,j;
+ const int xid = *((int *)params);
+ if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_SF_TRIGGER, &header) != 0)
+ goto error;
+
+ Protocol__FlexSfTrigger *sf_trigger_msg;
+ sf_trigger_msg = malloc(sizeof(Protocol__FlexSfTrigger));
+ if (sf_trigger_msg == NULL) {
+ goto error;
+ }
+ protocol__flex_sf_trigger__init(sf_trigger_msg);
+
+ frame_t frame;
+ sub_frame_t subframe;
+
+ int ahead_of_time = 1;
+
+ frame = (frame_t) flexran_get_current_system_frame_num(mod_id);
+ subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
+
+ subframe = ((subframe + ahead_of_time) % 10);
+
+ int full_frames_ahead = ((ahead_of_time / 10) % 10);
+
+ frame = frame + full_frames_ahead;
+
+ if (subframe < flexran_get_current_subframe(mod_id)) {
+ frame++;
+ }
+
+ sf_trigger_msg->header = header;
+ sf_trigger_msg->has_sfn_sf = 1;
+ sf_trigger_msg->sfn_sf = flexran_get_future_sfn_sf(mod_id, 1);
+
+ /*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);
+
+ Protocol__FlexDlInfo **dl_info = NULL;
+
+ if (sf_trigger_msg->n_dl_info > 0) {
+ dl_info = malloc(sizeof(Protocol__FlexDlInfo *) * sf_trigger_msg->n_dl_info);
+ if(dl_info == NULL)
+ goto error;
+ //Fill the status of the current HARQ process for each UE
+ for(i = 0; i < sf_trigger_msg->n_dl_info; i++) {
+ dl_info[i] = malloc(sizeof(Protocol__FlexDlInfo));
+ if(dl_info[i] == NULL)
+ goto error;
+ protocol__flex_dl_info__init(dl_info[i]);
+ dl_info[i]->rnti = flexran_get_ue_crnti(mod_id, i);
+ dl_info[i]->has_rnti = 1;
+ /*Fill in the right id of this round's HARQ process for this UE*/
+ int harq_id;
+ int harq_status;
+ flexran_get_harq(mod_id, UE_PCCID(mod_id,i), i, frame, subframe, &harq_id, &harq_status);
+ dl_info[i]->harq_process_id = harq_id;
+ 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++) {
+ // TODO: This should be different per TB
+ if(harq_status == 0)
+ dl_info[i]->harq_status[j] = PROTOCOL__FLEX_HARQ_STATUS__FLHS_ACK;
+ else if (harq_status > 0)
+ dl_info[i]->harq_status[j] = PROTOCOL__FLEX_HARQ_STATUS__FLHS_NACK;
+ }
+ /*Fill in the serving cell index for this UE */
+ dl_info[i]->serv_cell_index = UE_PCCID(mod_id,i);
+ dl_info[i]->has_serv_cell_index = 1;
+ }
+ }
+
+ sf_trigger_msg->dl_info = dl_info;
+
+ /* Fill in the number of UL reception status related info, based on the number of currently
+ * transmitting UEs
+ */
+ sf_trigger_msg->n_ul_info = flexran_get_num_ues(mod_id);
+
+ Protocol__FlexUlInfo **ul_info = NULL;
+
+ if (sf_trigger_msg->n_ul_info > 0) {
+ ul_info = malloc(sizeof(Protocol__FlexUlInfo *) * sf_trigger_msg->n_ul_info);
+ if(ul_info == NULL)
+ goto error;
+ //Fill the reception info for each transmitting UE
+ for(i = 0; i < sf_trigger_msg->n_ul_info; i++) {
+ ul_info[i] = malloc(sizeof(Protocol__FlexUlInfo));
+ 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);
+ ul_info[i]->has_rnti = 1;
+ /*Fill in the Tx power control command for this UE (if available)*/
+ if(flexran_get_tpc(mod_id,i) != 1){
+ ul_info[i]->tpc = flexran_get_tpc(mod_id,i);
+ ul_info[i]->has_tpc = 1;
+ }
+ else{
+ ul_info[i]->tpc = flexran_get_tpc(mod_id,i);
+ 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
+ given logical channel*/
+ ul_info[i]->n_ul_reception = 0;
+ ul_info[i]->ul_reception = malloc(sizeof(uint32_t) * ul_info[i]->n_ul_reception);
+ for (j = 0; j < ul_info[i]->n_ul_reception; j++) {
+ ul_info[i]->ul_reception[j] = 100;
+ }
+ /*TODO: Fill in the reception status for each UEs data*/
+ 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]->has_serv_cell_index = 1;
+ }
+ }
+
+ sf_trigger_msg->ul_info = ul_info;
+
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if(*msg == NULL)
+ goto error;
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+ (*msg)->sf_trigger_msg = sf_trigger_msg;
+ return 0;
+
+ error:
+ if (header != NULL)
+ free(header);
+ if (sf_trigger_msg != NULL) {
+ for (i = 0; i < sf_trigger_msg->n_dl_info; i++) {
+ free(sf_trigger_msg->dl_info[i]->harq_status);
+ }
+ free(sf_trigger_msg->dl_info);
+ for (i = 0; i < sf_trigger_msg->n_ul_info; i++) {
+ free(sf_trigger_msg->ul_info[i]->reception_status);
+ }
+ free(sf_trigger_msg->ul_info);
+ free(sf_trigger_msg);
+ }
+ if(*msg != NULL)
+ free(*msg);
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_mac_destroy_sf_trigger(Protocol__FlexranMessage *msg) {
+ int i;
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG)
+ goto error;
+
+ free(msg->sf_trigger_msg->header);
+ for (i = 0; i < msg->sf_trigger_msg->n_dl_info; i++) {
+ free(msg->sf_trigger_msg->dl_info[i]->harq_status);
+ free(msg->sf_trigger_msg->dl_info[i]);
+ }
+ free(msg->sf_trigger_msg->dl_info);
+ for (i = 0; i < msg->sf_trigger_msg->n_ul_info; i++) {
+ free(msg->sf_trigger_msg->ul_info[i]->ul_reception);
+ free(msg->sf_trigger_msg->ul_info[i]);
+ }
+ free(msg->sf_trigger_msg->ul_info);
+ free(msg->sf_trigger_msg);
+ free(msg);
+
+ return 0;
+
+ error:
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_mac_create_empty_dl_config(mid_t mod_id, Protocol__FlexranMessage **msg) {
+
+ int xid = 0;
+ Protocol__FlexHeader *header;
+ if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_DL_MAC_CONFIG, &header) != 0)
+ goto error;
+
+ Protocol__FlexDlMacConfig *dl_mac_config_msg;
+ dl_mac_config_msg = malloc(sizeof(Protocol__FlexDlMacConfig));
+ if (dl_mac_config_msg == NULL) {
+ goto error;
+ }
+ protocol__flex_dl_mac_config__init(dl_mac_config_msg);
+
+ dl_mac_config_msg->header = header;
+ dl_mac_config_msg->has_sfn_sf = 1;
+ dl_mac_config_msg->sfn_sf = flexran_get_sfn_sf(mod_id);
+
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if(*msg == NULL)
+ goto error;
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+ (*msg)->dl_mac_config_msg = dl_mac_config_msg;
+
+ return 0;
+
+ error:
+ return -1;
+}
+
+int flexran_agent_mac_destroy_dl_config(Protocol__FlexranMessage *msg) {
+ int i,j, k;
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG)
+ goto error;
+
+ Protocol__FlexDlDci *dl_dci;
+
+ free(msg->dl_mac_config_msg->header);
+ for (i = 0; i < msg->dl_mac_config_msg->n_dl_ue_data; i++) {
+ free(msg->dl_mac_config_msg->dl_ue_data[i]->ce_bitmap);
+ for (j = 0; j < msg->dl_mac_config_msg->dl_ue_data[i]->n_rlc_pdu; j++) {
+ for (k = 0; k < msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->n_rlc_pdu_tb; k++) {
+ free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb[k]);
+ }
+ free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb);
+ free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]);
+ }
+ free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu);
+ dl_dci = msg->dl_mac_config_msg->dl_ue_data[i]->dl_dci;
+ free(dl_dci->tbs_size);
+ free(dl_dci->mcs);
+ free(dl_dci->ndi);
+ free(dl_dci->rv);
+ free(dl_dci);
+ free(msg->dl_mac_config_msg->dl_ue_data[i]);
+ }
+ free(msg->dl_mac_config_msg->dl_ue_data);
+
+ for (i = 0; i < msg->dl_mac_config_msg->n_dl_rar; i++) {
+ dl_dci = msg->dl_mac_config_msg->dl_rar[i]->rar_dci;
+ free(dl_dci->tbs_size);
+ free(dl_dci->mcs);
+ free(dl_dci->ndi);
+ free(dl_dci->rv);
+ free(dl_dci);
+ free(msg->dl_mac_config_msg->dl_rar[i]);
+ }
+ free(msg->dl_mac_config_msg->dl_rar);
+
+ for (i = 0; i < msg->dl_mac_config_msg->n_dl_broadcast; i++) {
+ dl_dci = msg->dl_mac_config_msg->dl_broadcast[i]->broad_dci;
+ free(dl_dci->tbs_size);
+ free(dl_dci->mcs);
+ free(dl_dci->ndi);
+ free(dl_dci->rv);
+ free(dl_dci);
+ free(msg->dl_mac_config_msg->dl_broadcast[i]);
+ }
+ free(msg->dl_mac_config_msg->dl_broadcast);
+
+ for ( i = 0; i < msg->dl_mac_config_msg->n_ofdm_sym; i++) {
+ free(msg->dl_mac_config_msg->ofdm_sym[i]);
+ }
+ free(msg->dl_mac_config_msg->ofdm_sym);
+ free(msg->dl_mac_config_msg);
+ free(msg);
+
+ return 0;
+
+ error:
+ return -1;
+}
+
+void flexran_agent_get_pending_dl_mac_config(mid_t mod_id, Protocol__FlexranMessage **msg) {
+
+ struct lfds700_misc_prng_state ls;
+
+ LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+ lfds700_misc_prng_init(&ls);
+
+ if (lfds700_ringbuffer_read(&ringbuffer_state[mod_id], NULL, (void **) msg, &ls) == 0) {
+ *msg = NULL;
+ }
+}
+
+int flexran_agent_mac_handle_dl_mac_config(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+ struct lfds700_misc_prng_state ls;
+ enum lfds700_misc_flag overwrite_occurred_flag;
+ Protocol__FlexranMessage *overwritten_dl_config;
+
+ LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+ lfds700_misc_prng_init(&ls);
+
+ lfds700_ringbuffer_write( &ringbuffer_state[mod_id],
+ NULL,
+ (void *) params,
+ &overwrite_occurred_flag,
+ NULL,
+ (void **)&overwritten_dl_config,
+ &ls);
+
+ if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) {
+ // Delete unmanaged dl_config
+ flexran_agent_mac_destroy_dl_config(overwritten_dl_config);
+ }
+ *msg = NULL;
+ return 2;
+
+ error:
+ *msg = NULL;
+ return -1;
+}
+
+void flexran_agent_init_mac_agent(mid_t mod_id) {
+ lfds700_misc_library_init_valid_on_current_logical_core();
+ 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 );
+}
+
+/***********************************************
+ * FlexRAN agent - technology mac API implementation
+ ***********************************************/
+
+void flexran_agent_send_sr_info(mid_t mod_id) {
+ int size;
+ Protocol__FlexranMessage *msg;
+ void *data;
+ int priority;
+ err_code_t err_code;
+
+ int xid = 0;
+
+ /*TODO: Must use a proper xid*/
+ err_code = flexran_agent_mac_sr_info(mod_id, (void *) &xid, &msg);
+ if (err_code < 0) {
+ goto error;
+ }
+
+ if (msg != NULL){
+ data=flexran_agent_pack_message(msg, &size);
+ /*Send sr info using the MAC channel of the eNB*/
+ if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_MAC, data, size, priority)) {
+ err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+ goto error;
+ }
+
+ LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+ return;
+ }
+ error:
+ LOG_D(FLEXRAN_AGENT, "Could not send sr message\n");
+}
+
+void flexran_agent_send_sf_trigger(mid_t mod_id) {
+ int size;
+ Protocol__FlexranMessage *msg;
+ void *data;
+ int priority;
+ err_code_t err_code;
+
+ int xid = 0;
+
+ /*TODO: Must use a proper xid*/
+ err_code = flexran_agent_mac_sf_trigger(mod_id, (void *) &xid, &msg);
+ if (err_code < 0) {
+ goto error;
+ }
+
+ if (msg != NULL){
+ data=flexran_agent_pack_message(msg, &size);
+ /*Send sr info using the MAC channel of the eNB*/
+ if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_MAC, data, size, priority)) {
+ err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+ goto error;
+ }
+
+ LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+ return;
+ }
+ error:
+ LOG_D(FLEXRAN_AGENT, "Could not send sf trigger message\n");
+}
+
+void flexran_agent_send_update_mac_stats(mid_t mod_id) {
+
+ Protocol__FlexranMessage *current_report = NULL, *msg;
+ void *data;
+ int size;
+ err_code_t err_code;
+ int priority;
+
+ mac_stats_updates_context_t stats_context = mac_stats_context[mod_id];
+
+ if (pthread_mutex_lock(mac_stats_context[mod_id].mutex)) {
+ goto error;
+ }
+
+ if (mac_stats_context[mod_id].cont_update == 1) {
+
+ /*Create a fresh report with the required flags*/
+ err_code = flexran_agent_mac_handle_stats(mod_id, (void *) mac_stats_context[mod_id].stats_req, ¤t_report);
+ if (err_code < 0) {
+ goto error;
+ }
+ }
+ /* /\*TODO:Check if a previous reports exists and if yes, generate a report */
+ /* *that is the diff between the old and the new report, */
+ /* *respecting the thresholds. Otherwise send the new report*\/ */
+ /* if (mac_stats_context[mod_id].prev_stats_reply != NULL) { */
+
+ /* msg = flexran_agent_generate_diff_mac_stats_report(current_report, mac_stats_context[mod_id].prev_stats_reply); */
+
+ /* /\*Destroy the old stats*\/ */
+ /* flexran_agent_destroy_flexran_message(mac_stats_context[mod_id].prev_stats_reply); */
+ /* } */
+ /* /\*Use the current report for future comparissons*\/ */
+ /* mac_stats_context[mod_id].prev_stats_reply = current_report; */
+
+
+ if (pthread_mutex_unlock(mac_stats_context[mod_id].mutex)) {
+ goto error;
+ }
+
+ if (current_report != NULL){
+ data=flexran_agent_pack_message(current_report, &size);
+ /*Send any stats updates using the MAC channel of the eNB*/
+ if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_MAC, data, size, priority)) {
+ err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+ goto error;
+ }
+
+ LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+ return;
+ }
+ error:
+ LOG_D(FLEXRAN_AGENT, "Could not send sf trigger message\n");
+}
+
+int flexran_agent_register_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) {
+ if (mac_agent_registered[mod_id]) {
+ LOG_E(MAC, "MAC agent for eNB %d is already registered\n", mod_id);
+ return -1;
+ }
+
+ //xface->agent_ctxt = &shared_ctxt[mod_id];
+ xface->flexran_agent_send_sr_info = flexran_agent_send_sr_info;
+ xface->flexran_agent_send_sf_trigger = flexran_agent_send_sf_trigger;
+ xface->flexran_agent_send_update_mac_stats = flexran_agent_send_update_mac_stats;
+ xface->flexran_agent_schedule_ue_spec = flexran_schedule_ue_spec_default;
+ //xface->flexran_agent_schedule_ue_spec = flexran_schedule_ue_spec_remote;
+ xface->flexran_agent_get_pending_dl_mac_config = flexran_agent_get_pending_dl_mac_config;
+ xface->flexran_agent_notify_ue_state_change = flexran_agent_ue_state_change;
+
+ xface->dl_scheduler_loaded_lib = NULL;
+
+ mac_agent_registered[mod_id] = 1;
+ agent_mac_xface[mod_id] = xface;
+
+ return 0;
+}
+
+int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) {
+
+ //xface->agent_ctxt = NULL;
+ xface->flexran_agent_send_sr_info = NULL;
+ xface->flexran_agent_send_sf_trigger = NULL;
+ xface->flexran_agent_send_update_mac_stats = NULL;
+ xface->flexran_agent_schedule_ue_spec = NULL;
+ xface->flexran_agent_get_pending_dl_mac_config = NULL;
+ xface->flexran_agent_notify_ue_state_change = NULL;
+
+ xface->dl_scheduler_loaded_lib = NULL;
+
+ mac_agent_registered[mod_id] = 0;
+ agent_mac_xface[mod_id] = NULL;
+
+ return 0;
+}
+
+
+/******************************************************
+ *Implementations of flexran_agent_mac_internal.h functions
+ ******************************************************/
+
+err_code_t flexran_agent_init_cont_mac_stats_update(mid_t mod_id) {
+
+ /*Initialize the Mac stats update structure*/
+ /*Initially the continuous update is set to false*/
+ mac_stats_context[mod_id].cont_update = 0;
+ mac_stats_context[mod_id].is_initialized = 1;
+ mac_stats_context[mod_id].stats_req = NULL;
+ mac_stats_context[mod_id].prev_stats_reply = NULL;
+ mac_stats_context[mod_id].mutex = calloc(1, sizeof(pthread_mutex_t));
+ if (mac_stats_context[mod_id].mutex == NULL)
+ goto error;
+ if (pthread_mutex_init(mac_stats_context[mod_id].mutex, NULL))
+ goto error;;
+
+ return 0;
+
+ error:
+ return -1;
+}
+
+err_code_t flexran_agent_destroy_cont_mac_stats_update(mid_t mod_id) {
+ /*Disable the continuous updates for the MAC*/
+ mac_stats_context[mod_id].cont_update = 0;
+ mac_stats_context[mod_id].is_initialized = 0;
+ flexran_agent_destroy_flexran_message(mac_stats_context[mod_id].stats_req);
+ flexran_agent_destroy_flexran_message(mac_stats_context[mod_id].prev_stats_reply);
+ free(mac_stats_context[mod_id].mutex);
+
+ mac_agent_registered[mod_id] = NULL;
+ return 1;
+}
+
+
+err_code_t flexran_agent_enable_cont_mac_stats_update(mid_t mod_id,
+ xid_t xid, stats_request_config_t *stats_req) {
+ /*Enable the continuous updates for the MAC*/
+ if (pthread_mutex_lock(mac_stats_context[mod_id].mutex)) {
+ goto error;
+ }
+
+ Protocol__FlexranMessage *req_msg;
+
+ flexran_agent_mac_stats_request(mod_id, xid, stats_req, &req_msg);
+ mac_stats_context[mod_id].stats_req = req_msg;
+ mac_stats_context[mod_id].prev_stats_reply = NULL;
+
+ mac_stats_context[mod_id].cont_update = 1;
+ mac_stats_context[mod_id].xid = xid;
+
+ if (pthread_mutex_unlock(mac_stats_context[mod_id].mutex)) {
+ goto error;
+ }
+ return 0;
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "mac_stats_context for eNB %d is not initialized\n", mod_id);
+ return -1;
+}
+
+err_code_t flexran_agent_disable_cont_mac_stats_update(mid_t mod_id) {
+ /*Disable the continuous updates for the MAC*/
+ if (pthread_mutex_lock(mac_stats_context[mod_id].mutex)) {
+ goto error;
+ }
+ mac_stats_context[mod_id].cont_update = 0;
+ mac_stats_context[mod_id].xid = 0;
+ if (mac_stats_context[mod_id].stats_req != NULL) {
+ flexran_agent_destroy_flexran_message(mac_stats_context[mod_id].stats_req);
+ }
+ if (mac_stats_context[mod_id].prev_stats_reply != NULL) {
+ flexran_agent_destroy_flexran_message(mac_stats_context[mod_id].prev_stats_reply);
+ }
+ if (pthread_mutex_unlock(mac_stats_context[mod_id].mutex)) {
+ goto error;
+ }
+ return 0;
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "mac_stats_context for eNB %d is not initialized\n", mod_id);
+ return -1;
+
+}
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h
new file mode 100644
index 0000000000..e2378e9311
--- /dev/null
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h
@@ -0,0 +1,122 @@
+/*
+ * 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.0 (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.h
+ * \brief FlexRAN agent message handler APIs for MAC layer
+ * \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef FLEXRAN_AGENT_MAC_H_
+#define FLEXRAN_AGENT_MAC_H_
+
+#include "header.pb-c.h"
+#include "flexran.pb-c.h"
+#include "stats_messages.pb-c.h"
+#include "stats_common.pb-c.h"
+
+#include "flexran_agent_common.h"
+#include "flexran_agent_extern.h"
+
+/* These types will be used to give
+ instructions for the type of stats reports
+ we need to create */
+typedef struct {
+ uint16_t ue_rnti;
+ uint32_t ue_report_flags; /* Indicates the report elements
+ required for this UE id. See
+ FlexRAN specification 1.2.4.2 */
+} ue_report_type_t;
+
+typedef struct {
+ uint16_t cc_id;
+ uint32_t cc_report_flags; /* Indicates the report elements
+ required for this CC index. See
+ FlexRAN specification 1.2.4.3 */
+} cc_report_type_t;
+
+typedef struct {
+ int nr_ue;
+ ue_report_type_t *ue_report_type;
+ int nr_cc;
+ cc_report_type_t *cc_report_type;
+} report_config_t;
+
+typedef struct stats_request_config_s{
+ uint8_t report_type;
+ uint8_t report_frequency;
+ uint16_t period; /*In number of subframes*/
+ report_config_t *config;
+} stats_request_config_t;
+
+/* Initialization function for the agent structures etc */
+void flexran_agent_init_mac_agent(mid_t mod_id);
+
+int flexran_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+
+/* Statistics request protocol message constructor and destructor */
+int flexran_agent_mac_stats_request(mid_t mod_id, xid_t xid, const stats_request_config_t *report_config, Protocol__FlexranMessage **msg);
+int flexran_agent_mac_destroy_stats_request(Protocol__FlexranMessage *msg);
+
+/* Statistics reply protocol message constructor and destructor */
+int flexran_agent_mac_stats_reply(mid_t mod_id, xid_t xid, const report_config_t *report_config, Protocol__FlexranMessage **msg);
+int flexran_agent_mac_destroy_stats_reply(Protocol__FlexranMessage *msg);
+
+/* Scheduling request information protocol message constructor and estructor */
+int flexran_agent_mac_sr_info(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_mac_destroy_sr_info(Protocol__FlexranMessage *msg);
+
+/* Subframe trigger protocol msssage constructor and destructor */
+int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_mac_destroy_sf_trigger(Protocol__FlexranMessage *msg);
+
+/* DL MAC scheduling decision protocol message constructor (empty command) and destructor */
+int flexran_agent_mac_create_empty_dl_config(mid_t mod_id, Protocol__FlexranMessage **msg);
+int flexran_agent_mac_destroy_dl_config(Protocol__FlexranMessage *msg);
+
+int flexran_agent_mac_handle_dl_mac_config(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+
+
+/**********************************
+ * FlexRAN agent - technology mac API
+ **********************************/
+
+/*Inform controller about received scheduling requests during a subframe*/
+void flexran_agent_send_sr_info(mid_t mod_id);
+
+/*Inform the controller about the current UL/DL subframe*/
+void flexran_agent_send_sf_trigger(mid_t mod_id);
+
+/// Send to the controller all the mac stat updates that occured during this subframe
+/// based on the stats request configuration
+void flexran_agent_send_update_mac_stats(mid_t mod_id);
+
+/// Provide to the scheduler a pending dl_mac_config message
+void flexran_agent_get_pending_dl_mac_config(mid_t mod_id, Protocol__FlexranMessage **msg);
+
+/*Register technology specific interface callbacks*/
+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);
+
+#endif
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_defs.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_defs.h
new file mode 100644
index 0000000000..bb6aed1d8e
--- /dev/null
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_defs.h
@@ -0,0 +1,75 @@
+/*
+ * 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.0 (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_defs.h
+ * \brief FlexRAN agent - mac interface primitives
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ * \mail x.foukas@sms.ed.ac.uk
+ */
+
+#ifndef __FLEXRAN_AGENT_MAC_PRIMITIVES_H__
+#define __FLEXRAN_AGENT_MAC_PRIMITIVES_H__
+
+#include "flexran_agent_defs.h"
+#include "flexran.pb-c.h"
+#include "header.pb-c.h"
+
+#define RINGBUFFER_SIZE 100
+
+/* FLEXRAN AGENT-MAC Interface */
+typedef struct {
+ //msg_context_t *agent_ctxt;
+
+ /// Inform the controller about the scheduling requests received during the subframe
+ void (*flexran_agent_send_sr_info)(mid_t mod_id);
+
+ /// Inform the controller about the current UL/DL subframe
+ void (*flexran_agent_send_sf_trigger)(mid_t mod_id);
+
+ /// Send to the controller all the mac stat updates that occured during this subframe
+ /// based on the stats request configuration
+ void (*flexran_agent_send_update_mac_stats)(mid_t mod_id);
+
+ /// Provide to the scheduler a pending dl_mac_config message
+ void (*flexran_agent_get_pending_dl_mac_config)(mid_t mod_id,
+ Protocol__FlexranMessage **msg);
+
+ /// Run the UE DL scheduler and fill the Protocol__FlexranMessage. Assumes that
+ /// dl_info is already initialized as flex_dl_mac_config and fills the
+ /// flex_dl_data part of it
+ void (*flexran_agent_schedule_ue_spec)(mid_t mod_id, uint32_t frame, uint32_t subframe,
+ int *mbsfn_flag, Protocol__FlexranMessage **dl_info);
+
+
+ /// Notify the controller for a state change of a particular UE, by sending the proper
+ /// UE state change message (ACTIVATION, DEACTIVATION, HANDOVER)
+ void (*flexran_agent_notify_ue_state_change)(mid_t mod_id, uint32_t rnti,
+ uint32_t state_change);
+
+
+ void *dl_scheduler_loaded_lib;
+ /*TODO: Fill in with the rest of the MAC layer technology specific callbacks (UL/DL scheduling, RACH info etc)*/
+
+} AGENT_MAC_xface;
+
+#endif
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
new file mode 100644
index 0000000000..a63225e657
--- /dev/null
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
@@ -0,0 +1,794 @@
+/*
+ * 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.0 (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_internal.c
+ * \brief Helper functions for the MAC agent
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#include
+#include
+
+#include "flexran_agent_mac_internal.h"
+
+Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message,
+ Protocol__FlexranMessage *old_message) {
+
+ int i, j;
+
+ Protocol__FlexStatsReply *old_report, *new_report;
+
+ Protocol__FlexStatsReply *stats_reply_msg = NULL;
+ Protocol__FlexranMessage *msg = NULL;
+
+ Protocol__FlexUeStatsReport **ue_report;
+ Protocol__FlexUeStatsReport *tmp_ue_report[NUM_MAX_UE];
+ Protocol__FlexCellStatsReport **cell_report;
+ Protocol__FlexCellStatsReport *tmp_cell_report[NUM_MAX_UE];
+
+ old_report = old_message->stats_reply_msg;
+ new_report = new_message->stats_reply_msg;
+
+ /*Flags to designate changes in various levels of the message*/
+ int stats_had_changes = 0;
+ int ue_had_change = 0;
+ int cell_had_change = 0;
+
+ /*See how many and which UE reports should be included in the final stats message*/
+ int n_ue_report = 0;
+ int ue_found = 0;
+
+ /*Go through each RNTI of the new report and see if it exists in the old one*/
+ for (i = 0; i < new_report->n_ue_report; i++) {
+ for (j = 0; j < old_report->n_ue_report; i++) {
+ if (new_report->ue_report[i]->rnti == old_report->ue_report[j]->rnti) {
+ ue_found = 1;
+ /*Need to check if something changed*/
+ if (compare_ue_stats_reports(new_report->ue_report[i], old_report->ue_report[j]) != 0) {
+ tmp_ue_report[n_ue_report] = copy_ue_stats_report(new_report->ue_report[i]);
+ n_ue_report++;
+ }
+ break;
+ }
+ }
+ if (!ue_found) {
+ tmp_ue_report[n_ue_report] = copy_ue_stats_report(new_report->ue_report[i]);
+ n_ue_report++;
+ }
+ ue_found = 0;
+ }
+
+ /*See how many and which cell reports should be included in the final stats message*/
+ int n_cell_report = 0;
+ int cell_found = 0;
+
+ /*Go through each cell of the new report and see if it exists in the old one*/
+ for (i = 0; i < new_report->n_cell_report; i++) {
+ for (j = 0; j < old_report->n_cell_report; i++) {
+ if (new_report->cell_report[i]->carrier_index == old_report->cell_report[j]->carrier_index) {
+ cell_found = 1;
+ /*Need to check if something changed*/
+ if (compare_cell_stats_reports(new_report->cell_report[i], old_report->cell_report[j]) != 0) {
+ tmp_cell_report[n_cell_report] = copy_cell_stats_report(new_report->cell_report[i]);
+ n_cell_report++;
+ }
+ break;
+ }
+ }
+ if (!cell_found) {
+ tmp_cell_report[n_cell_report] = copy_cell_stats_report(new_report->cell_report[i]);
+ n_cell_report++;
+ }
+ cell_found = 0;
+ }
+
+ /*TODO: create the reply message based on the findings*/
+ /*Create ue report list*/
+ if (n_ue_report > 0) {
+ ue_report = malloc(sizeof(Protocol__FlexUeStatsReport *));
+ for (i = 0; i 0) {
+ cell_report = malloc(sizeof(Protocol__FlexCellStatsReport *));
+ for (i = 0; i 0 || n_ue_report > 0) {
+ /*Create header*/
+ int xid = old_report->header->xid;
+ Protocol__FlexHeader *header;
+ if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_STATS_REPLY, &header) != 0) {
+ goto error;
+ }
+ stats_reply_msg = malloc(sizeof(Protocol__FlexStatsReply));
+ protocol__flex_stats_reply__init(stats_reply_msg);
+ stats_reply_msg->header = header;
+ stats_reply_msg->n_ue_report = n_ue_report;
+ stats_reply_msg->ue_report = ue_report;
+ stats_reply_msg->n_cell_report = n_cell_report;
+ stats_reply_msg->cell_report = cell_report;
+ msg = malloc(sizeof(Protocol__FlexranMessage));
+ if(msg == NULL)
+ goto error;
+ protocol__flexran_message__init(msg);
+ msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG;
+ msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+ msg->stats_reply_msg = stats_reply_msg;
+ }
+ return msg;
+
+ error:
+ return NULL;
+}
+
+int compare_ue_stats_reports(Protocol__FlexUeStatsReport *rep1,
+ Protocol__FlexUeStatsReport *rep2) {
+ return 1;
+}
+
+int compare_cell_stats_reports(Protocol__FlexCellStatsReport *rep1,
+ Protocol__FlexCellStatsReport *rep2) {
+ return 1;
+}
+
+Protocol__FlexUeStatsReport * copy_ue_stats_report(Protocol__FlexUeStatsReport * original) {
+ int i;
+ Protocol__FlexUeStatsReport *copy = malloc(sizeof(Protocol__FlexUeStatsReport));
+ if (copy == NULL)
+ goto error;
+ protocol__flex_ue_stats_report__init(copy);
+ copy->rnti = original->rnti;
+ copy->has_rnti = original->has_rnti;
+ copy->flags = original->flags;
+ copy->has_flags = original->has_flags;
+
+ if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_BSR) {
+ copy->n_bsr = original->n_bsr;
+ if (copy->n_bsr > 0) {
+ uint32_t *elem;
+ elem = (uint32_t *) malloc(sizeof(uint32_t)*copy->n_bsr);
+ if (elem == NULL)
+ goto error;
+ for (i = 0; i < original->n_bsr; i++) {
+ elem[i] = original->bsr[i];
+ }
+ copy->bsr = elem;
+ }
+ }
+
+ if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PRH) {
+ copy->has_phr = original->has_phr;
+ copy->phr = original->phr;
+ }
+
+ if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RLC_BS) {
+ copy->n_rlc_report = original->n_rlc_report;
+ if (copy->n_rlc_report > 0) {
+ Protocol__FlexRlcBsr ** rlc_reports;
+ rlc_reports = malloc(sizeof(Protocol__FlexRlcBsr) * copy->n_rlc_report);
+ if (rlc_reports == NULL)
+ goto error;
+ for (i = 0; i < copy->n_rlc_report; i++) {
+ rlc_reports[i] = copy_rlc_report(original->rlc_report[i]);
+ }
+ copy->rlc_report = rlc_reports;
+ }
+ }
+
+ if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_CE_BS) {
+ copy->has_pending_mac_ces = original->has_pending_mac_ces;
+ copy->pending_mac_ces = original->pending_mac_ces;
+
+ }
+
+ if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) {
+ copy->dl_cqi_report = copy_dl_cqi_report(original->dl_cqi_report);
+ }
+
+ if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) {
+ /*Copy the Paging Buffer report*/
+ copy->pbr = copy_paging_buffer_report(original->pbr);
+ }
+
+ if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) {
+ /*TODO: Copy the UL report*/
+ copy->ul_cqi_report = copy_ul_cqi_report(original->ul_cqi_report);
+ }
+
+ return copy;
+
+ error:
+ return NULL;
+}
+
+Protocol__FlexRlcBsr * copy_rlc_report(Protocol__FlexRlcBsr * original) {
+ Protocol__FlexRlcBsr * copy = malloc(sizeof(Protocol__FlexRlcBsr));
+ if (copy == NULL)
+ goto error;
+ protocol__flex_rlc_bsr__init(copy);
+ copy->lc_id = original->lc_id;
+ copy->has_lc_id = original->has_lc_id;
+ copy->tx_queue_size = original->tx_queue_size;
+ copy->has_tx_queue_size = original->has_tx_queue_size;
+ copy->tx_queue_hol_delay = original->tx_queue_hol_delay;
+ copy->has_tx_queue_hol_delay = original->has_tx_queue_hol_delay;
+ copy->retransmission_queue_size = original->retransmission_queue_size;
+ copy->has_retransmission_queue_size = original->has_retransmission_queue_size;
+ copy->retransmission_queue_hol_delay = original->retransmission_queue_hol_delay;
+ copy->has_retransmission_queue_hol_delay = original->has_retransmission_queue_hol_delay;
+ copy->status_pdu_size = original->status_pdu_size;
+ copy->has_status_pdu_size = original->has_status_pdu_size;
+
+ return copy;
+
+ error:
+ return NULL;
+}
+
+Protocol__FlexUlCqiReport * copy_ul_cqi_report(Protocol__FlexUlCqiReport * original) {
+ int i, j;
+
+ //Fill in the full UL CQI report of the UE
+ Protocol__FlexUlCqiReport *full_ul_report;
+ full_ul_report = malloc(sizeof(Protocol__FlexUlCqiReport));
+ if(full_ul_report == NULL) {
+ goto error;
+ }
+ protocol__flex_ul_cqi_report__init(full_ul_report);
+ //TODO:Set the SFN and SF of the generated report
+ full_ul_report->sfn_sn = original->sfn_sn;
+ full_ul_report->has_sfn_sn = original->has_sfn_sn;
+ full_ul_report->n_cqi_meas = original->n_cqi_meas;
+
+ Protocol__FlexUlCqi **ul_report;
+ ul_report = malloc(sizeof(Protocol__FlexUlCqi *) * full_ul_report->n_cqi_meas);
+ if(ul_report == NULL)
+ goto error;
+ for(i = 0; i++; i < full_ul_report->n_cqi_meas) {
+ ul_report[i] = malloc(sizeof(Protocol__FlexUlCqi));
+ if(ul_report[i] == NULL)
+ goto error;
+ protocol__flex_ul_cqi__init(ul_report[i]);
+ ul_report[i]->type = original->cqi_meas[i]->type;
+ ul_report[i]->has_type = original->cqi_meas[i]->has_type;
+ ul_report[i]->n_sinr = original->cqi_meas[i]->n_sinr;
+ uint32_t *sinr_meas;
+ sinr_meas = (uint32_t *) malloc(sizeof(uint32_t) * ul_report[i]->n_sinr);
+ if (sinr_meas == NULL)
+ goto error;
+ for (j = 0; j < ul_report[i]->n_sinr; j++) {
+ sinr_meas[j] = original->cqi_meas[i]->sinr[j];
+ }
+ ul_report[i]->sinr = sinr_meas;
+ ul_report[i]->serv_cell_index = original->cqi_meas[i]->serv_cell_index;
+ ul_report[i]->has_serv_cell_index = original->cqi_meas[i]->has_serv_cell_index;
+ }
+ full_ul_report->cqi_meas = ul_report;
+
+ return full_ul_report;
+
+ error:
+ return NULL;
+}
+
+Protocol__FlexDlCqiReport * copy_dl_cqi_report(Protocol__FlexDlCqiReport * original) {
+ int i;
+ /*Copy the DL report*/
+ Protocol__FlexDlCqiReport * dl_report;
+ dl_report = malloc(sizeof(Protocol__FlexDlCqiReport));
+ if (dl_report == NULL)
+ goto error;
+ protocol__flex_dl_cqi_report__init(dl_report);
+
+ dl_report->sfn_sn = original->sfn_sn;
+ dl_report->has_sfn_sn = original->has_sfn_sn;
+ dl_report->n_csi_report = original->n_csi_report;
+
+ Protocol__FlexDlCsi **csi_reports;
+ csi_reports = malloc(sizeof(Protocol__FlexDlCsi *) * dl_report->n_csi_report);
+ if (csi_reports == NULL)
+ goto error;
+
+ for (i = 0; i < dl_report->n_csi_report; i++) {
+ csi_reports[i] = copy_csi_report(original->csi_report[i]);
+ }
+ dl_report->csi_report = csi_reports;
+ return dl_report;
+
+ error:
+ /*TODO: Must free memory properly*/
+ return NULL;
+}
+
+Protocol__FlexPagingBufferReport * copy_paging_buffer_report(Protocol__FlexPagingBufferReport *original) {
+
+ int i;
+ Protocol__FlexPagingBufferReport *copy;
+ copy = malloc(sizeof(Protocol__FlexPagingBufferReport));
+ if (copy == NULL)
+ goto error;
+
+ protocol__flex_paging_buffer_report__init(copy);
+ copy->n_paging_info = original->n_paging_info;
+
+ Protocol__FlexPagingInfo **p_info;
+ p_info = malloc(sizeof(Protocol__FlexPagingInfo *) * copy->n_paging_info);
+ if (p_info == NULL)
+ goto error;
+ for (i = 0; i < copy->n_paging_info; i++) {
+ p_info[i] = malloc(sizeof(Protocol__FlexPagingInfo));
+ if(p_info[i] == NULL)
+ goto error;
+ protocol__flex_paging_info__init(p_info[i]);
+ p_info[i]->paging_index = original->paging_info[i]->paging_index;
+ p_info[i]->has_paging_index = original->paging_info[i]->has_paging_index;;
+ p_info[i]->paging_message_size = original->paging_info[i]->paging_message_size;
+ p_info[i]->has_paging_message_size = original->paging_info[i]->has_paging_message_size;
+ p_info[i]->paging_subframe = original->paging_info[i]->paging_subframe;
+ p_info[i]->has_paging_subframe = original->paging_info[i]->has_paging_subframe;
+ p_info[i]->carrier_index = original->paging_info[i]->carrier_index;
+ p_info[i]->has_carrier_index = original->paging_info[i]->has_carrier_index;
+ }
+ copy->paging_info = p_info;
+ return copy;
+
+ error:
+ /*TODO: free memory properly*/
+ return NULL;
+}
+
+Protocol__FlexDlCsi * copy_csi_report(Protocol__FlexDlCsi * original) {
+ int i, j;
+ Protocol__FlexDlCsi *copy = malloc(sizeof(Protocol__FlexDlCsi));
+ if (copy == NULL)
+ goto error;
+ protocol__flex_dl_csi__init(copy);
+ copy->serv_cell_index = original->serv_cell_index;
+ copy->has_serv_cell_index = original->has_serv_cell_index;
+ copy->ri = original->ri;
+ copy->has_ri = original->ri;
+
+ copy->type = original->type;
+ copy->has_type = original->has_type;
+ copy->report_case = original->report_case;
+
+ switch (copy->report_case) {
+ case PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI:
+ copy->p10csi->wb_cqi = original->p10csi->wb_cqi;
+ copy->p10csi->has_wb_cqi = original->p10csi->has_wb_cqi;
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI:
+ copy->p11csi->n_wb_cqi = original->p11csi->n_wb_cqi;
+ copy->p11csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->p11csi->n_wb_cqi);
+ for (i = 0; i < copy->p11csi->n_wb_cqi; i++) {
+ copy->p11csi->wb_cqi[i] = original->p11csi->wb_cqi[i];
+ }
+ copy->p11csi->has_wb_pmi = original->p11csi->has_wb_pmi;
+ copy->p11csi->wb_pmi = original->p11csi->wb_pmi;
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI:
+ copy->p20csi->has_wb_cqi = original->p20csi->has_wb_cqi;
+ copy->p20csi->wb_cqi = original->p20csi->wb_cqi;
+ copy->p20csi->has_sb_cqi = original->p20csi->has_sb_cqi;
+ copy->p20csi->sb_cqi = original->p20csi->sb_cqi;
+ copy->p20csi->has_bandwidth_part_index = original->p20csi->has_bandwidth_part_index;
+ copy->p20csi->bandwidth_part_index = original->p20csi->bandwidth_part_index;
+ copy->p20csi->has_sb_index = original->p20csi->has_sb_index;
+ copy->p20csi->sb_index = original->p20csi->sb_index;
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI:
+ copy->p21csi->n_wb_cqi = original->p21csi->n_wb_cqi;
+ copy->p21csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->p21csi->n_wb_cqi);
+ for (i = 0; i < copy->p21csi->n_wb_cqi; i++) {
+ copy->p21csi->wb_cqi[i] = original->p21csi->wb_cqi[i];
+ }
+ copy->p21csi->has_wb_pmi = original->p21csi->has_wb_pmi;
+ copy->p21csi->wb_pmi = original->p21csi->wb_pmi;
+ copy->p21csi->n_sb_cqi = original->p21csi->n_sb_cqi;
+ copy->p21csi->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->p21csi->n_sb_cqi);
+ for (i = 0; i < copy->p21csi->n_sb_cqi; i++) {
+ copy->p21csi->sb_cqi[i] = original->p21csi->sb_cqi[i];
+ }
+ copy->p21csi->has_badwidth_part_index = original->p21csi->has_badwidth_part_index;
+ copy->p21csi->badwidth_part_index = original->p21csi->badwidth_part_index;
+ copy->p21csi->has_sb_index = original->p21csi->has_sb_index;
+ copy->p21csi->sb_index = original->p21csi->sb_index;
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI:
+ copy->a12csi->n_wb_cqi = original->a12csi->n_wb_cqi;
+ copy->a12csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a12csi->n_wb_cqi);
+ for (i = 0; i < copy->a12csi->n_wb_cqi; i++) {
+ copy->a12csi->wb_cqi[i] = original->a12csi->wb_cqi[i];
+ }
+ copy->a12csi->n_sb_pmi = original->a12csi->n_sb_pmi;
+ copy->a12csi->sb_pmi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a12csi->n_sb_pmi);
+ for (i = 0; i < copy->a12csi->n_sb_pmi; i++) {
+ copy->a12csi->sb_pmi[i] = original->a12csi->sb_pmi[i];
+ }
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI:
+ copy->a22csi->n_wb_cqi = original->a22csi->n_wb_cqi;
+ copy->a22csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a22csi->n_wb_cqi);
+ for (i = 0; i < copy->a22csi->n_wb_cqi; i++) {
+ copy->a22csi->wb_cqi[i] = original->a22csi->wb_cqi[i];
+ }
+ copy->a22csi->n_sb_cqi = original->a22csi->n_sb_cqi;
+ copy->a22csi->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a22csi->n_sb_cqi);
+ for (i = 0; i < copy->a22csi->n_sb_cqi; i++) {
+ copy->a22csi->sb_cqi[i] = original->a22csi->sb_cqi[i];
+ }
+ copy->a22csi->has_wb_pmi = original->a22csi->has_wb_pmi;
+ copy->a22csi->wb_pmi = original->a22csi->wb_pmi;
+ copy->a22csi->has_sb_pmi = original->a22csi->has_sb_pmi;
+ copy->a22csi->sb_pmi = original->a22csi->sb_pmi;
+ copy->a22csi->n_sb_list = original->a22csi->n_sb_list;
+ copy->a22csi->sb_list = (uint32_t *) malloc(sizeof(uint32_t) * copy->a22csi->n_sb_list);
+ for (i = 0; i < copy->a22csi->n_sb_list; i++) {
+ copy->a22csi->sb_list[i] = original->a22csi->sb_list[i];
+ }
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI:
+ copy->a20csi->has_wb_cqi = original->a20csi->has_wb_cqi;
+ copy->a20csi->wb_cqi = original->a20csi->wb_cqi;
+ copy->a20csi->has_sb_cqi = original->a20csi->has_sb_cqi;
+ copy->a20csi->sb_cqi = original->a20csi->sb_cqi;
+ copy->a20csi->n_sb_list = original->a20csi->n_sb_list;
+ copy->a20csi->sb_list = (uint32_t *) malloc(sizeof(uint32_t) * copy->a20csi->n_sb_list);
+ for (i = 0; i < copy->a20csi->n_sb_list; i++) {
+ copy->a20csi->sb_list[i] = original->a20csi->sb_list[i];
+ }
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI:
+ copy->a30csi->has_wb_cqi = original->a30csi->has_wb_cqi;
+ copy->a30csi->wb_cqi = original->a30csi->wb_cqi;
+ copy->a30csi->n_sb_cqi = original->a30csi->n_sb_cqi;
+ copy->a30csi->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a30csi->n_sb_cqi);
+ for (i = 0; i < copy->a30csi->n_sb_cqi; i++) {
+ copy->a30csi->sb_cqi[i] = original->a30csi->sb_cqi[i];
+ }
+ break;
+ case PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI:
+ copy->a31csi->n_wb_cqi = original->a31csi->n_wb_cqi;
+ copy->a31csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a31csi->n_wb_cqi);
+ for (i = 0; i < copy->a31csi->n_wb_cqi; i++) {
+ copy->a31csi->wb_cqi[i] = original->a31csi->wb_cqi[i];
+ }
+ copy->a31csi->has_wb_pmi = original->a31csi->has_wb_pmi;
+ copy->a31csi->wb_pmi = original->a31csi->wb_pmi;
+ copy->a31csi->n_sb_cqi = original->a31csi->n_sb_cqi;
+ copy->a31csi->sb_cqi = malloc(sizeof(Protocol__FlexMsbCqi *) * copy->a31csi->n_sb_cqi);
+ if (copy->a31csi == NULL) {
+ goto error;
+ }
+ for (i = 0; i < copy->a31csi->n_sb_cqi; i++) {
+ copy->a31csi->sb_cqi[i] = malloc(sizeof(Protocol__FlexMsbCqi));
+ if (copy->a31csi->sb_cqi[i] == NULL) {
+ goto error;
+ }
+ protocol__flex_msb_cqi__init(copy->a31csi->sb_cqi[i]);
+ copy->a31csi->sb_cqi[i]->n_sb_cqi = original->a31csi->sb_cqi[i]->n_sb_cqi;
+ copy->a31csi->sb_cqi[i]->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a31csi->sb_cqi[i]->n_sb_cqi);
+ for (j = 0; j < copy->a31csi->sb_cqi[i]->n_sb_cqi; j++) {
+ copy->a31csi->sb_cqi[i]->sb_cqi[j] = original->a31csi->sb_cqi[i]->sb_cqi[j];
+ }
+ }
+ break;
+ default:
+ goto error;
+ }
+ return copy;
+
+ error:
+ return NULL;
+}
+
+Protocol__FlexCellStatsReport * copy_cell_stats_report(Protocol__FlexCellStatsReport *original) {
+
+ Protocol__FlexCellStatsReport * copy = malloc(sizeof(Protocol__FlexCellStatsReport));
+
+ if(copy == NULL) {
+ goto error;
+ }
+ protocol__flex_cell_stats_report__init(copy);
+ copy->carrier_index = original->carrier_index;
+ copy->has_carrier_index = original->has_carrier_index;
+ copy->flags = original->flags;
+ copy->has_flags = original->has_flags;
+
+ if(copy->flags & PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE) {
+ copy->noise_inter_report = copy_noise_inter_report(original->noise_inter_report);
+ }
+
+ return copy;
+
+ error:
+ return NULL;
+}
+
+Protocol__FlexNoiseInterferenceReport * copy_noise_inter_report(Protocol__FlexNoiseInterferenceReport *original) {
+ Protocol__FlexNoiseInterferenceReport *ni_report;
+ ni_report = malloc(sizeof(Protocol__FlexNoiseInterferenceReport));
+ if(ni_report == NULL) {
+ goto error;
+ }
+ protocol__flex_noise_interference_report__init(ni_report);
+ // Current frame and subframe number
+ ni_report->sfn_sf = original->sfn_sf;
+ ni_report->has_sfn_sf = original->sfn_sf;
+ // Received interference power in dbm
+ ni_report->rip = original->rip;
+ ni_report->has_rip = original->has_rip;
+ // Thermal noise power in dbm
+ ni_report->tnp = original->tnp;
+ ni_report->has_tnp = original->has_tnp;
+
+ return ni_report;
+
+ error:
+ return NULL;
+}
+
+
+int parse_mac_config(mid_t mod_id, yaml_parser_t *parser) {
+
+ yaml_event_t event;
+
+ int done = 0;
+
+ int sequence_started = 0;
+ int mapping_started = 0;
+
+ while (!done) {
+
+ if (!yaml_parser_parse(parser, &event))
+ goto error;
+
+ switch (event.type) {
+ case YAML_SEQUENCE_START_EVENT:
+ LOG_D(ENB_APP, "A sequence just started as expected\n");
+ sequence_started = 1;
+ break;
+ case YAML_SEQUENCE_END_EVENT:
+ LOG_D(ENB_APP, "A sequence ended\n");
+ sequence_started = 0;
+ break;
+ case YAML_MAPPING_START_EVENT:
+ if (!sequence_started) {
+ goto error;
+ }
+ LOG_D(ENB_APP, "A mapping started\n");
+ mapping_started = 1;
+ break;
+ case YAML_MAPPING_END_EVENT:
+ if (!mapping_started) {
+ goto error;
+ }
+ LOG_D(ENB_APP, "A mapping ended\n");
+ mapping_started = 0;
+ break;
+ case YAML_SCALAR_EVENT:
+ if (!mapping_started) {
+ goto error;
+ }
+ // Check the types of subsystems offered and handle their values accordingly
+ if (strcmp(event.data.scalar.value, "dl_scheduler") == 0) {
+ LOG_D(ENB_APP, "This is for the dl_scheduler subsystem\n");
+ // Call the proper handler
+ if (parse_dl_scheduler_config(mod_id, parser) == -1) {
+ LOG_D(ENB_APP, "An error occured\n");
+ goto error;
+ }
+ } else if (strcmp(event.data.scalar.value, "ul_scheduler") == 0) {
+ // Call the proper handler
+ LOG_D(ENB_APP, "This is for the ul_scheduler subsystem\n");
+ goto error;
+ // TODO
+ } else if (strcmp(event.data.scalar.value, "ra_scheduler") == 0) {
+ // Call the proper handler
+ // TODO
+ } else if (strcmp(event.data.scalar.value, "page_scheduler") == 0) {
+ // Call the proper handler
+ // TODO
+ } else {
+ // Unknown subsystem
+ goto error;
+ }
+ break;
+ default: // We expect nothing else at this level of the hierarchy
+ goto error;
+ }
+
+ done = (event.type == YAML_SEQUENCE_END_EVENT);
+
+ yaml_event_delete(&event);
+
+ }
+
+ return 0;
+
+ error:
+ yaml_event_delete(&event);
+ return -1;
+
+}
+
+int parse_dl_scheduler_config(mid_t mod_id, yaml_parser_t *parser) {
+
+ yaml_event_t event;
+
+ int done = 0;
+ int mapping_started = 0;
+
+ while (!done) {
+
+ if (!yaml_parser_parse(parser, &event))
+ goto error;
+
+ switch (event.type) {
+ // We are expecting a mapping (behavior and parameters)
+ case YAML_MAPPING_START_EVENT:
+ LOG_D(ENB_APP, "The mapping of the subsystem started\n");
+ mapping_started = 1;
+ break;
+ case YAML_MAPPING_END_EVENT:
+ LOG_D(ENB_APP, "The mapping of the subsystem ended\n");
+ mapping_started = 0;
+ break;
+ case YAML_SCALAR_EVENT:
+ if (!mapping_started) {
+ goto error;
+ }
+ // Check what key needs to be set
+ if (strcmp(event.data.scalar.value, "behavior") == 0) {
+ LOG_I(ENB_APP, "Time to set the behavior attribute\n");
+ yaml_event_delete(&event);
+ if (!yaml_parser_parse(parser, &event)) {
+ goto error;
+ }
+ if (event.type == YAML_SCALAR_EVENT) {
+ if (load_dl_scheduler_function(mod_id, event.data.scalar.value) == -1) {
+ goto error;
+ }
+ } else {
+ goto error;
+ }
+ } else if (strcmp(event.data.scalar.value, "parameters") == 0) {
+ LOG_D(ENB_APP, "Now it is time to set the parameters for this subsystem\n");
+ if (parse_dl_scheduler_parameters(mod_id, parser) == -1) {
+ goto error;
+ }
+ }
+ break;
+ default:
+ goto error;
+ }
+
+ done = (event.type == YAML_MAPPING_END_EVENT);
+ yaml_event_delete(&event);
+ }
+
+ return 0;
+
+ error:
+ yaml_event_delete(&event);
+ return -1;
+}
+
+int parse_dl_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser) {
+ yaml_event_t event;
+
+ void *param;
+
+ int done = 0;
+ int mapping_started = 0;
+
+ while (!done) {
+
+ if (!yaml_parser_parse(parser, &event))
+ goto error;
+
+ switch (event.type) {
+ // We are expecting a mapping of parameters
+ case YAML_MAPPING_START_EVENT:
+ LOG_D(ENB_APP, "The mapping of the parameters started\n");
+ mapping_started = 1;
+ break;
+ case YAML_MAPPING_END_EVENT:
+ LOG_D(ENB_APP, "The mapping of the parameters ended\n");
+ mapping_started = 0;
+ break;
+ case YAML_SCALAR_EVENT:
+ if (!mapping_started) {
+ goto error;
+ }
+ // Check what key needs to be set
+ if (mac_agent_registered[mod_id]) {
+ LOG_D(ENB_APP, "Setting parameter %s\n", event.data.scalar.value);
+ param = dlsym(agent_mac_xface[mod_id]->dl_scheduler_loaded_lib,
+ event.data.scalar.value);
+ if (param == NULL) {
+ goto error;
+ }
+ apply_parameter_modification(param, parser);
+ } else {
+ goto error;
+ }
+ break;
+ default:
+ goto error;
+ }
+
+ done = (event.type == YAML_MAPPING_END_EVENT);
+ yaml_event_delete(&event);
+ }
+
+ return 0;
+
+ error:
+ yaml_event_delete(&event);
+ return -1;
+}
+
+int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
+ void *lib;
+
+ char lib_name[120];
+ char target[512];
+ snprintf(lib_name, sizeof(lib_name), "/%s.so", function_name);
+ strcpy(target, local_cache);
+ strcat(target, lib_name);
+
+ LOG_I(FLEXRAN_AGENT, "Opening pushed code: %s\n", target);
+ lib = dlopen(target, RTLD_NOW);
+ if (lib == NULL) {
+ LOG_I(FLEXRAN_AGENT, "Could not load library\n");
+ goto error;
+ }
+
+ LOG_I(FLEXRAN_AGENT, "Loading function: %s\n", function_name);
+ void *loaded_scheduler = dlsym(lib, function_name);
+ if (loaded_scheduler) {
+ if (mac_agent_registered[mod_id]) {
+ agent_mac_xface[mod_id]->flexran_agent_schedule_ue_spec = loaded_scheduler;
+ if (agent_mac_xface[mod_id]->dl_scheduler_loaded_lib != NULL) {
+ dlclose(agent_mac_xface[mod_id]->dl_scheduler_loaded_lib);
+ }
+ agent_mac_xface[mod_id]->dl_scheduler_loaded_lib = lib;
+ LOG_I(FLEXRAN_AGENT, "New DL UE scheduler: %s\n", function_name);
+ }
+ } else {
+ LOG_I(FLEXRAN_AGENT, "Scheduler could not be loaded\n");
+ }
+
+ return 0;
+
+ error:
+ return -1;
+
+}
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h
new file mode 100644
index 0000000000..9a7d4a8555
--- /dev/null
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h
@@ -0,0 +1,106 @@
+/*
+ * 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.0 (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_internal.h
+ * \brief Implementation specific definitions for the FlexRAN MAC agent
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef FLEXRAN_AGENT_MAC_INTERNAL_H_
+#define FLEXRAN_AGENT_MAC_INTERNAL_H_
+
+#include
+
+#include
+
+#include "flexran_agent_mac.h"
+#include "flexran_agent_common.h"
+#include "flexran_agent_defs.h"
+
+/*This will be used for producing continuous status updates for the MAC
+ *Needs to be thread-safe
+ */
+typedef struct {
+ /*Flag showing if continuous mac stats update is enabled*/
+ uint8_t is_initialized;
+ volatile uint8_t cont_update;
+ xid_t xid;
+ Protocol__FlexranMessage *stats_req;
+ Protocol__FlexranMessage *prev_stats_reply;
+
+ pthread_mutex_t *mutex;
+} mac_stats_updates_context_t;
+
+/*Array holding the last stats reports for each eNB. Used for continuous reporting*/
+mac_stats_updates_context_t mac_stats_context[NUM_MAX_ENB];
+
+/*Functions to initialize and destroy the struct required for the
+ *continuous stats update report*/
+err_code_t flexran_agent_init_cont_mac_stats_update(mid_t mod_id);
+
+err_code_t flexran_agent_destroy_cont_mac_stats_update(mid_t mod_id);
+
+
+/*Enable/Disable the continuous stats update service for the MAC*/
+err_code_t flexran_agent_enable_cont_mac_stats_update(mid_t mod_id, xid_t xid,
+ stats_request_config_t *stats_req);
+
+err_code_t flexran_agent_disable_cont_mac_stats_update(mid_t mod_id);
+
+Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_report,
+ Protocol__FlexranMessage *old_report);
+
+Protocol__FlexUeStatsReport * copy_ue_stats_report(Protocol__FlexUeStatsReport * original);
+
+Protocol__FlexCellStatsReport * copy_cell_stats_report(Protocol__FlexCellStatsReport *original);
+
+Protocol__FlexRlcBsr * copy_rlc_report(Protocol__FlexRlcBsr * original);
+
+Protocol__FlexUlCqiReport * copy_ul_cqi_report(Protocol__FlexUlCqiReport * original);
+
+Protocol__FlexDlCqiReport * copy_dl_cqi_report(Protocol__FlexDlCqiReport * original);
+
+Protocol__FlexPagingBufferReport * copy_paging_buffer_report(Protocol__FlexPagingBufferReport *original);
+
+Protocol__FlexDlCsi * copy_csi_report(Protocol__FlexDlCsi * original);
+
+Protocol__FlexNoiseInterferenceReport * copy_noise_inter_report(Protocol__FlexNoiseInterferenceReport *original);
+
+int compare_ue_stats_reports(Protocol__FlexUeStatsReport *rep1,
+ Protocol__FlexUeStatsReport *rep2);
+
+int compare_cell_stats_reports(Protocol__FlexCellStatsReport *rep1,
+ Protocol__FlexCellStatsReport *rep2);
+
+
+/* Functions for parsing the MAC agent policy reconfiguration command */
+
+int parse_mac_config(mid_t mod_id, yaml_parser_t *parser);
+
+int parse_dl_scheduler_config(mid_t mod_id, yaml_parser_t *parser);
+
+int parse_dl_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser);
+
+int load_dl_scheduler_function(mid_t mod_id, const char *function_name);
+
+#endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/
diff --git a/openair2/ENB_APP/MESSAGES/V2/config_common.proto b/openair2/ENB_APP/MESSAGES/V2/config_common.proto
new file mode 100644
index 0000000000..51ae711277
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/config_common.proto
@@ -0,0 +1,180 @@
+//'syntax = "proto2";'
+package protocol;
+
+//
+// Cell config related structures and enums
+//
+
+message flex_si_config {
+ optional uint32 sfn = 1;
+ optional uint32 sib1_length = 2; // The length of SIB1 in bytes
+ optional uint32 si_window_length = 3; // The scheduling window for all SIs in SF
+ repeated flex_si_message si_message = 4; // List of SI messages to be sent.
+ // The index identifies the type of an SI message
+ // 0 - SIB1
+ // 1..31 - SIx
+ // 32..63 - PCCH
+}
+
+message flex_si_message {
+ optional uint32 periodicity = 1; // Periodicity of SI msg in radio frames
+ optional uint32 length = 2; // The length of the SI message in bytes
+}
+
+enum flex_hopping_mode {
+ FLHM_INTER = 0;
+ FLHM_INTERINTRA = 1;
+}
+
+enum flex_phich_resource {
+ FLPR_ONE_SIXTH = 0;
+ FLPR_HALF = 1;
+ FLPR_ONE = 2;
+ FLPR_TWO = 3;
+}
+
+enum flex_phich_duration {
+ FLPD_NORMAL = 0;
+ FLPD_EXTENDED = 1;
+}
+
+enum flex_ul_cyclic_prefix_length {
+ FLUCPL_NORMAL = 0;
+ FLUCPL_EXTENDED = 1;
+}
+
+enum flex_dl_cyclic_prefix_length {
+ FLDCPL_NORMAL = 0;
+ FLDCPL_EXTENDED = 1;
+}
+
+enum flex_duplex_mode {
+ FLDM_TDD = 0;
+ FLDM_FDD = 1;
+}
+
+enum flex_qam {
+ FLEQ_MOD_16QAM = 0;
+ FLEQ_MOD_64QAM = 1;
+}
+
+//
+// UE config related structures and enums
+//
+
+message flex_drx_config {
+ optional uint32 on_duration_timer = 1; // Timer in SF. See TS 36.321
+ optional uint32 drx_inactivity_timer = 2; // Timer in SF. See TS 36.321
+ optional uint32 drx_retransmission_timer = 3; // Timer in SF. See TS 36.321
+ optional uint32 long_drx_cycle = 4; // In SF. See TS 36.321
+ optional uint32 long_drx_cycle_start_offset = 5;// See TS 36.321
+ optional uint32 short_drx_cycle = 6; // In SF
+ optional uint32 drx_short_cycle_timer = 7; // Timer in subframes. See TS 36.321
+}
+
+message flex_sps_config {
+ optional uint32 semi_persistent_sched_interval_UL = 1; // SPS UL scheduling interval in SF
+ optional uint32 semi_persistent_sched_interval_DL = 2; // SPS DL scheduling interval in SF
+ optional uint32 num_of_conf_sps_proc = 3; // Number of SPS HARQ processes. See TS 36.321
+ repeated uint32 n1_PUCCH_AN_persistent_element = 4;// See TS36.213. Ignored when config is used
+ // as part of FLPT_SET_UE_CONFIG
+ optional uint32 implicit_release_after = 5; // number of empty transmissions before release of SPS
+}
+
+message flex_sr_config {
+ optional uint32 sr_action = 1; // Indicates if SR config should be changed or released
+ // One of the FLSRA_* enum values
+ optional uint32 sched_interval = 2; // SR scheduling interval in SF
+ optional uint32 dsr_trans_max = 3; // See TS 36.213
+}
+
+message flex_cqi_config {
+ optional uint32 cqi_action = 1; // Indicats if CQI changed or released.
+ // One of the FLSRA_* enum values
+ optional uint32 cqi_sched_interval = 2; // CQI scheduling interval in SF
+ optional uint32 ri_sched_interval = 3; // RI scheduling interval in SF
+}
+
+message flex_ue_capabilities {
+ optional uint32 half_duplex = 1; // Boolean value. Only half duplex support. FDD operation
+ optional uint32 intra_SF_hopping = 2; // Support for intra-subframe hopping. Boolean value
+ optional uint32 type2_sb_1 = 3; // Support for type 2 hopping with n_sb > 1
+ optional uint32 ue_category = 4;
+ optional uint32 res_alloc_type1 = 5; // Boolean value. UE support for resource allocation type 1
+}
+
+message flex_scell_config {
+ optional uint32 carrier_index = 1; // Id of the carrier component
+ optional uint32 scell_index = 2; // Index of this Scell (RRC SCellIndex)
+ optional uint32 use_ccs = 3; // Boolean value. Indicates if cross-carrier scheduling
+ // is used by this SCell
+ optional uint32 sched_cell_index = 4; // Index of the cell responsible for scheduling
+ // this SCell if cross-carrier scheduling is enabled
+ optional uint32 pdsch_start = 5; // Starting OFDM symbol of PDSCH data region for this SCell
+}
+
+enum flex_meas_gap_config_pattern {
+ FLMGCP_GP1 = 0;
+ FLMGCP_GP2 = 1;
+ FLMGCP_OFF = 2;
+}
+
+enum flex_setup_release_action {
+ FLSRA_SETUP = 0;
+ FLSRA_RELEASE = 1;
+}
+
+enum flex_ue_transmission_antenna {
+ FLUTA_NONE = 0;
+ FLUTA_OPEN_LOOP = 1;
+ FLUTA_CLOSED_LOOP = 2;
+}
+
+enum flex_aperiodic_cqi_report_mode {
+ FLACRM_RM12 = 0;
+ FLACRM_RM20 = 1;
+ FLACRM_RM22 = 2;
+ FLACRM_RM30 = 3;
+ FLACRM_RM31 = 4;
+ FLACRM_NONE = 5;
+}
+
+enum flex_tdd_ack_nack_feedback_mode {
+ FLTANFM_BUNDLING = 0;
+ FLTANFM_MULTIPLEXING = 1;
+}
+
+//
+// Logical channel config related structures and enums
+//
+
+message flex_lc_config {
+ optional uint32 lcid = 1; // The logical channel id
+ optional uint32 lcg = 2; // The logical channel group (0..3) the LC is mapped to
+ optional uint32 direction = 3; // The LC direction. One of the FLLCD_* enum values
+ optional uint32 qos_bearer_type = 4;// GBR or NGBR bearer. One of the FLQBT_* enum values
+ optional uint32 qci = 5; // The QCI defined in TS 23.203, coded as defined in TS 36.413
+ // One less than the actual QCI value
+ optional uint64 e_RAB_max_bitrate_UL = 6; // In bps (GBR only)
+ optional uint64 e_RAB_max_bitrate_DL = 7; // In bps (GBR only)
+ optional uint64 e_RAB_guaranteed_bitrate_UL = 8; // In bps (GBR only)
+ optional uint64 e_RAB_guaranteed_bitrate_DL = 9; // In bps (GBR only)
+}
+
+enum flex_lc_direction {
+ FLLCD_UL = 0;
+ FLLCD_DL = 1;
+ FLLCD_BOTH = 2;
+}
+
+enum flex_qos_bearer_type {
+ FLQBT_NON_GBR = 0;
+ FLQBT_GBR = 1;
+}
+
+enum flex_ue_state_change_type {
+ FLUESC_UPDATED = 0;
+ FLUESC_ACTIVATED = 1;
+ FLUESC_DEACTIVATED = 2;
+ FLUESC_MOVED = 3;
+}
\ No newline at end of file
diff --git a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto
new file mode 100644
index 0000000000..441e193569
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto
@@ -0,0 +1,88 @@
+//'syntax = "proto2";'
+package protocol;
+
+import "config_common.proto";
+
+message flex_cell_config {
+ optional uint32 phy_cell_id = 1; // The PCI of this cell
+ optional uint32 cell_id = 2; // The PLMN cell id of this cell
+ optional uint32 pusch_hopping_offset = 3; // PUSCH resources in RBs for hopping
+ optional uint32 hopping_mode = 4; // One of the FLHM_* enum values
+ optional uint32 n_sb = 5; // The number of subbands
+ optional uint32 phich_resource = 6; // The number of REGs used for PHICH
+ // One of the FLPR_* enum values
+ optional uint32 phich_duration = 7; // One of the FLPD_* enum values
+ optional uint32 init_nr_PDCCH_OFDM_sym = 8; // See TS 36.211, section 6.9
+ optional flex_si_config si_config = 9; // The SI configuration
+ optional uint32 dl_bandwidth = 10; // The DL transmission bandwidth in RBs
+ optional uint32 ul_bandwidth = 11; // The UL transmission bandwidth in RBs
+ optional uint32 ul_cyclic_prefix_length = 13; // One of the FLUCPL_* enum values
+ optional uint32 dl_cyclic_prefix_length = 14; // One of the FLDCPL_* enum values
+ optional uint32 antenna_ports_count = 15; // Number of cell specific antenna ports
+ optional uint32 duplex_mode = 16; // One of the FLDM_* enum values
+ optional uint32 subframe_assignment = 17; // DL/UL subframe assignment. TDD only
+ optional uint32 special_subframe_patterns = 18; // TDD only. See TS 36.211, table 4.2.1
+ repeated uint32 mbsfn_subframe_config_rfperiod = 19; // The MBSFN radio frame period (Optional)
+ repeated uint32 mbsfn_subframe_config_rfoffset = 20; // The radio frame offset (Optional)
+ repeated uint32 mbsfn_subframe_config_sfalloc = 21; // Bitmap indicating the MBSFN subframes (Optional)
+ optional uint32 prach_config_index = 22; // See TS 36.211, section 5.7.1
+ optional uint32 prach_freq_offset = 23; // See TS 36.211, section 5.7.1
+ optional uint32 ra_response_window_size = 24; // The duration of the RA response window in SF
+ optional uint32 mac_contention_resolution_timer = 25; // Timer for RA
+ optional uint32 max_HARQ_Msg3Tx = 26; // See TS 36.321
+ optional uint32 n1PUCCH_AN = 27; // See TS 36.213, section 10.1
+ optional uint32 deltaPUCCH_shift = 28; // See TS 36.211, section 5.4
+ optional uint32 nRB_cqi = 29; // See TS 36.211, section 5.4
+ optional uint32 srs_subframe_config = 30; // See TS 36.211, table 5.5.3.3-1 and 2
+ optional uint32 srs_bw_config = 31; // See TS 36.211, section 5.5.3.2
+ optional uint32 srs_mac_up_pts = 32; // Boolean value. See TS 36.211, section 5.5.3.2. TDD only
+ optional uint32 enable_64QAM = 33; // One of the FLEQ_* enum values
+ optional uint32 carrier_index = 34; // Carrier component index
+}
+
+message flex_ue_config {
+ optional uint32 rnti = 1;
+ optional flex_drx_config drx_config = 2; // The DRX configuration (Optional)
+ optional uint32 time_alignment_timer = 3; // Timer in SF. Control the synchronization
+ // status of the UE, not the actual advance procedure
+ // See TS 36.321
+ optional uint32 meas_gap_config_pattern = 4; // Measurement gap configuration.
+ // One of the FLMGCP_* enum values
+ // See TS 36.133
+ optional uint32 meas_gap_config_sf_offset = 5; // Measurement gap offset if applicable
+ optional flex_sps_config sps_config = 6; // The SPS configuration (Optional)
+ optional flex_sr_config sr_config = 7; // The SR configuration (Optional)
+ optional flex_cqi_config cqi_config = 8; // The CQI configuration (Optional)
+ optional uint32 transmission_mode = 9; // The UE transmission mode
+ optional uint64 ue_aggregated_max_bitrate_UL = 10; // Aggregated bit-rate of non-gbr bearer
+ // per UE. See TS 36.413
+ optional uint64 ue_aggregated_max_bitrate_DL = 11; // Aggregated bit-rate of non-gbr bearer
+ // per UE. See TS 36.413
+ optional flex_ue_capabilities capabilities = 12;
+ optional uint32 ue_transmission_antenna = 13; // One of the FLUTA_* enum values
+ optional uint32 tti_bundling = 14; // Boolean value. See TS 36.321
+ optional uint32 max_HARQ_tx = 15; // The max HARQ retransmission for UL
+ optional uint32 beta_offset_ACK_index = 16; // See TS 36.213
+ optional uint32 beta_offset_RI_index = 17; // See TS 36.213
+ optional uint32 beta_offset_CQI_index = 18; // See TS 36.213
+ optional uint32 ack_nack_simultaneous_trans = 19;// Boolean. See TS 36.213
+ optional uint32 simultaneous_ack_nack_cqi = 20; // Boolean. See TS 36.213
+ optional uint32 aperiodic_cqi_rep_mode = 21; // One of the FLACRM_* enum values
+ optional uint32 tdd_ack_nack_feedback = 22; // One of the FLTANFM_* enum values
+ optional uint32 ack_nack_repetition_factor = 23;// See TS 36.213, section 10.1
+ optional uint32 extended_bsr_size = 24; // Boolean for extended BSR size
+ optional uint32 ca_support = 25; // Boolean. Support for carrier aggregation
+ optional uint32 cross_carrier_sched_support = 26; // Boolean value
+ optional uint32 pcell_carrier_index = 27; // Index of primary cell
+ repeated flex_scell_config scell_config = 28; // Secondary cells configuration
+ optional uint32 scell_deactivation_timer = 29;// Deactivation timer for secondary cell
+}
+
+message flex_lc_ue_config {
+ optional uint32 rnti = 1;
+ repeated flex_lc_config lc_config = 2; // A list of LC configurations for the given UE
+}
+
+
+
+
diff --git a/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto b/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto
new file mode 100644
index 0000000000..3a5efaf7d4
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto
@@ -0,0 +1,6 @@
+//'syntax = "proto2";'
+package protocol;
+
+enum flex_control_delegation_type {
+ FLCDT_MAC_DL_UE_SCHEDULER = 1; // DL UE scheduler delegation
+}
\ No newline at end of file
diff --git a/openair2/ENB_APP/MESSAGES/V2/controller_commands.proto b/openair2/ENB_APP/MESSAGES/V2/controller_commands.proto
new file mode 100644
index 0000000000..cbec332b30
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/controller_commands.proto
@@ -0,0 +1,58 @@
+package protocol;
+
+import "mac_primitives.proto";
+
+//
+// Body of UE DL MAC scheduling configuration info
+//
+
+message flex_dl_data {
+ optional uint32 rnti = 1;
+ optional flex_dl_dci dl_dci = 2;
+ repeated uint32 ce_bitmap = 3; // list of 2 MAC CEs, one for each TB
+ repeated flex_rlc_pdu rlc_pdu = 4; // list of parameters for the creation of RLC PDUs. One for each lcid
+ optional uint32 serv_cell_index = 5;
+ optional uint32 act_deact_ce = 6; //Hex content of MAC CE for Activation/Deactivation in CA
+}
+
+//
+// Body of the RAR scheduler configuration
+//
+message flex_dl_rar {
+ optional uint32 rnti = 1;
+ optional uint32 grant = 2; // The 20-bit UL grant. TS 36.213, sec 6.2
+ optional flex_dl_dci rar_dci = 3;
+ optional uint32 carrier_index = 4; // The carrier index for the RAR
+}
+
+//
+// Body of the paging/broadcast configuration message
+//
+
+message flex_dl_broadcast {
+ optional uint32 type = 1; // The FLBT_* values
+ optional uint32 index = 2; // Index of the broadcast message:
+ // 0 - SIB1,
+ // 1..31 - Six,
+ // 32..63 - PCCH (PCCH index obtained from flex_paging_info)
+ optional flex_dl_dci broad_dci = 3;
+ optional uint32 carrier_index = 4; // Index of the carrier for broadcast
+}
+
+//
+// Body of the OFDM symbol count message
+//
+
+message flex_pdcch_ofdm_sym_count {
+ optional uint32 carrier_index = 1;
+ optional uint32 num_pdcch_ofdm_symbols = 2;
+}
+
+//
+// Types of commands related enums
+//
+
+enum flex_broadcast_type {
+ FLBT_BCCH = 0;
+ FLBT_PCCH = 1;
+}
\ No newline at end of file
diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto
new file mode 100644
index 0000000000..3a1d40bca6
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto
@@ -0,0 +1,210 @@
+//'syntax = "proto2";'
+package protocol;
+
+import "stats_messages.proto";
+import "header.proto";
+import "time_common.proto";
+import "config_messages.proto";
+import "controller_commands.proto";
+import "control_delegation.proto";
+
+message flexran_message {
+ optional flexran_direction msg_dir = 100;
+ oneof msg {
+ flex_hello hello_msg = 1;
+ flex_echo_request echo_request_msg = 2;
+ flex_echo_reply echo_reply_msg = 3;
+ flex_stats_request stats_request_msg = 4;
+ flex_stats_reply stats_reply_msg = 5;
+ flex_sf_trigger sf_trigger_msg = 6;
+ flex_ul_sr_info ul_sr_info_msg = 7;
+ flex_enb_config_request enb_config_request_msg = 8;
+ flex_enb_config_reply enb_config_reply_msg = 9;
+ flex_ue_config_request ue_config_request_msg = 10;
+ flex_ue_config_reply ue_config_reply_msg = 11;
+ flex_lc_config_request lc_config_request_msg = 12;
+ flex_lc_config_reply lc_config_reply_msg = 13;
+ flex_dl_mac_config dl_mac_config_msg = 14;
+ flex_ue_state_change ue_state_change_msg = 15;
+ flex_control_delegation control_delegation_msg = 16;
+ flex_agent_reconfiguration agent_reconfiguration_msg = 17;
+ }
+}
+
+enum flexran_direction {
+ //option allow_alias = true;
+ NOT_SET = 0;
+ INITIATING_MESSAGE = 1;
+ SUCCESSFUL_OUTCOME=2;
+ UNSUCCESSFUL_OUTCOME=3;
+}
+
+enum flexran_err {
+ option allow_alias = true;
+ // message errors
+ NO_ERR = 0;
+ MSG_DEQUEUING = -1;
+ MSG_ENQUEUING = -2;
+ MSG_DECODING = -3;
+ MSG_ENCODING = -4;
+ MSG_BUILD = -5;
+ MSG_NOT_SUPPORTED = -6;
+ MSG_NOT_HANDLED = -7;
+ MSG_NOT_VALIDATED = -8;
+ MSG_OUT_DATED = -9;
+
+
+ // other erros
+ UNEXPECTED = -100;
+}
+
+//
+// Maintenance and discovery messages
+//
+
+message flex_hello {
+ optional flex_header header = 1;
+}
+
+message flex_echo_request {
+ optional flex_header header = 1;
+ extensions 100 to 199;
+}
+
+
+message flex_echo_reply {
+ optional flex_header header = 1;
+ extensions 100 to 199;
+}
+
+
+//
+// Statistics request and reply message
+//
+
+message flex_stats_request {
+ optional flex_header header = 1;
+ optional flex_stats_type type = 2;
+ oneof body {
+ flex_complete_stats_request complete_stats_request = 3;
+ flex_cell_stats_request cell_stats_request = 4;
+ flex_ue_stats_request ue_stats_request = 5;
+ }
+}
+
+message flex_stats_reply {
+ optional flex_header header = 1;
+ repeated flex_ue_stats_report ue_report = 2;
+ repeated flex_cell_stats_report cell_report = 3;
+}
+
+//
+// Time indication messages
+//
+
+message flex_sf_trigger {
+ optional flex_header header = 1;
+ optional uint32 sfn_sf = 2;
+ repeated flex_dl_info dl_info = 3;
+ repeated flex_ul_info ul_info = 4;
+}
+
+//
+// Asynchronous messages
+//
+
+message flex_ul_sr_info {
+ optional flex_header header = 1;
+ optional uint32 sfn_sf = 2;
+ repeated uint32 rnti = 3;
+}
+
+//
+// eNB configuration messages
+//
+message flex_enb_config_request {
+ optional flex_header header = 1;
+}
+
+message flex_enb_config_reply {
+ optional flex_header header = 1;
+ optional uint32 eNB_id = 2; // Unique id to distinguish the eNB
+ repeated flex_cell_config cell_config = 3;
+}
+
+message flex_ue_config_request {
+ optional flex_header header = 1;
+}
+
+message flex_ue_config_reply {
+ optional flex_header header = 1;
+ repeated flex_ue_config ue_config = 2;
+}
+
+message flex_lc_config_request {
+ optional flex_header header = 1;
+}
+
+message flex_lc_config_reply {
+ optional flex_header header = 1;
+ repeated flex_lc_ue_config lc_ue_config = 2;
+}
+
+//
+// Controller command messages
+//
+
+message flex_dl_mac_config {
+ optional flex_header header = 1;
+ optional uint32 sfn_sf = 2;
+ repeated flex_dl_data dl_ue_data = 3;
+ repeated flex_dl_rar dl_rar = 4;
+ repeated flex_dl_broadcast dl_broadcast = 5;
+ repeated flex_pdcch_ofdm_sym_count ofdm_sym = 6; // OFDM symbol count for each CC
+}
+
+//
+// UE state change message
+//
+
+message flex_ue_state_change {
+ optional flex_header header = 1;
+ optional uint32 type = 2; // One of the FLUESC_* values
+ optional flex_ue_config config = 3; // Body of the message (based on type)
+}
+
+//
+// Control delegation message
+//
+
+message flex_control_delegation {
+ optional flex_header header = 1;
+ optional uint32 delegation_type = 2; // Bitmap of FLCDT_* flags
+ optional bytes payload = 3; // Byte array of shared lib containing the delegated functions
+ optional string name = 4; // The delegated functions names ordered based on bitmap flags
+}
+
+//
+// Agent reconfiguration message
+//
+
+message flex_agent_reconfiguration {
+ optional flex_header header = 1;
+ optional string policy = 2; // The policy changes using YAML syntax in string format
+}
+
+// Extensions of the echo request and reply
+// messages for carrying a latency value in ms
+message flex_echo_request_latency {
+ extend flex_echo_request {
+ optional uint32 latency = 100;
+ }
+}
+
+message flex_echo_reply_latency {
+ extend flex_echo_reply {
+ optional uint32 latency = 100;
+ }
+}
+
+
diff --git a/openair2/ENB_APP/MESSAGES/V2/header.proto b/openair2/ENB_APP/MESSAGES/V2/header.proto
new file mode 100644
index 0000000000..dfd5ea6c99
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/header.proto
@@ -0,0 +1,43 @@
+package protocol;
+
+message flex_header {
+ optional uint32 version = 1;
+ optional uint32 type = 2;
+ optional uint32 xid = 4;
+}
+
+enum flex_type {
+ // Discovery and maintenance messages
+ FLPT_HELLO = 0;
+ FLPT_ECHO_REQUEST = 1;
+ FLPT_ECHO_REPLY = 2;
+
+ // Statistics and measurement messages
+ FLPT_STATS_REQUEST = 3;
+ FLPT_STATS_REPLY = 4;
+
+ // Time indication messages
+ FLPT_SF_TRIGGER = 5;
+
+ // Asynchronous messages
+ FLPT_UL_SR_INFO = 6;
+
+ // eNB configuration messages
+ FLPT_GET_ENB_CONFIG_REQUEST = 7;
+ FLPT_GET_ENB_CONFIG_REPLY = 8;
+ FLPT_GET_UE_CONFIG_REQUEST = 9;
+ FLPT_GET_UE_CONFIG_REPLY = 10;
+ FLPT_GET_LC_CONFIG_REQUEST = 11;
+ FLPT_GET_LC_CONFIG_REPLY = 12;
+
+ //Controller command messages
+ FLPT_DL_MAC_CONFIG = 13;
+
+ // UE state change messages
+ FLPT_UE_STATE_CHANGE = 14;
+
+ // Control delegation messages
+ FLPT_DELEGATE_CONTROL = 15;
+ FLPT_RECONFIGURE_AGENT = 16;
+}
+
diff --git a/openair2/ENB_APP/MESSAGES/V2/mac_primitives.proto b/openair2/ENB_APP/MESSAGES/V2/mac_primitives.proto
new file mode 100644
index 0000000000..be7c72ab7b
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/mac_primitives.proto
@@ -0,0 +1,76 @@
+package protocol;
+
+//
+// Message containing the DL DCI info
+//
+
+message flex_dl_dci {
+ optional uint32 rnti = 1;
+ optional uint32 res_alloc = 2; // Type of resource allocation
+ optional uint32 rb_bitmap = 3; // Bitmap for RB allocation
+ optional uint32 rb_shift = 4; // See TS 36.214, section 7.1.6.2
+ repeated uint32 tbs_size = 5; // The size of each TBS
+ repeated uint32 mcs = 6; // The MCS of each TB
+ repeated uint32 ndi = 7; // New data indicator of each TB
+ repeated uint32 rv = 8; // Redundancy version of each TB
+ optional uint32 cce_index = 9; // CCE index used to send the DCI
+ optional uint32 aggr_level = 10;
+ optional uint32 precoding_info = 11; // 2 antenna ports:0..6,
+ // 4 antenna ports:0..50
+ optional uint32 format = 12; // DCI format. A FLDCIF_* value
+ optional uint32 tpc = 13; // TS 36.213, sec 5.1.1.1
+ optional uint32 harq_process = 14; // HARQ process ID
+ optional uint32 dai = 15; // TDD only
+ optional uint32 vrb_format = 16; // One of the FLVRBF_* values
+ optional uint32 tb_swap = 17; // Boolean. TB to codeword swap flag
+ optional uint32 sps_release = 18; // Flag value
+ optional uint32 pdcch_order = 19;
+ optional uint32 preamble_index = 20; // Only valid if pdcch_order = 1
+ optional uint32 prach_mask_index = 21; // Only valid if pdcch_order = 1
+ optional uint32 n_gap = 22; // One of the FLNGV_* values
+ optional uint32 tbs_idx = 23; // The TBS index for Format 1A
+ optional uint32 dl_power_offset = 24; // For format 1D
+ optional uint32 pdcch_power_offset = 25; // DL PDCCH power boosting in dB
+ optional uint32 cif_present = 26; // Boolean. Indication of CIF field
+ optional uint32 cif = 27; // CIF for cross-carrier scheduling
+}
+
+//
+// Messages related to the creation of RLC PDUs
+//
+
+message flex_rlc_pdu {
+ repeated flex_rlc_pdu_tb rlc_pdu_tb = 1; // list of parameters for the creation of RLC PDUs. One for each TB
+}
+
+message flex_rlc_pdu_tb {
+ optional uint32 logical_channel_id = 1;
+ optional uint32 size = 2; // Maximum RLC PDU to be created in bytes
+}
+
+//
+// MAC content types related enums
+//
+
+enum flex_dci_format {
+ FLDCIF_1 = 0;
+ FLDCIF_1A = 1;
+ FLDCIF_1B = 2;
+ FLDCIF_1C = 3;
+ FLDCIF_1D = 4;
+ FLDCIF_2 = 5;
+ FLDCIF_2A = 6;
+ FLDCIF_2B = 7;
+ FLDCIF_3 = 8;
+ FLDCIF_3A = 9;
+}
+
+enum flex_vrb_format {
+ FLVRBF_LOCALIZED = 0;
+ FLVRBF_DISTRIBUTED = 1;
+}
+
+enum flex_ngap_val {
+ FLNGV_1 = 0;
+ FLNGV_2 = 1;
+}
\ No newline at end of file
diff --git a/openair2/ENB_APP/MESSAGES/V2/stats_common.proto b/openair2/ENB_APP/MESSAGES/V2/stats_common.proto
new file mode 100644
index 0000000000..70f99618ac
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/stats_common.proto
@@ -0,0 +1,182 @@
+package protocol;
+
+//
+// UE related statistics
+//
+
+// RLC buffer status for a specific logical channel of a UE
+message flex_rlc_bsr {
+ optional uint32 lc_id = 1;
+ optional uint32 tx_queue_size = 2;
+ optional uint32 tx_queue_hol_delay = 3;
+ optional uint32 retransmission_queue_size = 4;
+ optional uint32 retransmission_queue_hol_delay = 5;
+ optional uint32 status_pdu_size = 6;
+}
+
+// Flags for MAC Control Elements
+enum flex_ce_type {
+ FLPCET_TA = 1;
+ FLPCET_DRX = 2;
+ FLPCET_CR = 4;
+ FLPCET_CA = 8;
+}
+
+// Types of DL CSI reports
+enum flex_csi_type {
+ FLCSIT_P10 = 0;
+ FLCSIT_P11 = 1;
+ FLCSIT_P20 = 2;
+ FLCSIT_P21 = 3;
+ FLCSIT_A12 = 4;
+ FLCSIT_A22 = 5;
+ FLCSIT_A20 = 6;
+ FLCSIT_A30 = 7;
+ FLCSIT_A31 = 8;
+}
+
+// CSI type P10
+message flex_csi_p10 {
+ optional uint32 wb_cqi = 1;
+}
+
+// CSI type P11
+message flex_csi_p11 {
+ repeated uint32 wb_cqi = 1;
+ optional uint32 wb_pmi = 2;
+}
+
+// CSI type P20
+message flex_csi_p20 {
+ optional uint32 wb_cqi = 1;
+ optional uint32 sb_cqi = 2;
+ optional uint32 bandwidth_part_index = 3;
+ optional uint32 sb_index = 4;
+}
+
+// CSI type P21
+message flex_csi_p21 {
+ repeated uint32 wb_cqi = 1;
+ optional uint32 wb_pmi = 2;
+ repeated uint32 sb_cqi = 3;
+ optional uint32 badwidth_part_index = 4;
+ optional uint32 sb_index = 5;
+}
+
+// CSI type A12
+message flex_csi_a12 {
+ repeated uint32 wb_cqi = 1;
+ repeated uint32 sb_pmi = 2;
+}
+
+// CSI type A22
+message flex_csi_a22 {
+ repeated uint32 wb_cqi = 1;
+ repeated uint32 sb_cqi = 2;
+ optional uint32 wb_pmi = 3;
+ optional uint32 sb_pmi = 4;
+ repeated uint32 sb_list = 5;
+}
+
+// CSI type A20
+message flex_csi_a20 {
+ optional uint32 wb_cqi = 1;
+ optional uint32 sb_cqi = 2;
+ repeated uint32 sb_list = 3;
+}
+
+// CSI type A30
+message flex_csi_a30 {
+ optional uint32 wb_cqi = 1;
+ repeated uint32 sb_cqi = 2;
+}
+
+// CSI type A31
+message flex_csi_a31 {
+ repeated uint32 wb_cqi = 1;
+ repeated flex_msb_cqi sb_cqi = 2;
+ optional uint32 wb_pmi = 3;
+}
+
+// The CQI for the M-preffered subband
+message flex_msb_cqi {
+ repeated uint32 sb_cqi = 1;
+}
+
+// The CSI report of the UE for a specific servCellIndex
+message flex_dl_csi {
+ optional uint32 serv_cell_index = 1;
+ optional uint32 ri = 2;
+ optional flex_csi_type type = 3;
+ oneof report {
+ flex_csi_p10 p10csi = 4;
+ flex_csi_p11 p11csi = 5;
+ flex_csi_p20 p20csi = 6;
+ flex_csi_p21 p21csi = 7;
+ flex_csi_a12 a12csi = 8;
+ flex_csi_a22 a22csi = 9;
+ flex_csi_a20 a20csi = 10;
+ flex_csi_a30 a30csi = 11;
+ flex_csi_a31 a31csi = 12;
+ }
+}
+
+// The full DL CQI report for all CC of a UE
+message flex_dl_cqi_report {
+ optional uint32 sfn_sn = 1;
+ repeated flex_dl_csi csi_report = 2;
+}
+
+// Paging message info
+message flex_paging_info {
+ optional uint32 paging_index = 1;
+ optional uint32 paging_message_size = 2;
+ optional uint32 paging_subframe = 3;
+ optional uint32 carrier_index = 4;
+}
+
+// Report for the paging buffer status
+message flex_paging_buffer_report {
+ repeated flex_paging_info paging_info = 1;
+}
+
+// The type of UL CQI
+enum flex_ul_cqi_type {
+ FLUCT_SRS = 0;
+ FLUCT_PUSCH = 1;
+ FLUCT_PUCCH_1 = 2;
+ FLUCT_PUCCH_2 = 3;
+ FLUCT_PRACH = 4;
+}
+
+// UL CQI report for a specific UE for a given report type
+message flex_ul_cqi {
+ optional flex_ul_cqi_type type = 1;
+ repeated uint32 sinr = 2;
+ optional uint32 serv_cell_index = 3;
+}
+
+// Full UL CQI report for a specific UE
+message flex_ul_cqi_report {
+ optional uint32 sfn_sn = 1;
+ repeated flex_ul_cqi cqi_meas = 2;
+ repeated flex_pucch_dbm pucch_dbm = 3;
+}
+
+message flex_pucch_dbm {
+ optional int32 p0_pucch_dbm = 1;
+ optional uint32 serv_cell_index = 2;
+}
+
+//
+// Cell related statistics
+//
+
+// The UL noise and interference report for a UE
+message flex_noise_interference_report {
+ optional uint32 sfn_sf = 1;
+ optional uint32 rip = 2;
+ optional uint32 tnp = 3;
+ optional int32 p0_nominal_pucch = 4;
+}
+
diff --git a/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto b/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto
new file mode 100644
index 0000000000..1b1567dda1
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto
@@ -0,0 +1,86 @@
+package protocol;
+
+//import "header.proto";
+import "stats_common.proto";
+
+//
+// Bodies of statistics report requests
+//
+
+message flex_complete_stats_request {
+ optional flex_stats_report_freq report_frequency = 1;
+ optional uint32 sf = 2;
+ optional uint32 cell_report_flags = 3;
+ optional uint32 ue_report_flags = 4;
+}
+
+message flex_cell_stats_request {
+ repeated uint32 cell = 1;
+ optional uint32 flags = 2;
+}
+
+message flex_ue_stats_request {
+ repeated uint32 rnti = 1;
+ optional uint32 flags = 2;
+}
+
+//
+// Bodies of statistics reports
+//
+
+// The full statistics report for a specific cell
+message flex_cell_stats_report {
+ optional uint32 carrier_index = 1;
+ optional uint32 flags = 2;
+ optional flex_noise_interference_report noise_inter_report = 3;
+}
+
+// Statistics report for a specific UE
+message flex_ue_stats_report {
+ optional uint32 rnti = 1;
+ optional uint32 flags = 2;
+ repeated uint32 bsr = 3;
+ optional uint32 phr = 4;
+ repeated flex_rlc_bsr rlc_report = 5;
+ optional uint32 pending_mac_ces = 6;
+ optional flex_dl_cqi_report dl_cqi_report = 7;
+ optional flex_paging_buffer_report pbr = 8;
+ optional flex_ul_cqi_report ul_cqi_report = 9;
+}
+
+//
+// Types of statistics related enums
+//
+
+
+//Types of statistics requested by the controller
+enum flex_stats_type {
+ FLST_COMPLETE_STATS = 0;
+ FLST_CELL_STATS = 1;
+ FLST_UE_STATS = 2;
+}
+
+// Report frequency for the requested statistics
+enum flex_stats_report_freq {
+ FLSRF_ONCE = 0;
+ FLSRF_PERIODICAL = 1;
+ FLSRF_CONTINUOUS = 2;
+ FLSRF_OFF = 3;
+}
+
+// Flags for cell statistics
+enum flex_cell_stats_type {
+ FLCST_NOISE_INTERFERENCE = 1;
+}
+
+// Flags for UE-related statistics
+enum flex_ue_stats_type {
+ FLUST_BSR = 1;
+ FLUST_PRH = 2;
+ FLUST_RLC_BS = 4;
+ FLUST_MAC_CE_BS = 8;
+ FLUST_DL_CQI = 16;
+ FLUST_PBS = 32;
+ FLUST_UL_CQI = 64;
+ // To be extended with more types of stats
+}
\ No newline at end of file
diff --git a/openair2/ENB_APP/MESSAGES/V2/time_common.proto b/openair2/ENB_APP/MESSAGES/V2/time_common.proto
new file mode 100644
index 0000000000..30a56bb776
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/time_common.proto
@@ -0,0 +1,29 @@
+package protocol;
+
+enum flex_harq_status {
+ FLHS_ACK = 0;
+ FLHS_NACK = 1;
+ FLHS_DTX = 2;
+}
+
+enum flex_reception_status {
+ FLRS_OK = 0;
+ FLRS_NOT_OK = 1;
+ FLRS_NOT_VALID = 2;
+}
+
+message flex_dl_info {
+ optional uint32 rnti = 1;
+ optional uint32 harq_process_id = 2;
+ repeated uint32 harq_status = 3;
+ optional uint32 serv_cell_index = 4;
+}
+
+message flex_ul_info {
+ optional uint32 rnti = 1;
+ repeated uint32 ul_reception = 2;
+ optional uint32 reception_status = 3;
+ optional uint32 tpc = 4;
+ optional uint32 serv_cell_index = 5;
+}
+
diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c
index 217f44fcf5..3734bc4a2b 100644
--- a/openair2/ENB_APP/enb_app.c
+++ b/openair2/ENB_APP/enb_app.c
@@ -49,6 +49,10 @@
# include "gtpv1u_eNB_task.h"
# endif
+#if defined(FLEXRAN_AGENT_SB_IF)
+# include "flexran_agent.h"
+#endif
+
extern unsigned char NB_eNB_INST;
#endif
@@ -287,7 +291,7 @@ void *eNB_app_task(void *args_p)
itti_mark_task_ready (TASK_ENB_APP);
-# if defined(ENABLE_USE_MME)
+ # if defined(ENABLE_ITTI)
# if defined(OAI_EMU)
enb_nb = oai_emulation.info.nb_enb_local;
enb_id_start = oai_emulation.info.first_enb_local;
@@ -297,7 +301,7 @@ void *eNB_app_task(void *args_p)
"Last eNB index is greater or equal to maximum eNB index (%d/%d)!",
enb_id_end, NUMBER_OF_eNB_MAX);
# endif
-# endif
+ # endif
enb_properties_p = enb_config_get();
@@ -310,6 +314,14 @@ void *eNB_app_task(void *args_p)
configure_rrc(enb_id, enb_properties_p);
}
+#if defined (FLEXRAN_AGENT_SB_IF)
+
+ for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
+ printf("\n start enb agent %d\n", enb_id);
+ flexran_agent_start(enb_id, enb_properties_p);
+ }
+#endif
+
# if defined(ENABLE_USE_MME)
/* Try to register each eNB */
registered_enb = 0;
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index eb31e62362..fb4c6266ca 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -190,6 +190,12 @@
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U "ENB_IPV4_ADDRESS_FOR_S1U"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_S1U "ENB_PORT_FOR_S1U"
+#define ENB_CONFIG_STRING_NETWORK_CONTROLLER_CONFIG "NETWORK_CONTROLLER"
+#define ENB_CONFIG_STRING_FLEXRAN_AGENT_INTERFACE_NAME "FLEXRAN_AGENT_INTERFACE_NAME"
+#define ENB_CONFIG_STRING_FLEXRAN_AGENT_IPV4_ADDRESS "FLEXRAN_AGENT_IPV4_ADDRESS"
+#define ENB_CONFIG_STRING_FLEXRAN_AGENT_PORT "FLEXRAN_AGENT_PORT"
+#define ENB_CONFIG_STRING_FLEXRAN_AGENT_CACHE "FLEXRAN_AGENT_CACHE"
+
#define ENB_CONFIG_STRING_RRH_GW_CONFIG "rrh_gw_config"
#define ENB_CONFIG_STRING_RRH_GW_LOCAL_IF_NAME "local_if_name"
#define ENB_CONFIG_STRING_RRH_GW_LOCAL_ADDRESS "local_address"
@@ -335,6 +341,15 @@ void enb_config_display(void)
}
}
+#if defined(FLEXRAN_AGENT_SB_IF)
+ printf( "\nFLEXRAN AGENT CONFIG : \n\n");
+ printf( "\tInterface name: \t%s:\n",enb_properties.properties[i]->flexran_agent_interface_name);
+ printf( "\tInterface IP Address: \t%s:\n",enb_properties.properties[i]->flexran_agent_ipv4_address);
+ printf( "\tInterface PORT: \t%d:\n\n",enb_properties.properties[i]->flexran_agent_port);
+ printf( "\tCache directory: \t%s:\n",enb_properties.properties[i]->flexran_agent_cache);
+
+#endif
+
for (j=0; j< enb_properties.properties[i]->nb_cc; j++) {
// CC_ID node function/timing
printf( "\n\tnode_function for CC %d: \t%s:\n",j,eNB_functions[enb_properties.properties[i]->cc_node_function[j]]);
@@ -659,6 +674,10 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
char *address = NULL;
char *cidr = NULL;
char *astring = NULL;
+ char* flexran_agent_interface_name = NULL;
+ char* flexran_agent_ipv4_address = NULL;
+ libconfig_int flexran_agent_port = 0;
+ char* flexran_agent_cache = NULL;
libconfig_int otg_ue_id = 0;
char* otg_app_type = NULL;
char* otg_bg_traffic = NULL;
@@ -1053,14 +1072,14 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
if ((nb_antennas_tx <1) || (nb_antennas_tx > 64))
AssertFatal (0,
- "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for nb_antennas_tx choice: 1..4 !\n",
+ "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for nb_antennas_tx choice: 1..64 !\n",
lib_config_file_name_pP, i, nb_antennas_tx);
enb_properties.properties[enb_properties_index]->nb_antennas_rx[j] = nb_antennas_rx;
- if ((nb_antennas_rx <1) || (nb_antennas_rx > 4))
+ if ((nb_antennas_rx <1) || (nb_antennas_rx > 64))
AssertFatal (0,
- "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for nb_antennas_rx choice: 1..4 !\n",
+ "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for nb_antennas_rx choice: 1..64 !\n",
lib_config_file_name_pP, i, nb_antennas_rx);
enb_properties.properties[enb_properties_index]->tx_gain[j] = tx_gain;
@@ -2456,6 +2475,35 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
}
}
}
+
+ // Network Controller
+ subsetting = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_NETWORK_CONTROLLER_CONFIG);
+
+ if (subsetting != NULL) {
+ if ( (
+ config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_INTERFACE_NAME,
+ (const char **)&flexran_agent_interface_name)
+ && config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_IPV4_ADDRESS,
+ (const char **)&flexran_agent_ipv4_address)
+ && config_setting_lookup_int(subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_PORT,
+ &flexran_agent_port)
+ && config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_CACHE,
+ (const char **)&flexran_agent_cache)
+ )
+ ) {
+ enb_properties.properties[enb_properties_index]->flexran_agent_interface_name = strdup(flexran_agent_interface_name);
+ cidr = flexran_agent_ipv4_address;
+ address = strtok(cidr, "/");
+ enb_properties.properties[enb_properties_index]->flexran_agent_ipv4_address = strdup(address);
+ /* if (address) {
+ IPV4_STR_ADDR_TO_INT_NWBO (address, enb_properties.properties[enb_properties_index]->flexran_agent_ipv4_address, "BAD IP ADDRESS FORMAT FOR eNB Agent !\n" );
+ }*/
+
+ enb_properties.properties[enb_properties_index]->flexran_agent_port = flexran_agent_port;
+ enb_properties.properties[enb_properties_index]->flexran_agent_cache = strdup(flexran_agent_cache);
+ }
+ }
+
// OTG _CONFIG
setting_otg = config_setting_get_member (setting_enb, ENB_CONF_STRING_OTG_CONFIG);
diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h
index 9e53af172d..fd53395311 100644
--- a/openair2/ENB_APP/enb_config.h
+++ b/openair2/ENB_APP/enb_config.h
@@ -228,6 +228,10 @@ typedef struct Enb_properties_s {
char *enb_interface_name_for_S1_MME;
in_addr_t enb_ipv4_address_for_S1_MME;
+ char *flexran_agent_interface_name;
+ in_addr_t flexran_agent_ipv4_address;
+ tcp_udp_port_t flexran_agent_port;
+ char *flexran_agent_cache;
/* Nb of RRH to connect to */
uint8_t nb_rrh_gw;
diff --git a/openair2/ENB_APP/flexran_agent.c b/openair2/ENB_APP/flexran_agent.c
new file mode 100644
index 0000000000..beca1062bd
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent.c
@@ -0,0 +1,319 @@
+/*
+ * 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.0 (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.h
+ * \brief top level flexran agent receive thread and itti task
+ * \author Xenofon Foukas and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+#include "flexran_agent_common.h"
+#include "log.h"
+#include "flexran_agent.h"
+#include "flexran_agent_mac_defs.h"
+
+#include "flexran_agent_extern.h"
+
+#include "assertions.h"
+
+#include "flexran_agent_net_comm.h"
+#include "flexran_agent_async.h"
+
+//#define TEST_TIMER
+
+flexran_agent_instance_t flexran_agent[NUM_MAX_ENB];
+
+char in_ip[40];
+static uint16_t in_port;
+char local_cache[40];
+
+void *send_thread(void *args);
+void *receive_thread(void *args);
+pthread_t new_thread(void *(*f)(void *), void *b);
+Protocol__FlexranMessage *flexran_agent_timeout(void* args);
+
+
+int agent_task_created = 0;
+/*
+ * enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller
+ * and can interact with other itti tasks
+*/
+void *flexran_agent_task(void *args){
+
+ //flexran_agent_instance_t *d = (flexran_agent_instance_t *) args;
+ Protocol__FlexranMessage *msg;
+ void *data;
+ int size;
+ err_code_t err_code;
+ int priority;
+
+ MessageDef *msg_p = NULL;
+ const char *msg_name = NULL;
+ instance_t instance;
+ int result;
+ struct flexran_agent_timer_element_s * elem = NULL;
+
+ itti_mark_task_ready(TASK_FLEXRAN_AGENT);
+
+ do {
+ // Wait for a message
+ itti_receive_msg (TASK_FLEXRAN_AGENT, &msg_p);
+ DevAssert(msg_p != NULL);
+ msg_name = ITTI_MSG_NAME (msg_p);
+ instance = ITTI_MSG_INSTANCE (msg_p);
+
+ switch (ITTI_MSG_ID(msg_p)) {
+ case TERMINATE_MESSAGE:
+ itti_exit_task ();
+ break;
+
+ case MESSAGE_TEST:
+ LOG_I(FLEXRAN_AGENT, "Received %s\n", ITTI_MSG_NAME(msg_p));
+ break;
+
+ case TIMER_HAS_EXPIRED:
+ msg = flexran_agent_process_timeout(msg_p->ittiMsg.timer_has_expired.timer_id, msg_p->ittiMsg.timer_has_expired.arg);
+ if (msg != NULL){
+ data=flexran_agent_pack_message(msg,&size);
+ elem = get_timer_entry(msg_p->ittiMsg.timer_has_expired.timer_id);
+ if (flexran_agent_msg_send(elem->agent_id, FLEXRAN_AGENT_DEFAULT, data, size, priority)) {
+ err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+ goto error;
+ }
+
+ LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+ }
+ break;
+
+ default:
+ LOG_E(FLEXRAN_AGENT, "Received unexpected message %s\n", msg_name);
+ break;
+ }
+
+ result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
+ AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+ continue;
+ error:
+ LOG_E(FLEXRAN_AGENT,"flexran_agent_task: error %d occured\n",err_code);
+ } while (1);
+
+ return NULL;
+}
+
+void *receive_thread(void *args) {
+
+ flexran_agent_instance_t *d = args;
+ void *data;
+ int size;
+ int priority;
+ err_code_t err_code;
+
+ Protocol__FlexranMessage *msg;
+
+ while (1) {
+
+ while (flexran_agent_msg_recv(d->enb_id, FLEXRAN_AGENT_DEFAULT, &data, &size, &priority) == 0) {
+
+ LOG_D(FLEXRAN_AGENT,"received message with size %d\n", size);
+
+ // Invoke the message handler
+ msg=flexran_agent_handle_message(d->enb_id, data, size);
+
+ free(data);
+
+ // check if there is something to send back to the controller
+ if (msg != NULL){
+ data=flexran_agent_pack_message(msg,&size);
+
+ if (flexran_agent_msg_send(d->enb_id, FLEXRAN_AGENT_DEFAULT, data, size, priority)) {
+ err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+ goto error;
+ }
+
+ LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+ }
+ }
+ }
+
+ return NULL;
+
+error:
+ LOG_E(FLEXRAN_AGENT,"receive_thread: error %d occured\n",err_code);
+ return NULL;
+}
+
+
+/* utility function to create a thread */
+pthread_t new_thread(void *(*f)(void *), void *b) {
+ pthread_t t;
+ pthread_attr_t att;
+
+ if (pthread_attr_init(&att)){
+ fprintf(stderr, "pthread_attr_init err\n");
+ exit(1);
+ }
+
+ struct sched_param sched_param_recv_thread;
+
+ sched_param_recv_thread.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1;
+ pthread_attr_setschedparam(&att, &sched_param_recv_thread);
+ pthread_attr_setschedpolicy(&att, SCHED_FIFO);
+
+ if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) {
+ fprintf(stderr, "pthread_attr_setdetachstate err\n");
+ exit(1);
+ }
+ if (pthread_create(&t, &att, f, b)) {
+ fprintf(stderr, "pthread_create err\n");
+ exit(1);
+ }
+ if (pthread_attr_destroy(&att)) {
+ fprintf(stderr, "pthread_attr_destroy err\n");
+ exit(1);
+ }
+
+ return t;
+}
+
+int channel_container_init = 0;
+int flexran_agent_start(mid_t mod_id, const Enb_properties_array_t* enb_properties){
+
+ int channel_id;
+
+ flexran_set_enb_vars(mod_id, RAN_LTE_OAI);
+ flexran_agent[mod_id].enb_id = mod_id;
+
+ /*
+ * check the configuration
+ */
+ if (enb_properties->properties[mod_id]->flexran_agent_cache != NULL) {
+ strncpy(local_cache, enb_properties->properties[mod_id]->flexran_agent_cache, sizeof(local_cache));
+ local_cache[sizeof(local_cache) - 1] = 0;
+ } else {
+ strcpy(local_cache, DEFAULT_FLEXRAN_AGENT_CACHE);
+ }
+
+ if (enb_properties->properties[mod_id]->flexran_agent_ipv4_address != NULL) {
+ strncpy(in_ip, enb_properties->properties[mod_id]->flexran_agent_ipv4_address, sizeof(in_ip) );
+ in_ip[sizeof(in_ip) - 1] = 0; // terminate string
+ } else {
+ strcpy(in_ip, DEFAULT_FLEXRAN_AGENT_IPv4_ADDRESS );
+ }
+
+ if (enb_properties->properties[mod_id]->flexran_agent_port != 0 ) {
+ in_port = enb_properties->properties[mod_id]->flexran_agent_port;
+ } else {
+ in_port = DEFAULT_FLEXRAN_AGENT_PORT ;
+ }
+ LOG_I(FLEXRAN_AGENT,"starting enb agent client for module id %d on ipv4 %s, port %d\n",
+ flexran_agent[mod_id].enb_id,
+ in_ip,
+ in_port);
+
+ /*
+ * Initialize the channel container
+ */
+ if (!channel_container_init) {
+ flexran_agent_init_channel_container();
+ channel_container_init = 1;
+ }
+ /*Create the async channel info*/
+ flexran_agent_instance_t *channel_info = flexran_agent_async_channel_info(mod_id, in_ip, in_port);
+
+ /*Create a channel using the async channel info*/
+ channel_id = flexran_agent_create_channel((void *) channel_info,
+ flexran_agent_async_msg_send,
+ flexran_agent_async_msg_recv,
+ flexran_agent_async_release);
+
+
+ if (channel_id <= 0) {
+ goto error;
+ }
+
+ flexran_agent_channel_t *channel = get_channel(channel_id);
+
+ if (channel == NULL) {
+ goto error;
+ }
+
+ /*Register the channel for all underlying agents (use FLEXRAN_AGENT_MAX)*/
+ flexran_agent_register_channel(mod_id, channel, FLEXRAN_AGENT_MAX);
+
+ /*Example of registration for a specific agent(MAC):
+ *flexran_agent_register_channel(mod_id, channel, FLEXRAN_AGENT_MAC);
+ */
+
+ /*Initialize the continuous MAC stats update mechanism*/
+ flexran_agent_init_cont_mac_stats_update(mod_id);
+
+ new_thread(receive_thread, &flexran_agent[mod_id]);
+
+ /*Initialize and register the mac xface. Must be modified later
+ *for more flexibility in agent management */
+
+ AGENT_MAC_xface *mac_agent_xface = (AGENT_MAC_xface *) malloc(sizeof(AGENT_MAC_xface));
+ flexran_agent_register_mac_xface(mod_id, mac_agent_xface);
+
+ /*
+ * initilize a timer
+ */
+
+ flexran_agent_init_timer();
+
+ /*
+ * Initialize the mac agent
+ */
+ flexran_agent_init_mac_agent(mod_id);
+
+ /*
+ * start the enb agent task for tx and interaction with the underlying network function
+ */
+ if (!agent_task_created) {
+ if (itti_create_task (TASK_FLEXRAN_AGENT, flexran_agent_task, (void *) &flexran_agent[mod_id]) < 0) {
+ LOG_E(FLEXRAN_AGENT, "Create task for FlexRAN Agent failed\n");
+ return -1;
+ }
+ agent_task_created = 1;
+ }
+
+ LOG_I(FLEXRAN_AGENT,"client ends\n");
+ return 0;
+
+error:
+ LOG_I(FLEXRAN_AGENT,"there was an error\n");
+ return 1;
+
+}
+
+Protocol__FlexranMessage *flexran_agent_timeout(void* args){
+
+ // flexran_agent_timer_args_t *timer_args = calloc(1, sizeof(*timer_args));
+ //memcpy (timer_args, args, sizeof(*timer_args));
+ flexran_agent_timer_args_t *timer_args = (flexran_agent_timer_args_t *) args;
+
+ LOG_I(FLEXRAN_AGENT, "flexran_agent %d timeout\n", timer_args->mod_id);
+ //LOG_I(FLEXRAN_AGENT, "eNB action %d ENB flags %d \n", timer_args->cc_actions,timer_args->cc_report_flags);
+ //LOG_I(FLEXRAN_AGENT, "UE action %d UE flags %d \n", timer_args->ue_actions,timer_args->ue_report_flags);
+
+ return NULL;
+}
diff --git a/openair2/ENB_APP/flexran_agent.h b/openair2/ENB_APP/flexran_agent.h
new file mode 100644
index 0000000000..21ea21aafc
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent.h
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.0 (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.h
+ * \brief top level flexran agent
+ * \author Navid Nikaein and Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef FLEXRAN_AGENT_H_
+#define FLEXRAN_AGENT_H_
+
+#include "enb_config.h" // for enb properties
+#include "flexran_agent_common.h"
+
+
+/* Initiation and termination of the eNodeB agent */
+int flexran_agent_start(mid_t mod_id, const Enb_properties_array_t* enb_properties);
+int flexran_agent_stop(mid_t mod_id);
+
+/*
+ * enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller
+ * and can interact with other itti tasks
+*/
+void *flexran_agent_task(void *args);
+
+#endif
diff --git a/openair2/ENB_APP/flexran_agent_async.c b/openair2/ENB_APP/flexran_agent_async.c
new file mode 100644
index 0000000000..978b44929d
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_async.c
@@ -0,0 +1,99 @@
+/*
+ * 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.0 (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_async.c
+ * \brief channel implementation for async interface
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#include "flexran_agent_async.h"
+#include "flexran_agent_defs.h"
+
+#include "log.h"
+
+flexran_agent_async_channel_t * flexran_agent_async_channel_info(mid_t mod_id, char *dst_ip, uint16_t dst_port) {
+
+ flexran_agent_async_channel_t *channel;
+ channel = (flexran_agent_async_channel_t *) malloc(sizeof(flexran_agent_channel_t));
+
+ if (channel == NULL)
+ goto error;
+
+ channel->enb_id = mod_id;
+ /*Create a socket*/
+ channel->link = new_link_client(dst_ip, dst_port);
+ if (channel->link == NULL) goto error;
+
+ LOG_I(FLEXRAN_AGENT,"starting enb agent client for module id %d on ipv4 %s, port %d\n",
+ channel->enb_id,
+ dst_ip,
+ dst_port);
+
+ /*
+ * create a message queue
+ */
+ // Set size of queues statically for now
+ channel->send_queue = new_message_queue(500);
+ if (channel->send_queue == NULL) goto error;
+ channel->receive_queue = new_message_queue(500);
+ if (channel->receive_queue == NULL) goto error;
+
+ /*
+ * create a link manager
+ */
+ channel->manager = create_link_manager(channel->send_queue, channel->receive_queue, channel->link);
+ if (channel->manager == NULL) goto error;
+
+ return channel;
+
+ error:
+ LOG_I(FLEXRAN_AGENT,"there was an error\n");
+ return 1;
+}
+
+int flexran_agent_async_msg_send(void *data, int size, int priority, void *channel_info) {
+ flexran_agent_async_channel_t *channel;
+ channel = (flexran_agent_channel_t *)channel_info;
+
+ return message_put(channel->send_queue, data, size, priority);
+}
+
+int flexran_agent_async_msg_recv(void **data, int *size, int *priority, void *channel_info) {
+ flexran_agent_async_channel_t *channel;
+ channel = (flexran_agent_async_channel_t *)channel_info;
+
+ return message_get(channel->receive_queue, data, size, priority);
+}
+
+void flexran_agent_async_release(flexran_agent_channel_t *channel) {
+ flexran_agent_async_channel_t *channel_info;
+ channel_info = (flexran_agent_async_channel_t *) channel->channel_info;
+
+ destroy_link_manager(channel_info->manager);
+
+ destroy_message_queue(channel_info->send_queue);
+ destroy_message_queue(channel_info->receive_queue);
+
+ close_link(channel_info->link);
+ free(channel_info);
+}
diff --git a/openair2/ENB_APP/flexran_agent_async.h b/openair2/ENB_APP/flexran_agent_async.h
new file mode 100644
index 0000000000..b097b15c25
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_async.h
@@ -0,0 +1,55 @@
+/*
+ * 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.0 (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_async.h
+ * \brief channel implementation for async interface
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef FLEXRAN_AGENT_ASYNC_H_
+#define FLEXRAN_AGENT_ASYNC_H_
+
+#include "flexran_agent_net_comm.h"
+
+typedef struct {
+ mid_t enb_id;
+ socket_link_t *link;
+ message_queue_t *send_queue;
+ message_queue_t *receive_queue;
+ link_manager_t *manager;
+} flexran_agent_async_channel_t;
+
+/* Create a new channel for a given destination ip and destination port */
+flexran_agent_async_channel_t * flexran_agent_async_channel_info(mid_t mod_id, char *dst_ip, uint16_t dst_port);
+
+/* Send a message to the given channel */
+int flexran_agent_async_msg_send(void *data, int size, int priority, void *channel_info);
+
+/* Receive a message from a given channel */
+int flexran_agent_async_msg_recv(void **data, int *size, int *priority, void *channel_info);
+
+/* Release a channel */
+void flexran_agent_async_release(flexran_agent_channel_t *channel);
+
+
+#endif /*FLEXRAN_AGENT_ASYNC_H_*/
diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c
new file mode 100644
index 0000000000..2ccca6602b
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_common.c
@@ -0,0 +1,2279 @@
+/*
+ * 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.0 (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_common.c
+ * \brief common primitives for all agents
+ * \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+#include
+#include
+
+#include "flexran_agent_common.h"
+#include "flexran_agent_common_internal.h"
+#include "flexran_agent_extern.h"
+#include "PHY/extern.h"
+#include "log.h"
+
+#include "SCHED/defs.h"
+#include "RRC/LITE/extern.h"
+#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
+#include "rrc_eNB_UE_context.h"
+
+void * enb[NUM_MAX_ENB];
+void * enb_ue[NUM_MAX_ENB];
+void * enb_rrc[NUM_MAX_ENB];
+
+/*
+ * message primitives
+ */
+
+int flexran_agent_serialize_message(Protocol__FlexranMessage *msg, void **buf, int *size) {
+
+ *size = protocol__flexran_message__get_packed_size(msg);
+
+ *buf = malloc(*size);
+ if (buf == NULL)
+ goto error;
+
+ protocol__flexran_message__pack(msg, *buf);
+
+ return 0;
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "an error occured\n"); // change the com
+ return -1;
+}
+
+
+
+/* We assume that the buffer size is equal to the message size.
+ Should be chekced durint Tx/Rx */
+int flexran_agent_deserialize_message(void *data, int size, Protocol__FlexranMessage **msg) {
+ *msg = protocol__flexran_message__unpack(NULL, size, data);
+ if (*msg == NULL)
+ goto error;
+
+ return 0;
+
+ error:
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+
+int flexran_create_header(xid_t xid, Protocol__FlexType type, Protocol__FlexHeader **header) {
+
+ *header = malloc(sizeof(Protocol__FlexHeader));
+ if(*header == NULL)
+ goto error;
+
+ protocol__flex_header__init(*header);
+ (*header)->version = FLEXRAN_VERSION;
+ (*header)->has_version = 1;
+ // check if the type is set
+ (*header)->type = type;
+ (*header)->has_type = 1;
+ (*header)->xid = xid;
+ (*header)->has_xid = 1;
+ return 0;
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+int flexran_agent_hello(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+ Protocol__FlexHeader *header;
+ /*TODO: Need to set random xid or xid from received hello message*/
+ xid_t xid = 1;
+ if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_HELLO, &header) != 0)
+ goto error;
+
+ Protocol__FlexHello *hello_msg;
+ hello_msg = malloc(sizeof(Protocol__FlexHello));
+ if(hello_msg == NULL)
+ goto error;
+ protocol__flex_hello__init(hello_msg);
+ hello_msg->header = header;
+
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if(*msg == NULL)
+ goto error;
+
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_HELLO_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+ (*msg)->has_msg_dir = 1;
+ (*msg)->hello_msg = hello_msg;
+ return 0;
+
+ error:
+ if(header != NULL)
+ free(header);
+ if(hello_msg != NULL)
+ free(hello_msg);
+ if(*msg != NULL)
+ free(*msg);
+ LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+int flexran_agent_destroy_hello(Protocol__FlexranMessage *msg) {
+
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_HELLO_MSG)
+ goto error;
+
+ free(msg->hello_msg->header);
+ free(msg->hello_msg);
+ free(msg);
+ return 0;
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+int flexran_agent_echo_request(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg) {
+ Protocol__FlexHeader *header;
+ /*TODO: Need to set a random xid*/
+ xid_t xid = 1;
+ if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_ECHO_REQUEST, &header) != 0)
+ goto error;
+
+ Protocol__FlexEchoRequest *echo_request_msg;
+ echo_request_msg = malloc(sizeof(Protocol__FlexEchoRequest));
+ if(echo_request_msg == NULL)
+ goto error;
+ protocol__flex_echo_request__init(echo_request_msg);
+ echo_request_msg->header = header;
+
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if(*msg == NULL)
+ goto error;
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REQUEST_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+ (*msg)->echo_request_msg = echo_request_msg;
+ return 0;
+
+ error:
+ if(header != NULL)
+ free(header);
+ if(echo_request_msg != NULL)
+ free(echo_request_msg);
+ if(*msg != NULL)
+ free(*msg);
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+int flexran_agent_destroy_echo_request(Protocol__FlexranMessage *msg) {
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REQUEST_MSG)
+ goto error;
+
+ free(msg->echo_request_msg->header);
+ free(msg->echo_request_msg);
+ free(msg);
+ return 0;
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+
+int flexran_agent_echo_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+ xid_t xid;
+ Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+ Protocol__FlexEchoRequest *echo_req = input->echo_request_msg;
+ xid = (echo_req->header)->xid;
+
+ Protocol__FlexHeader *header;
+ if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_ECHO_REPLY, &header) != 0)
+ goto error;
+
+ Protocol__FlexEchoReply *echo_reply_msg;
+ echo_reply_msg = malloc(sizeof(Protocol__FlexEchoReply));
+ if(echo_reply_msg == NULL)
+ goto error;
+ protocol__flex_echo_reply__init(echo_reply_msg);
+ echo_reply_msg->header = header;
+
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if(*msg == NULL)
+ goto error;
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REPLY_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+ (*msg)->has_msg_dir = 1;
+ (*msg)->echo_reply_msg = echo_reply_msg;
+ return 0;
+
+ error:
+ if(header != NULL)
+ free(header);
+ if(echo_reply_msg != NULL)
+ free(echo_reply_msg);
+ if(*msg != NULL)
+ free(*msg);
+ LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+int flexran_agent_destroy_echo_reply(Protocol__FlexranMessage *msg) {
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REPLY_MSG)
+ goto error;
+
+ free(msg->echo_reply_msg->header);
+ free(msg->echo_reply_msg);
+ free(msg);
+ return 0;
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG)
+ goto error;
+ free(msg->enb_config_reply_msg->header);
+ int i, j;
+ Protocol__FlexEnbConfigReply *reply = msg->enb_config_reply_msg;
+
+ for(i = 0; i < reply->n_cell_config;i++) {
+ free(reply->cell_config[i]->mbsfn_subframe_config_rfoffset);
+ free(reply->cell_config[i]->mbsfn_subframe_config_rfperiod);
+ free(reply->cell_config[i]->mbsfn_subframe_config_sfalloc);
+ if (reply->cell_config[i]->si_config != NULL) {
+ for(j = 0; j < reply->cell_config[i]->si_config->n_si_message;j++){
+ free(reply->cell_config[i]->si_config->si_message[j]);
+ }
+ free(reply->cell_config[i]->si_config->si_message);
+ free(reply->cell_config[i]->si_config);
+ }
+ free(reply->cell_config[i]);
+ }
+ free(reply->cell_config);
+ free(reply);
+ free(msg);
+
+ return 0;
+ error:
+ //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_destroy_ue_config_reply(Protocol__FlexranMessage *msg) {
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG)
+ goto error;
+ free(msg->ue_config_reply_msg->header);
+ int i, j;
+ Protocol__FlexUeConfigReply *reply = msg->ue_config_reply_msg;
+
+ for(i = 0; i < reply->n_ue_config;i++){
+ free(reply->ue_config[i]->capabilities);
+ free(reply->ue_config[i]);
+ }
+ free(reply->ue_config);
+ free(reply);
+ free(msg);
+
+ return 0;
+ error:
+ //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_destroy_lc_config_reply(Protocol__FlexranMessage *msg) {
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REPLY_MSG)
+ goto error;
+
+ int i, j;
+ free(msg->lc_config_reply_msg->header);
+ for (i = 0; i < msg->lc_config_reply_msg->n_lc_ue_config; i++) {
+ for (j = 0; j < msg->lc_config_reply_msg->lc_ue_config[i]->n_lc_config; j++) {
+ free(msg->lc_config_reply_msg->lc_ue_config[i]->lc_config[j]);
+ }
+ free(msg->lc_config_reply_msg->lc_ue_config[i]->lc_config);
+ free(msg->lc_config_reply_msg->lc_ue_config[i]);
+ }
+ free(msg->lc_config_reply_msg->lc_ue_config);
+ free(msg->lc_config_reply_msg);
+ free(msg);
+ return 0;
+ error:
+ //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_destroy_ue_state_change(Protocol__FlexranMessage *msg) {
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG)
+ goto error;
+ free(msg->ue_state_change_msg->header);
+ //TODO: Free the contents of the UE config structure
+ free(msg->ue_state_change_msg);
+ free(msg);
+ return 0;
+
+ error:
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_destroy_enb_config_request(Protocol__FlexranMessage *msg) {
+ if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REQUEST_MSG)
+ goto error;
+ free(msg->enb_config_request_msg->header);
+ free(msg->enb_config_request_msg);
+ free(msg);
+ return 0;
+
+ error:
+ //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_destroy_ue_config_request(Protocol__FlexranMessage *msg) {
+ /* TODO: Deallocate memory for a dynamically allocated UE config message */
+ return 0;
+}
+
+int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg) {
+ /* TODO: Deallocate memory for a dynamically allocated LC config message */
+ return 0;
+}
+
+// call this function to start a nanosecond-resolution timer
+struct timespec timer_start(){
+ struct timespec start_time;
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
+ return start_time;
+}
+
+// call this function to end a timer, returning nanoseconds elapsed as a long
+long timer_end(struct timespec start_time){
+ struct timespec end_time;
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
+ long diffInNanos = end_time.tv_nsec - start_time.tv_nsec;
+ return diffInNanos;
+}
+
+int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+ Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+ Protocol__FlexControlDelegation *control_delegation_msg = input->control_delegation_msg;
+
+ uint32_t delegation_type = control_delegation_msg->delegation_type;
+
+ int i;
+
+ struct timespec vartime = timer_start();
+
+ //Write the payload lib into a file in the cache and load the lib
+ char lib_name[120];
+ char target[512];
+ snprintf(lib_name, sizeof(lib_name), "/%s.so", control_delegation_msg->name);
+ strcpy(target, local_cache);
+ strcat(target, lib_name);
+
+ FILE *f;
+ f = fopen(target, "wb");
+ fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f);
+ fclose(f);
+
+ long time_elapsed_nanos = timer_end(vartime);
+ *msg = NULL;
+ return 0;
+
+ error:
+ return -1;
+}
+
+int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg) {
+ /*TODO: Dealocate memory for a dynamically allocated control delegation message*/
+}
+
+int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+ Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+ Protocol__FlexAgentReconfiguration *agent_reconfiguration_msg = input->agent_reconfiguration_msg;
+
+ apply_reconfiguration_policy(mod_id, agent_reconfiguration_msg->policy, strlen(agent_reconfiguration_msg->policy));
+
+ *msg = NULL;
+ return 0;
+}
+
+int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg) {
+ /*TODO: Dealocate memory for a dynamically allocated agent reconfiguration message*/
+}
+
+
+/*
+ * get generic info from RAN
+ */
+
+void flexran_set_enb_vars(mid_t mod_id, ran_name_t ran){
+
+ switch (ran){
+ case RAN_LTE_OAI :
+ enb[mod_id] = (void *)&eNB_mac_inst[mod_id];
+ enb_ue[mod_id] = (void *)&eNB_mac_inst[mod_id].UE_list;
+ enb_rrc[mod_id] = (void *)&eNB_rrc_inst[mod_id];
+ break;
+ default :
+ goto error;
+ }
+
+ return;
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "unknown RAN name %d\n", ran);
+}
+
+int flexran_get_current_time_ms (mid_t mod_id, int subframe_flag){
+
+ if (subframe_flag == 1){
+ return ((eNB_MAC_INST *)enb[mod_id])->frame*10 + ((eNB_MAC_INST *)enb[mod_id])->subframe;
+ }else {
+ return ((eNB_MAC_INST *)enb[mod_id])->frame*10;
+ }
+
+}
+
+unsigned int flexran_get_current_frame (mid_t mod_id) {
+
+ #warning "SFN will not be in [0-1023] when oaisim is used"
+ return ((eNB_MAC_INST *)enb[mod_id])->frame;
+
+}
+
+unsigned int flexran_get_current_system_frame_num(mid_t mod_id) {
+ return (flexran_get_current_frame(mod_id) %1024);
+}
+
+unsigned int flexran_get_current_subframe (mid_t mod_id) {
+
+ return ((eNB_MAC_INST *)enb[mod_id])->subframe;
+
+}
+
+uint16_t flexran_get_sfn_sf (mid_t mod_id) {
+
+ frame_t frame;
+ sub_frame_t subframe;
+ uint16_t sfn_sf, frame_mask, sf_mask;
+
+ frame = (frame_t) flexran_get_current_system_frame_num(mod_id);
+ subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
+ frame_mask = ((1<<12) - 1);
+ sf_mask = ((1<<4) - 1);
+ sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4);
+
+ return sfn_sf;
+}
+
+uint16_t flexran_get_future_sfn_sf (mid_t mod_id, int ahead_of_time) {
+
+ frame_t frame;
+ sub_frame_t subframe;
+ uint16_t sfn_sf, frame_mask, sf_mask;
+
+ frame = (frame_t) flexran_get_current_system_frame_num(mod_id);
+ subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
+
+ subframe = ((subframe + ahead_of_time) % 10);
+
+ int full_frames_ahead = ((ahead_of_time / 10) % 10);
+
+ frame = frame + full_frames_ahead;
+
+ if (subframe < flexran_get_current_subframe(mod_id)) {
+ frame++;
+ }
+
+ frame_mask = ((1<<12) - 1);
+ sf_mask = ((1<<4) - 1);
+ sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4);
+
+ return sfn_sf;
+}
+
+int flexran_get_num_ues (mid_t mod_id){
+
+ return ((UE_list_t *)enb_ue[mod_id])->num_UEs;
+}
+
+int flexran_get_ue_crnti (mid_t mod_id, mid_t ue_id) {
+
+ return UE_RNTI(mod_id, ue_id);
+}
+
+int flexran_get_ue_bsr (mid_t mod_id, mid_t ue_id, lcid_t lcid) {
+
+ return ((UE_list_t *)enb_ue[mod_id])->UE_template[UE_PCCID(mod_id,ue_id)][ue_id].bsr_info[lcid];
+}
+
+int flexran_get_ue_phr (mid_t mod_id, mid_t ue_id) {
+
+ return ((UE_list_t *)enb_ue[mod_id])->UE_template[UE_PCCID(mod_id,ue_id)][ue_id].phr_info;
+}
+
+int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id) {
+ return ((UE_list_t *)enb_ue[mod_id])->eNB_UE_stats[UE_PCCID(mod_id,ue_id)][ue_id].dl_cqi;
+}
+
+int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
+ rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+ uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id);
+ mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id,frame,ENB_FLAG_YES,MBMS_FLAG_NO,channel_id,0);
+ return rlc_status.bytes_in_buffer;
+}
+
+int flexran_update_TA(mid_t mod_id, mid_t ue_id, int CC_id) {
+
+ UE_list_t *UE_list=&eNB_mac_inst[mod_id].UE_list;
+ UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id];
+ int rnti;
+
+ rnti = flexran_get_ue_crnti(mod_id, ue_id);
+ if (ue_sched_ctl->ta_timer == 0) {
+
+ // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...
+ LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
+ ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY
+ switch (PHY_vars_eNB_g[mod_id][CC_id]->frame_parms.N_RB_DL) {
+ case 6:
+ ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update;
+ break;
+
+ case 15:
+ ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2;
+ break;
+
+ case 25:
+ ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4;
+ break;
+
+ case 50:
+ ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8;
+ break;
+
+ case 75:
+ ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/12;
+ break;
+
+ case 100:
+ ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16;
+ break;
+ }
+ // clear the update in case PHY does not have a new measurement after timer expiry
+ eNB_UE_stats->timing_advance_update = 0;
+ }
+ else {
+ ue_sched_ctl->ta_timer--;
+ ue_sched_ctl->ta_update = 0; // don't trigger a timing advance command
+ }
+
+ return ue_sched_ctl->ta_update = 0;
+
+}
+
+int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id,int CC_id) {
+
+ UE_list_t *UE_list = &eNB_mac_inst[mod_id].UE_list;
+ UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id];
+
+ rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+ LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
+
+ if (eNB_UE_stats == NULL) {
+ return 0;
+ }
+
+ if (ue_sched_ctl->ta_update == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+
+int flexran_get_active_CC(mid_t mod_id, mid_t ue_id) {
+ return ((UE_list_t *)enb_ue[mod_id])->numactiveCCs[ue_id];
+}
+
+int flexran_get_current_RI(mid_t mod_id, mid_t ue_id, int CC_id) {
+ LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+
+ int pCCid = UE_PCCID(mod_id,ue_id);
+ rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+
+ eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
+
+ if (eNB_UE_stats == NULL) {
+ return 0;
+ }
+
+ return eNB_UE_stats[CC_id].rank;
+}
+
+int flexran_get_tpc(mid_t mod_id, mid_t ue_id) {
+ LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+ int32_t normalized_rx_power, target_rx_power;
+ int tpc = 1;
+
+ int pCCid = UE_PCCID(mod_id,ue_id);
+ rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+
+ eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, pCCid, rnti);
+
+ target_rx_power = mac_xface->get_target_pusch_rx_power(mod_id,pCCid);
+
+ if (eNB_UE_stats == NULL) {
+ normalized_rx_power = target_rx_power;
+ } else if (eNB_UE_stats->UL_rssi != NULL) {
+ normalized_rx_power = eNB_UE_stats->UL_rssi[0];
+ } else {
+ normalized_rx_power = target_rx_power;
+ }
+
+ if (normalized_rx_power>(target_rx_power+1)) {
+ tpc = 0; //-1
+ } else if (normalized_rx_power<(target_rx_power-1)) {
+ tpc = 2; //+1
+ } else {
+ tpc = 1; //0
+ }
+ return tpc;
+}
+
+int flexran_get_harq(const mid_t mod_id, const uint8_t CC_id, const mid_t ue_id, const int frame, const uint8_t subframe, int *id, int *round) { //flag_id_status = 0 then id, else status
+ /*TODO: Add int TB in function parameters to get the status of the second TB. This can be done to by editing in
+ * get_ue_active_harq_pid function in line 272 file: phy_procedures_lte_eNB.c to add
+ * DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch_eNB[(uint32_t)UE_id][1];*/
+
+ uint8_t harq_pid;
+ uint8_t harq_round;
+
+
+ uint16_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+
+ mac_xface->get_ue_active_harq_pid(mod_id,CC_id,rnti,frame,subframe,&harq_pid,&harq_round,openair_harq_DL);
+
+ *id = harq_pid;
+ *round = harq_round;
+ /* if (round > 0) { */
+ /* *status = 1; */
+ /* } else { */
+ /* *status = 0; */
+ /* } */
+
+ /* return 0; */
+ return round;
+}
+
+int flexran_get_p0_pucch_dbm(mid_t mod_id, mid_t ue_id, int CC_id) {
+ LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+ uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+
+ eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
+
+ if (eNB_UE_stats == NULL) {
+ return -1;
+ }
+
+ if(eNB_UE_stats->Po_PUCCH_update == 1) {
+ return eNB_UE_stats->Po_PUCCH_dBm;
+ }
+ else
+ return -1;
+}
+
+int flexran_get_p0_nominal_pucch(mid_t mod_id, int CC_id) {
+ int32_t pucch_rx_received = mac_xface->get_target_pucch_rx_power(mod_id, CC_id);
+ return pucch_rx_received;
+}
+
+int flexran_get_p0_pucch_status(mid_t mod_id, mid_t ue_id, int CC_id) {
+ LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+ uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+
+ eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
+ return eNB_UE_stats->Po_PUCCH_update;
+}
+
+int flexran_update_p0_pucch(mid_t mod_id, mid_t ue_id, int CC_id) {
+ LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+ uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+
+ eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
+ eNB_UE_stats->Po_PUCCH_update = 0;
+
+ return 0;
+}
+
+
+/*
+ * ************************************
+ * Get Messages for eNB Configuration Reply
+ * ************************************
+ */
+
+int flexran_get_hopping_offset(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->pusch_config_common.pusch_HoppingOffset;
+}
+
+int flexran_get_hopping_mode(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->pusch_config_common.hoppingMode;
+}
+
+int flexran_get_n_SB(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->pusch_config_common.n_SB;
+}
+
+int flexran_get_enable64QAM(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->pusch_config_common.enable64QAM;
+}
+
+int flexran_get_phich_duration(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->phich_config_common.phich_duration;
+}
+
+int flexran_get_phich_resource(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ if(frame_parms->phich_config_common.phich_resource == oneSixth)
+ return 0;
+ else if(frame_parms->phich_config_common.phich_resource == half)
+ return 1;
+ else if(frame_parms->phich_config_common.phich_resource == one)
+ return 2;
+ else if(frame_parms->phich_config_common.phich_resource == two)
+ return 3;
+
+ return -1;
+}
+
+int flexran_get_n1pucch_an(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->pucch_config_common.n1PUCCH_AN;
+}
+
+int flexran_get_nRB_CQI(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->pucch_config_common.nRB_CQI;
+}
+
+int flexran_get_deltaPUCCH_Shift(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->pucch_config_common.deltaPUCCH_Shift;
+}
+
+int flexran_get_prach_ConfigIndex(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex;
+}
+
+int flexran_get_prach_FreqOffset(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset;
+}
+
+int flexran_get_maxHARQ_Msg3Tx(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->maxHARQ_Msg3Tx;
+}
+
+int flexran_get_ul_cyclic_prefix_length(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->Ncp_UL;
+}
+
+int flexran_get_dl_cyclic_prefix_length(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->Ncp;
+}
+
+int flexran_get_cell_id(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->Nid_cell;
+}
+
+int flexran_get_srs_BandwidthConfig(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig;
+}
+
+int flexran_get_srs_SubframeConfig(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->soundingrs_ul_config_common.srs_SubframeConfig;
+}
+
+int flexran_get_srs_MaxUpPts(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->soundingrs_ul_config_common.srs_MaxUpPts;
+}
+
+int flexran_get_N_RB_DL(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->N_RB_DL;
+}
+
+int flexran_get_N_RB_UL(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->N_RB_UL;
+}
+
+int flexran_get_N_RBG(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->N_RBG;
+}
+
+int flexran_get_subframe_assignment(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->tdd_config;
+}
+
+int flexran_get_special_subframe_assignment(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ return frame_parms->tdd_config_S;
+}
+
+int flexran_get_ra_ResponseWindowSize(mid_t mod_id, int CC_id) {
+ Enb_properties_array_t *enb_properties;
+ enb_properties = enb_config_get();
+ return enb_properties->properties[mod_id]->rach_raResponseWindowSize[CC_id];
+}
+
+int flexran_get_mac_ContentionResolutionTimer(mid_t mod_id, int CC_id) {
+ Enb_properties_array_t *enb_properties;
+ enb_properties = enb_config_get();
+ return enb_properties->properties[mod_id]->rach_macContentionResolutionTimer[CC_id];
+}
+
+int flexran_get_duplex_mode(mid_t mod_id, int CC_id) {
+ LTE_DL_FRAME_PARMS *frame_parms;
+
+ frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+ if(frame_parms->frame_type == TDD)
+ return PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD;
+ else if (frame_parms->frame_type == FDD)
+ return PROTOCOL__FLEX_DUPLEX_MODE__FLDM_FDD;
+
+ return -1;
+}
+
+long flexran_get_si_window_length(mid_t mod_id, int CC_id) {
+ return ((eNB_RRC_INST *)enb_rrc[mod_id])->carrier[CC_id].sib1->si_WindowLength;
+}
+
+int flexran_get_sib1_length(mid_t mod_id, int CC_id) {
+ return ((eNB_RRC_INST *)enb_rrc[mod_id])->carrier[CC_id].sizeof_SIB1;
+}
+
+int flexran_get_num_pdcch_symb(mid_t mod_id, int CC_id) {
+ /* TODO: This should return the number of PDCCH symbols initially used by the cell CC_id */
+ return 0;
+ //(PHY_vars_UE_g[mod_id][CC_id]->lte_ue_pdcch_vars[mod_id]->num_pdcch_symbols);
+}
+
+
+
+/*
+ * ************************************
+ * Get Messages for UE Configuration Reply
+ * ************************************
+ */
+
+
+int flexran_get_time_alignment_timer(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.mac_MainConfig != NULL)
+ return ue_context_p->ue_context.mac_MainConfig->timeAlignmentTimerDedicated;
+ }
+ else
+ return -1;
+}
+
+int flexran_get_meas_gap_config(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.measGapConfig != NULL) {
+ if(ue_context_p->ue_context.measGapConfig->present == MeasGapConfig_PR_setup) {
+ if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp0) {
+ return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_GP1;
+ } else if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp1) {
+ return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_GP2;
+ } else {
+ return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+
+int flexran_get_meas_gap_config_offset(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.measGapConfig != NULL){
+ if(ue_context_p->ue_context.measGapConfig->present == MeasGapConfig_PR_setup) {
+ if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp0) {
+ return ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.choice.gp0;
+ } else if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp1) {
+ return ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.choice.gp0;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+int flexran_get_ue_aggregated_max_bitrate_dl (mid_t mod_id, mid_t ue_id) {
+ return ((UE_list_t *)enb_ue[mod_id])->UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL;
+}
+
+int flexran_get_ue_aggregated_max_bitrate_ul (mid_t mod_id, mid_t ue_id) {
+ return ((UE_list_t *)enb_ue[mod_id])->UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateUL;
+}
+
+int flexran_get_half_duplex(mid_t ue_id) {
+ // TODO
+ //int halfduplex = 0;
+ //int bands_to_scan = ((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;
+ //for (int i =0; i < bands_to_scan; i++){
+ //if(((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->halfDuplex > 0)
+ // halfduplex = 1;
+ //}
+ //return halfduplex;
+}
+
+int flexran_get_intra_sf_hopping(mid_t ue_id) {
+ //TODO:Get proper value
+ //temp = (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->featureGroupIndicators->buf);
+ //return (0 & ( 1 << (31)));
+}
+
+int flexran_get_type2_sb_1(mid_t ue_id) {
+ //TODO:Get proper value
+ //uint8_t temp = 0;
+ //temp = (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->featureGroupIndicators->buf);
+ //return (temp & ( 1 << (11)));
+}
+
+int flexran_get_ue_category(mid_t ue_id) {
+ //TODO:Get proper value
+ //return (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->ue_Category);
+}
+
+int flexran_get_res_alloc_type1(mid_t ue_id) {
+ //TODO:Get proper value
+ //uint8_t temp = 0;
+ //temp = (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->featureGroupIndicators->buf);
+ //return (temp & ( 1 << (30)));
+}
+
+int flexran_get_ue_transmission_mode(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+ return ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode;
+ }
+ }
+ else
+ return -1;
+}
+
+int flexran_get_tti_bundling(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.mac_MainConfig != NULL){
+ return ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config->ttiBundling;
+ }
+ }
+ else
+ return -1;
+}
+
+int flexran_get_maxHARQ_TX(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.mac_MainConfig != NULL){
+ return *ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config->maxHARQ_Tx;
+ }
+ }
+ return -1;
+}
+
+int flexran_get_beta_offset_ack_index(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+ return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_ACK_Index;
+ }
+ }
+ else
+ return -1;
+}
+
+int flexran_get_beta_offset_ri_index(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+ return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index;
+ }
+ }
+ else
+ return -1;
+}
+
+int flexran_get_beta_offset_cqi_index(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+ return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index;
+ }
+ }
+ else
+ return -1;
+}
+
+int flexran_get_simultaneous_ack_nack_cqi(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+ if (ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic != NULL) {
+ return ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.simultaneousAckNackAndCQI;
+ }
+ }
+ }
+ return -1;
+}
+
+int flexran_get_ack_nack_simultaneous_trans(mid_t mod_id,mid_t ue_id) {
+ return (&eNB_rrc_inst[mod_id])->carrier[0].sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission;
+}
+
+int flexran_get_aperiodic_cqi_rep_mode(mid_t mod_id,mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+ return *ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic;
+ }
+ }
+ return -1;
+}
+
+int flexran_get_tdd_ack_nack_feedback(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+ return ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode;
+ }
+ }
+ else
+ return -1;
+}
+
+int flexran_get_ack_nack_repetition_factor(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+ return ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->ackNackRepetition.choice.setup.repetitionFactor;
+ }
+ }
+ else
+ return -1;
+}
+
+int flexran_get_extended_bsr_size(mid_t mod_id, mid_t ue_id) {
+ //TODO: need to double check
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.mac_MainConfig != NULL){
+ if(ue_context_p->ue_context.mac_MainConfig->ext2 != NULL){
+ long val = (*(ue_context_p->ue_context.mac_MainConfig->ext2->mac_MainConfig_v1020->extendedBSR_Sizes_r10));
+ if (val > 0) {
+ return 1;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+int flexran_get_ue_transmission_antenna(mid_t mod_id, mid_t ue_id) {
+ struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+ uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+ ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+
+ if(ue_context_p != NULL) {
+ if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+ if(ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.choice.setup == AntennaInfoDedicated__ue_TransmitAntennaSelection__setup_closedLoop)
+ return 2;
+ else if(ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.choice.setup == AntennaInfoDedicated__ue_TransmitAntennaSelection__setup_openLoop)
+ return 1;
+ else
+ return 0;
+ }
+ }
+ else
+ return -1;
+}
+
+int flexran_get_lcg(mid_t ue_id, mid_t lc_id) {
+ if (UE_mac_inst == NULL) {
+ return -1;
+ }
+ if(UE_mac_inst[ue_id].logicalChannelConfig[lc_id] != NULL) {
+ return *UE_mac_inst[ue_id].logicalChannelConfig[lc_id]->ul_SpecificParameters->logicalChannelGroup;
+ } else {
+ return -1;
+ }
+}
+
+int flexran_get_direction(mid_t ue_id, mid_t lc_id) {
+ /*TODO: fill with the value for the rest of LCID*/
+ if(lc_id == DCCH | lc_id == DCCH1)
+ return 2;
+ else if(lc_id == DTCH)
+ return 1;
+}
+
+int flexran_agent_ue_state_change(mid_t mod_id, uint32_t rnti, uint8_t state_change) {
+ int size;
+ Protocol__FlexranMessage *msg;
+ Protocol__FlexHeader *header;
+ void *data;
+ int priority;
+ err_code_t err_code;
+
+ int xid = 0;
+
+ if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_UE_STATE_CHANGE, &header) != 0)
+ goto error;
+
+ Protocol__FlexUeStateChange *ue_state_change_msg;
+ ue_state_change_msg = malloc(sizeof(Protocol__FlexUeStateChange));
+ if(ue_state_change_msg == NULL) {
+ goto error;
+ }
+ protocol__flex_ue_state_change__init(ue_state_change_msg);
+ ue_state_change_msg->has_type = 1;
+ ue_state_change_msg->type = state_change;
+
+ Protocol__FlexUeConfig *config;
+ config = malloc(sizeof(Protocol__FlexUeConfig));
+ if (config == NULL) {
+ goto error;
+ }
+ protocol__flex_ue_config__init(config);
+ if (state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED) {
+ // Simply set the rnti of the UE
+ 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
+
+ //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;
+ }
+
+ config->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id,i);
+ config->has_ue_aggregated_max_bitrate_ul = 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;
+
+ //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);
+ }
+
+ 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_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_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_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_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_ack_nack_simultaneous_trans(mod_id,i) != -1) {
+ config->has_ack_nack_simultaneous_trans = 1;
+ config->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(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_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_tdd_ack_nack_feedback(mod_id, i) != -1) {
+ config->has_tdd_ack_nack_feedback = 1;
+ config->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback(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_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
+ }
+
+ ue_state_change_msg->config = config;
+ msg = malloc(sizeof(Protocol__FlexranMessage));
+ if (msg == NULL) {
+ goto error;
+ }
+ protocol__flexran_message__init(msg);
+ msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG;
+ msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+ msg->ue_state_change_msg = ue_state_change_msg;
+
+ data = flexran_agent_pack_message(msg, &size);
+ /*Send sr info using the MAC channel of the eNB*/
+ if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_DEFAULT, data, size, priority)) {
+ err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+ goto error;
+ }
+
+ LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+ return;
+ error:
+ LOG_D(FLEXRAN_AGENT, "Could not send UE state message\n");
+}
+
+
+
+int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+ xid_t xid;
+ Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+ Protocol__FlexLcConfigRequest *lc_config_request_msg = input->lc_config_request_msg;
+ xid = (lc_config_request_msg->header)->xid;
+
+ int i, j;
+ Protocol__FlexHeader *header;
+ if(flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_GET_LC_CONFIG_REPLY, &header) != 0)
+ goto error;
+
+ Protocol__FlexLcConfigReply *lc_config_reply_msg;
+ lc_config_reply_msg = malloc(sizeof(Protocol__FlexLcConfigReply));
+ if(lc_config_reply_msg == NULL)
+ goto error;
+ protocol__flex_lc_config_reply__init(lc_config_reply_msg);
+ lc_config_reply_msg->header = header;
+
+ lc_config_reply_msg->n_lc_ue_config = flexran_get_num_ues(mod_id);
+
+ Protocol__FlexLcUeConfig **lc_ue_config;
+ if (lc_config_reply_msg->n_lc_ue_config > 0) {
+ lc_ue_config = malloc(sizeof(Protocol__FlexLcUeConfig *) * lc_config_reply_msg->n_lc_ue_config);
+ if (lc_ue_config == NULL) {
+ goto error;
+ }
+ // Fill the config for each UE
+ for (i = 0; i < lc_config_reply_msg->n_lc_ue_config; i++) {
+ lc_ue_config[i] = malloc(sizeof(Protocol__FlexLcUeConfig));
+ protocol__flex_lc_ue_config__init(lc_ue_config[i]);
+
+ lc_ue_config[i]->has_rnti = 1;
+ lc_ue_config[i]->rnti = flexran_get_ue_crnti(mod_id,i);
+
+ //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));
+ if (status < RRC_CONNECTED) {
+ lc_ue_config[i]->n_lc_config = 0;
+ } else if (status == RRC_CONNECTED) {
+ lc_ue_config[i]->n_lc_config = 1;
+ } else {
+ lc_ue_config[i]->n_lc_config = 3;
+ }
+
+ Protocol__FlexLcConfig **lc_config;
+ if (lc_ue_config[i]->n_lc_config > 0) {
+ lc_config = malloc(sizeof(Protocol__FlexLcConfig *) * lc_ue_config[i]->n_lc_config);
+ if (lc_config == NULL) {
+ goto error;
+ }
+ for (j = 0; j < lc_ue_config[i]->n_lc_config; j++) {
+ lc_config[j] = malloc(sizeof(Protocol__FlexLcConfig));
+ protocol__flex_lc_config__init(lc_config[j]);
+
+ lc_config[j]->has_lcid = 1;
+ lc_config[j]->lcid = j+1;
+
+ int lcg = flexran_get_lcg(i, j+1);
+ if (lcg >= 0 && lcg <= 3) {
+ lc_config[j]->has_lcg = 1;
+ lc_config[j]->lcg = flexran_get_lcg(i,j+1);
+ }
+
+ lc_config[j]->has_direction = 1;
+ lc_config[j]->direction = flexran_get_direction(i,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;
+
+ //TODO: Set the QCI defined in TS 23.203, coded as defined in TS 36.413
+ // One less than the actual QCI value. Needs to be generalized
+ lc_config[j]->has_qci = 1;
+ lc_config[j]->qci = 1;
+ if (lc_config[j]->direction == PROTOCOL__FLEX_QOS_BEARER_TYPE__FLQBT_GBR) {
+ //TODO: Set the max bitrate (UL)
+ lc_config[j]->has_e_rab_max_bitrate_ul = 0;
+ lc_config[j]->e_rab_max_bitrate_ul = 0;
+ //TODO: Set the max bitrate (DL)
+ lc_config[j]->has_e_rab_max_bitrate_dl = 0;
+ lc_config[j]->e_rab_max_bitrate_dl = 0;
+ //TODO: Set the guaranteed bitrate (UL)
+ lc_config[j]->has_e_rab_guaranteed_bitrate_ul = 0;
+ lc_config[j]->e_rab_guaranteed_bitrate_ul = 0;
+ //TODO: Set the guaranteed bitrate (DL)
+ lc_config[j]->has_e_rab_guaranteed_bitrate_dl = 0;
+ lc_config[j]->e_rab_guaranteed_bitrate_dl = 0;
+ }
+ }
+ lc_ue_config[i]->lc_config = lc_config;
+ }
+ } // end for UE
+ lc_config_reply_msg->lc_ue_config = lc_ue_config;
+ } // lc_config_reply_msg->n_lc_ue_config > 0
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if (*msg == NULL)
+ goto error;
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REPLY_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+ (*msg)->lc_config_reply_msg = lc_config_reply_msg;
+
+ return 0;
+
+ error:
+ // TODO: Need to make proper error handling
+ if (header != NULL)
+ free(header);
+ if (lc_config_reply_msg != NULL)
+ free(lc_config_reply_msg);
+ if(*msg != NULL)
+ free(*msg);
+ //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+/*
+ * ************************************
+ * UE Configuration Reply
+ * ************************************
+ */
+
+int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+ xid_t xid;
+ Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+ Protocol__FlexUeConfigRequest *ue_config_request_msg = input->ue_config_request_msg;
+ xid = (ue_config_request_msg->header)->xid;
+
+ int i;
+
+ Protocol__FlexHeader *header;
+ if(flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_GET_UE_CONFIG_REPLY, &header) != 0)
+ goto error;
+
+ Protocol__FlexUeConfigReply *ue_config_reply_msg;
+ ue_config_reply_msg = malloc(sizeof(Protocol__FlexUeConfigReply));
+ if(ue_config_reply_msg == NULL)
+ goto error;
+ protocol__flex_ue_config_reply__init(ue_config_reply_msg);
+ ue_config_reply_msg->header = header;
+
+ ue_config_reply_msg->n_ue_config = flexran_get_num_ues(mod_id);
+
+ Protocol__FlexUeConfig **ue_config;
+ if (ue_config_reply_msg->n_ue_config > 0) {
+ ue_config = malloc(sizeof(Protocol__FlexUeConfig *) * ue_config_reply_msg->n_ue_config);
+ if (ue_config == NULL) {
+ goto error;
+ }
+ for (i = 0; i < ue_config_reply_msg->n_ue_config; i++) {
+ 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_config[i]->has_rnti = 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_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 (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]->has_meas_gap_config_sf_offset = 1;
+ }
+ //TODO: Set the SPS configuration (Optional)
+ //Not supported for noe, so we do not set it
+
+ //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) {
+ ue_config[i]->transmission_mode = flexran_get_ue_transmission_mode(mod_id,i);
+ 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]->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]->has_ue_aggregated_max_bitrate_dl = 1;
+
+ Protocol__FlexUeCapabilities *capabilities;
+ capabilities = malloc(sizeof(Protocol__FlexUeCapabilities));
+ protocol__flex_ue_capabilities__init(capabilities);
+ //TODO: Set half duplex (FDD operation)
+ capabilities->has_half_duplex = 0;
+ capabilities->half_duplex = 0;//flexran_get_half_duplex(i);
+ //TODO: Set intra-frame hopping flag
+ capabilities->has_intra_sf_hopping = 0;
+ capabilities->intra_sf_hopping = 1;//flexran_get_intra_sf_hopping(i);
+ //TODO: Set support for type 2 hopping with n_sb > 1
+ capabilities->has_type2_sb_1 = 0;
+ capabilities->type2_sb_1 = 1;//flexran_get_type2_sb_1(i);
+ //TODO: Set ue category
+ capabilities->has_ue_category = 0;
+ capabilities->ue_category = 1;//flexran_get_ue_category(i);
+ //TODO: Set UE support for resource allocation type 1
+ capabilities->has_res_alloc_type1 = 0;
+ capabilities->res_alloc_type1 = 1;//flexran_get_res_alloc_type1(i);
+ //Set the capabilites to the message
+ ue_config[i]->capabilities = capabilities;
+
+ if (flexran_get_ue_transmission_antenna(mod_id,i) != -1) {
+ ue_config[i]->has_ue_transmission_antenna = 1;
+ ue_config[i]->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id,i);
+ }
+
+ if (flexran_get_tti_bundling(mod_id,i) != -1) {
+ ue_config[i]->has_tti_bundling = 1;
+ ue_config[i]->tti_bundling = flexran_get_tti_bundling(mod_id,i);
+ }
+
+ if (flexran_get_maxHARQ_TX(mod_id,i) != -1) {
+ ue_config[i]->has_max_harq_tx = 1;
+ ue_config[i]->max_harq_tx = flexran_get_maxHARQ_TX(mod_id,i);
+ }
+
+ 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_ri_index(mod_id,i) != -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);
+ }
+
+ if (flexran_get_beta_offset_cqi_index(mod_id,i) != -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);
+ }
+
+ if (flexran_get_ack_nack_simultaneous_trans(mod_id,i) != -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);
+ }
+
+ if (flexran_get_simultaneous_ack_nack_cqi(mod_id,i) != -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);
+ }
+
+ if (flexran_get_aperiodic_cqi_rep_mode(mod_id,i) != -1) {
+ ue_config[i]->has_aperiodic_cqi_rep_mode = 1;
+ int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id,i);
+ if (mode > 4) {
+ ue_config[i]->aperiodic_cqi_rep_mode = PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
+ } else {
+ ue_config[i]->aperiodic_cqi_rep_mode = mode;
+ }
+ }
+
+ if (flexran_get_tdd_ack_nack_feedback(mod_id, i) != -1) {
+ ue_config[i]->has_tdd_ack_nack_feedback = 1;
+ ue_config[i]->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback(mod_id,i);
+ }
+
+ if(flexran_get_ack_nack_repetition_factor(mod_id, i) != -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);
+ }
+
+ if (flexran_get_extended_bsr_size(mod_id, i) != -1) {
+ ue_config[i]->has_extended_bsr_size = 1;
+ ue_config[i]->extended_bsr_size = flexran_get_extended_bsr_size(mod_id,i);
+ }
+ //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);
+ if(ue_config[i]->has_ca_support){
+ //TODO: Set cross carrier scheduling support (boolean)
+ ue_config[i]->has_cross_carrier_sched_support = 0;
+ ue_config[i]->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
+ ue_config[i]->has_scell_deactivation_timer = 0;
+ ue_config[i]->scell_deactivation_timer = 0;
+ }
+ }
+ ue_config_reply_msg->ue_config = ue_config;
+ }
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if (*msg == NULL)
+ goto error;
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+ (*msg)->ue_config_reply_msg = ue_config_reply_msg;
+ return 0;
+
+ error:
+ // TODO: Need to make proper error handling
+ if (header != NULL)
+ free(header);
+ if (ue_config_reply_msg != NULL)
+ free(ue_config_reply_msg);
+ if(*msg != NULL)
+ free(*msg);
+ //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+/*
+ * ************************************
+ * eNB Configuration Request and Reply
+ * ************************************
+ */
+
+int flexran_agent_enb_config_request(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg) {
+
+ Protocol__FlexHeader *header;
+ xid_t xid = 1;
+ if(flexran_create_header(xid,PROTOCOL__FLEX_TYPE__FLPT_GET_ENB_CONFIG_REQUEST, &header) != 0)
+ goto error;
+
+ Protocol__FlexEnbConfigRequest *enb_config_request_msg;
+ enb_config_request_msg = malloc(sizeof(Protocol__FlexEnbConfigRequest));
+
+ if(enb_config_request_msg == NULL)
+ goto error;
+
+ protocol__flex_enb_config_request__init(enb_config_request_msg);
+ enb_config_request_msg->header = header;
+
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if(*msg == NULL)
+ goto error;
+
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REQUEST_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+ (*msg)->enb_config_request_msg = enb_config_request_msg;
+ return 0;
+
+ error:
+ // TODO: Need to make proper error handling
+ if (header != NULL)
+ free(header);
+ if (enb_config_request_msg != NULL)
+ free(enb_config_request_msg);
+ if(*msg != NULL)
+ free(*msg);
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+ xid_t xid;
+ Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+ Protocol__FlexEnbConfigRequest *enb_config_req_msg = input->enb_config_request_msg;
+ xid = (enb_config_req_msg->header)->xid;
+
+ int i, j, k;
+ int cc_id = 0;
+ int enb_id = mod_id;
+
+ Protocol__FlexHeader *header;
+ if(flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_GET_ENB_CONFIG_REPLY, &header) != 0)
+ goto error;
+
+ Protocol__FlexEnbConfigReply *enb_config_reply_msg;
+ enb_config_reply_msg = malloc(sizeof(Protocol__FlexEnbConfigReply));
+ if(enb_config_reply_msg == NULL)
+ goto error;
+ protocol__flex_enb_config_reply__init(enb_config_reply_msg);
+ enb_config_reply_msg->header = header;
+
+ enb_config_reply_msg->enb_id = mod_id;
+
+
+ enb_config_reply_msg->n_cell_config = MAX_NUM_CCs;
+
+ Protocol__FlexCellConfig **cell_conf;
+ if(enb_config_reply_msg->n_cell_config > 0){
+ cell_conf = malloc(sizeof(Protocol__FlexCellConfig *) * enb_config_reply_msg->n_cell_config);
+ if(cell_conf == NULL)
+ goto error;
+ for(i = 0; i < enb_config_reply_msg->n_cell_config; i++){
+ 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(enb_id,i);
+
+ cell_conf[i]->cell_id = i;
+ cell_conf[i]->has_cell_id = 1;
+
+ cell_conf[i]->pusch_hopping_offset = flexran_get_hopping_offset(enb_id,i);
+ cell_conf[i]->has_pusch_hopping_offset = 1;
+
+ if (flexran_get_hopping_mode(enb_id,i) == 0) {
+ cell_conf[i]->hopping_mode = PROTOCOL__FLEX_HOPPING_MODE__FLHM_INTER;
+ } else if(flexran_get_hopping_mode(enb_id,i) == 1) {
+ cell_conf[i]->hopping_mode = PROTOCOL__FLEX_HOPPING_MODE__FLHM_INTERINTRA;
+ }
+ cell_conf[i]->has_hopping_mode = 1;
+
+ cell_conf[i]->n_sb = flexran_get_n_SB(enb_id,i);
+ cell_conf[i]->has_n_sb = 1;
+
+ if (flexran_get_phich_resource(enb_id,i) == 0) {
+ cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_ONE_SIXTH; //0
+ } else if (flexran_get_phich_resource(enb_id,i) == 1) {
+ cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_HALF; //1
+ } else if (flexran_get_phich_resource(enb_id,i) == 2) {
+ cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_ONE; // 2
+ } else if (flexran_get_phich_resource(enb_id,i) == 3) {
+ cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_TWO;//3
+ }
+ cell_conf[i]->has_phich_resource = 1;
+
+ if (flexran_get_phich_duration(enb_id,i) == 0) {
+ cell_conf[i]->phich_duration = PROTOCOL__FLEX_PHICH_DURATION__FLPD_NORMAL;
+ } else if(flexran_get_phich_duration(enb_id,i) == 1) {
+ cell_conf[i]->phich_duration = PROTOCOL__FLEX_PHICH_DURATION__FLPD_EXTENDED;
+ }
+ cell_conf[i]->has_phich_duration = 1;
+ //TODO: Fill in with actual value, See TS 36.211, section 6.9
+ cell_conf[i]->init_nr_pdcch_ofdm_sym = flexran_get_num_pdcch_symb(enb_id,i);
+ cell_conf[i]->has_init_nr_pdcch_ofdm_sym = 0;
+ //TODO: Fill in with actual value
+ /* Protocol__FlexSiConfig *si_config; */
+ /* si_config = malloc(sizeof(Protocol__FlexSiConfig)); */
+ /* if(si_config == NULL) */
+ /* goto error; */
+ /* protocol__flex_si_config__init(si_config); */
+ /* //TODO: Fill in with actual value, Frame number to apply the SI configuration */
+ /* si_config->sfn = 1; */
+ /* si_config->has_sfn = 1; */
+ /* //TODO: Fill in with actual value, the length of SIB1 in bytes */
+ /* si_config->sib1_length = get_sib1_length(enb_id,i); */
+ /* si_config->has_sib1_length = 1; */
+ /* //TODO: Fill in with actual value, Scheduling window for all SIs in SF */
+ /* si_config->si_window_length = (uint32_t) get_si_window_length(enb_id,i); */
+ /* si_config->has_si_window_length = 1; */
+ /* //TODO: Fill in with actual value, the number of SI messages */
+ /* si_config->n_si_message=1; */
+ /* Protocol__FlexSiMessage **si_message; */
+ /* si_message = malloc(sizeof(Protocol__FlexSiMessage *) * si_config->n_si_message); */
+ /* if(si_message == NULL) */
+ /* goto error; */
+ /* for(j = 0; j < si_config->n_si_message; j++){ */
+ /* si_message[j] = malloc(sizeof(Protocol__FlexSiMessage)); */
+ /* if(si_message[j] == NULL) */
+ /* goto error; */
+ /* protocol__flex_si_message__init(si_message[j]); */
+ /* //TODO: Fill in with actual value, Periodicity of SI msg in radio frames */
+ /* si_message[j]->periodicity = 1; //SIPeriod */
+ /* si_message[j]->has_periodicity = 1; */
+ /* //TODO: Fill in with actual value, rhe length of the SI message in bytes */
+ /* si_message[j]->length = 10; */
+ /* si_message[j]->has_length = 1; */
+ /* } */
+ /* if(si_config->n_si_message > 0){ */
+ /* si_config->si_message = si_message; */
+ /* } */
+ /* cell_conf[i]->si_config = si_config; */
+
+ cell_conf[i]->dl_bandwidth = flexran_get_N_RB_DL(enb_id,i);
+ cell_conf[i]->has_dl_bandwidth = 1;
+
+ cell_conf[i]->ul_bandwidth = flexran_get_N_RB_UL(enb_id,i);
+ cell_conf[i]->has_ul_bandwidth = 1;
+
+ if (flexran_get_ul_cyclic_prefix_length(enb_id, i) == 0) {
+ cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_UL_CYCLIC_PREFIX_LENGTH__FLUCPL_NORMAL;
+ } else if(flexran_get_ul_cyclic_prefix_length(enb_id, i) == 1) {
+ cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_UL_CYCLIC_PREFIX_LENGTH__FLUCPL_EXTENDED;
+ }
+ cell_conf[i]->has_ul_cyclic_prefix_length = 1;
+
+ if (flexran_get_ul_cyclic_prefix_length(enb_id,i) == 0) {
+ cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_DL_CYCLIC_PREFIX_LENGTH__FLDCPL_NORMAL;
+ } else if (flexran_get_ul_cyclic_prefix_length(enb_id,i) == 1) {
+ cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_DL_CYCLIC_PREFIX_LENGTH__FLDCPL_EXTENDED;
+ }
+
+ cell_conf[i]->has_dl_cyclic_prefix_length = 1;
+ //TODO: Fill in with actual value, number of cell specific antenna ports. Currently single port support
+ cell_conf[i]->antenna_ports_count = 1;
+ cell_conf[i]->has_antenna_ports_count = 1;
+
+ if (flexran_get_duplex_mode(enb_id,i) == 1) {
+ cell_conf[i]->duplex_mode = PROTOCOL__FLEX_DUPLEX_MODE__FLDM_FDD;
+ } else if(flexran_get_duplex_mode(enb_id,i) == 0) {
+ cell_conf[i]->duplex_mode = PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD;
+ }
+ cell_conf[i]->has_duplex_mode = 1;
+ //TODO: Fill in with actual value, DL/UL subframe assignment. TDD only
+ cell_conf[i]->subframe_assignment = flexran_get_subframe_assignment(enb_id, i);
+ cell_conf[i]->has_subframe_assignment = 0;
+ //TODO: Fill in with actual value, TDD only. See TS 36.211, table 4.2.1
+ cell_conf[i]->special_subframe_patterns = flexran_get_special_subframe_assignment(enb_id,i);
+ cell_conf[i]->has_special_subframe_patterns = 0;
+ //TODO: Fill in with actual value, The MBSFN radio frame period
+ cell_conf[i]->n_mbsfn_subframe_config_rfperiod = 0;
+ uint32_t *elem_rfperiod;
+ elem_rfperiod = (uint32_t *) malloc(sizeof(uint32_t) *cell_conf[i]->n_mbsfn_subframe_config_rfperiod);
+ if(elem_rfperiod == NULL)
+ goto error;
+ for(j = 0; j < cell_conf[i]->n_mbsfn_subframe_config_rfperiod; j++){
+ elem_rfperiod[j] = 1;
+ }
+ cell_conf[i]->mbsfn_subframe_config_rfperiod = elem_rfperiod;
+
+ //TODO: Fill in with actual value, The MBSFN radio frame offset
+ cell_conf[i]->n_mbsfn_subframe_config_rfoffset = 0;
+ uint32_t *elem_rfoffset;
+ elem_rfoffset = (uint32_t *) malloc(sizeof(uint32_t) *cell_conf[i]->n_mbsfn_subframe_config_rfoffset);
+ if(elem_rfoffset == NULL)
+ goto error;
+ for(j = 0; j < cell_conf[i]->n_mbsfn_subframe_config_rfoffset; j++){
+ elem_rfoffset[j] = 1;
+ }
+ cell_conf[i]->mbsfn_subframe_config_rfoffset = elem_rfoffset;
+
+ //TODO: Fill in with actual value, Bitmap indicating the MBSFN subframes
+ cell_conf[i]->n_mbsfn_subframe_config_sfalloc = 0;
+ uint32_t *elem_sfalloc;
+ elem_sfalloc = (uint32_t *) malloc(sizeof(uint32_t) *cell_conf[i]->n_mbsfn_subframe_config_sfalloc);
+ if(elem_sfalloc == NULL)
+ goto error;
+ for(j = 0; j < cell_conf[i]->n_mbsfn_subframe_config_sfalloc; j++){
+ elem_sfalloc[j] = 1;
+ }
+ cell_conf[i]->mbsfn_subframe_config_sfalloc = elem_sfalloc;
+
+ cell_conf[i]->prach_config_index = flexran_get_prach_ConfigIndex(enb_id,i);
+ cell_conf[i]->has_prach_config_index = 1;
+
+ cell_conf[i]->prach_freq_offset = flexran_get_prach_FreqOffset(enb_id,i);
+ cell_conf[i]->has_prach_freq_offset = 1;
+
+ cell_conf[i]->ra_response_window_size = flexran_get_ra_ResponseWindowSize(enb_id,i);
+ cell_conf[i]->has_ra_response_window_size = 1;
+
+ cell_conf[i]->mac_contention_resolution_timer = flexran_get_mac_ContentionResolutionTimer(enb_id,i);
+ cell_conf[i]->has_mac_contention_resolution_timer = 1;
+
+ cell_conf[i]->max_harq_msg3tx = flexran_get_maxHARQ_Msg3Tx(enb_id,i);
+ cell_conf[i]->has_max_harq_msg3tx = 1;
+
+ cell_conf[i]->n1pucch_an = flexran_get_n1pucch_an(enb_id,i);
+ cell_conf[i]->has_n1pucch_an = 1;
+
+ cell_conf[i]->deltapucch_shift = flexran_get_deltaPUCCH_Shift(enb_id,i);
+ cell_conf[i]->has_deltapucch_shift = 1;
+
+ cell_conf[i]->nrb_cqi = flexran_get_nRB_CQI(enb_id,i);
+ cell_conf[i]->has_nrb_cqi = 1;
+
+ cell_conf[i]->srs_subframe_config = flexran_get_srs_SubframeConfig(enb_id,i);
+ cell_conf[i]->has_srs_subframe_config = 1;
+
+ cell_conf[i]->srs_bw_config = flexran_get_srs_BandwidthConfig(enb_id,i);
+ cell_conf[i]->has_srs_bw_config = 1;
+
+ cell_conf[i]->srs_mac_up_pts = flexran_get_srs_MaxUpPts(enb_id,i);
+ cell_conf[i]->has_srs_mac_up_pts = 1;
+
+ if (flexran_get_enable64QAM(enb_id,i) == 0) {
+ cell_conf[i]->enable_64qam = PROTOCOL__FLEX_QAM__FLEQ_MOD_16QAM;
+ } else if(flexran_get_enable64QAM(enb_id,i) == 1) {
+ cell_conf[i]->enable_64qam = PROTOCOL__FLEX_QAM__FLEQ_MOD_64QAM;
+ }
+ cell_conf[i]->has_enable_64qam = 1;
+
+ cell_conf[i]->carrier_index = i;
+ cell_conf[i]->has_carrier_index = 1;
+ }
+ enb_config_reply_msg->cell_config=cell_conf;
+ }
+ *msg = malloc(sizeof(Protocol__FlexranMessage));
+ if(*msg == NULL)
+ goto error;
+ protocol__flexran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG;
+ (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+ (*msg)->enb_config_reply_msg = enb_config_reply_msg;
+
+ return 0;
+
+ error:
+ // TODO: Need to make proper error handling
+ if (header != NULL)
+ free(header);
+ if (enb_config_reply_msg != NULL)
+ free(enb_config_reply_msg);
+ if(*msg != NULL)
+ free(*msg);
+ //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+
+/*
+ * timer primitives
+ */
+
+//struct flexran_agent_map agent_map;
+flexran_agent_timer_instance_t timer_instance;
+int agent_timer_init = 0;
+err_code_t flexran_agent_init_timer(void){
+
+ LOG_I(FLEXRAN_AGENT, "init RB tree\n");
+ if (!agent_timer_init) {
+ RB_INIT(&timer_instance.flexran_agent_head);
+ agent_timer_init = 1;
+ }
+
+ return PROTOCOL__FLEXRAN_ERR__NO_ERR;
+}
+
+RB_GENERATE(flexran_agent_map, flexran_agent_timer_element_s, entry, flexran_agent_compare_timer);
+
+/* The timer_id might not be the best choice for the comparison */
+int flexran_agent_compare_timer(struct flexran_agent_timer_element_s *a, struct flexran_agent_timer_element_s *b){
+
+ if (a->timer_id < b->timer_id) return -1;
+ if (a->timer_id > b->timer_id) return 1;
+
+ // equal timers
+ return 0;
+}
+
+err_code_t flexran_agent_create_timer(uint32_t interval_sec,
+ uint32_t interval_usec,
+ agent_id_t agent_id,
+ instance_t instance,
+ uint32_t timer_type,
+ xid_t xid,
+ flexran_agent_timer_callback_t cb,
+ void* timer_args,
+ long *timer_id){
+
+ struct flexran_agent_timer_element_s *e = calloc(1, sizeof(*e));
+ DevAssert(e != NULL);
+
+//uint32_t timer_id;
+ int ret=-1;
+
+ if ((interval_sec == 0) && (interval_usec == 0 ))
+ return TIMER_NULL;
+
+ if (timer_type >= FLEXRAN_AGENT_TIMER_TYPE_MAX)
+ return TIMER_TYPE_INVALIDE;
+
+ if (timer_type == FLEXRAN_AGENT_TIMER_TYPE_ONESHOT){
+ ret = timer_setup(interval_sec,
+ interval_usec,
+ TASK_FLEXRAN_AGENT,
+ instance,
+ TIMER_ONE_SHOT,
+ timer_args,
+ timer_id);
+
+ e->type = TIMER_ONE_SHOT;
+ }
+ else if (timer_type == FLEXRAN_AGENT_TIMER_TYPE_PERIODIC ){
+ ret = timer_setup(interval_sec,
+ interval_usec,
+ TASK_FLEXRAN_AGENT,
+ instance,
+ TIMER_PERIODIC,
+ timer_args,
+ timer_id);
+
+ e->type = TIMER_PERIODIC;
+ }
+
+ if (ret < 0 ) {
+ return TIMER_SETUP_FAILED;
+ }
+
+ e->agent_id = agent_id;
+ e->instance = instance;
+ e->state = FLEXRAN_AGENT_TIMER_STATE_ACTIVE;
+ e->timer_id = *timer_id;
+ e->xid = xid;
+ e->timer_args = timer_args;
+ e->cb = cb;
+ /*element should be a real pointer*/
+ RB_INSERT(flexran_agent_map, &timer_instance.flexran_agent_head, e);
+
+ LOG_I(FLEXRAN_AGENT,"Created a new timer with id 0x%lx for agent %d, instance %d \n",
+ e->timer_id, e->agent_id, e->instance);
+
+ return 0;
+}
+
+err_code_t flexran_agent_destroy_timer(long timer_id){
+
+ struct flexran_agent_timer_element_s *e = get_timer_entry(timer_id);
+
+ if (e != NULL ) {
+ RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
+ flexran_agent_destroy_flexran_message(e->timer_args->msg);
+ free(e);
+ }
+
+ if (timer_remove(timer_id) < 0 )
+ goto error;
+
+ return 0;
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "timer can't be removed\n");
+ return TIMER_REMOVED_FAILED ;
+}
+
+err_code_t flexran_agent_destroy_timer_by_task_id(xid_t xid) {
+ struct flexran_agent_timer_element_s *e = NULL;
+ long timer_id;
+ RB_FOREACH(e, flexran_agent_map, &timer_instance.flexran_agent_head) {
+ if (e->xid == xid) {
+ timer_id = e->timer_id;
+ RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
+ flexran_agent_destroy_flexran_message(e->timer_args->msg);
+ free(e);
+ if (timer_remove(timer_id) < 0 ) {
+ goto error;
+ }
+ }
+ }
+ return 0;
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "timer can't be removed\n");
+ return TIMER_REMOVED_FAILED ;
+}
+
+err_code_t flexran_agent_destroy_timers(void){
+
+ struct flexran_agent_timer_element_s *e = NULL;
+
+ RB_FOREACH(e, flexran_agent_map, &timer_instance.flexran_agent_head) {
+ RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
+ timer_remove(e->timer_id);
+ flexran_agent_destroy_flexran_message(e->timer_args->msg);
+ free(e);
+ }
+
+ return 0;
+
+}
+
+void flexran_agent_sleep_until(struct timespec *ts, int delay) {
+ ts->tv_nsec += delay;
+ if(ts->tv_nsec >= 1000*1000*1000){
+ ts->tv_nsec -= 1000*1000*1000;
+ ts->tv_sec++;
+ }
+ clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts, NULL);
+}
+
+
+err_code_t flexran_agent_stop_timer(long timer_id){
+
+ struct flexran_agent_timer_element_s *e=NULL;
+ struct flexran_agent_timer_element_s search;
+ memset(&search, 0, sizeof(struct flexran_agent_timer_element_s));
+ search.timer_id = timer_id;
+
+ e = RB_FIND(flexran_agent_map, &timer_instance.flexran_agent_head, &search);
+
+ if (e != NULL ) {
+ e->state = FLEXRAN_AGENT_TIMER_STATE_STOPPED;
+ }
+
+ timer_remove(timer_id);
+
+ return 0;
+}
+
+struct flexran_agent_timer_element_s * get_timer_entry(long timer_id) {
+
+ struct flexran_agent_timer_element_s search;
+ memset(&search, 0, sizeof(struct flexran_agent_timer_element_s));
+ search.timer_id = timer_id;
+
+ return RB_FIND(flexran_agent_map, &timer_instance.flexran_agent_head, &search);
+}
diff --git a/openair2/ENB_APP/flexran_agent_common.h b/openair2/ENB_APP/flexran_agent_common.h
new file mode 100644
index 0000000000..56a52cd0b6
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_common.h
@@ -0,0 +1,496 @@
+/*
+ * 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.0 (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_common.h
+ * \brief common message primitves and utilities
+ * \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+
+
+#ifndef FLEXRAN_AGENT_COMMON_H_
+#define FLEXRAN_AGENT_COMMON_H_
+
+#include
+
+#include "header.pb-c.h"
+#include "flexran.pb-c.h"
+#include "stats_messages.pb-c.h"
+#include "stats_common.pb-c.h"
+
+#include "flexran_agent_defs.h"
+#include "enb_config.h"
+
+#include "LAYER2/MAC/extern.h"
+#include "LAYER2/RLC/rlc.h"
+
+# include "tree.h"
+# include "intertask_interface.h"
+# include "timer.h"
+
+#define FLEXRAN_VERSION 0
+
+typedef int (*flexran_agent_message_decoded_callback)(
+ mid_t mod_id,
+ const void *params,
+ Protocol__FlexranMessage **msg
+);
+
+typedef int (*flexran_agent_message_destruction_callback)(
+ Protocol__FlexranMessage *msg
+);
+
+/**********************************
+ * FlexRAN protocol messages helper
+ * functions and generic handlers
+ **********************************/
+
+/* Helper functions for message (de)serialization */
+int flexran_agent_serialize_message(Protocol__FlexranMessage *msg, void **buf, int *size);
+int flexran_agent_deserialize_message(void *data, int size, Protocol__FlexranMessage **msg);
+
+/* Serialize message and then destroy the input flexran msg. Should be called when protocol
+ message is created dynamically */
+void * flexran_agent_pack_message(Protocol__FlexranMessage *msg,
+ uint32_t * size);
+
+/* Calls destructor of the given message */
+err_code_t flexran_agent_destroy_flexran_message(Protocol__FlexranMessage *msg);
+
+/* Function to create the header for any FlexRAN protocol message */
+int flexran_create_header(xid_t xid, Protocol__FlexType type, Protocol__FlexHeader **header);
+
+/* Hello protocol message constructor and destructor */
+int flexran_agent_hello(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_hello(Protocol__FlexranMessage *msg);
+
+/* Echo request protocol message constructor and destructor */
+int flexran_agent_echo_request(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_echo_request(Protocol__FlexranMessage *msg);
+
+/* Echo reply protocol message constructor and destructor */
+int flexran_agent_echo_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_echo_reply(Protocol__FlexranMessage *msg);
+
+/* eNodeB configuration reply message constructor and destructor */
+int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg);
+
+/* UE configuration reply message constructor and destructor */
+int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_ue_config_reply(Protocol__FlexranMessage *msg);
+
+/* Logical channel reply configuration message constructor and destructor */
+int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_lc_config_reply(Protocol__FlexranMessage *msg);
+
+/* eNodeB configuration request message constructor and destructor */
+int flexran_agent_enb_config_request(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_enb_config_request(Protocol__FlexranMessage *msg);
+
+/* UE configuration request message constructor */
+/* TODO: Need to define and implement destructor */
+int flexran_agent_destroy_ue_config_request(Protocol__FlexranMessage *msg);
+
+/* Logical channel configuration request message constructor */
+/* TODO: Need to define and implement destructor */
+int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg);
+
+/* UE state change message constructor and destructor */
+int flexran_agent_ue_state_change(mid_t mod_id, uint32_t rnti, uint8_t state_change);
+int flexran_agent_destroy_ue_state_change(Protocol__FlexranMessage *msg);
+
+/* Control delegation message constructor and destructor */
+int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg);
+
+/* Policy reconfiguration message constructor and destructor */
+int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg);
+
+/* FlexRAN protocol message dispatcher function */
+Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id,
+ uint8_t *data,
+ uint32_t size);
+
+/* Function to be used to send a message to a dispatcher once the appropriate event is triggered. */
+Protocol__FlexranMessage *flexran_agent_handle_timed_task(void *args);
+
+
+
+
+/****************************
+ * get generic info from RAN
+ ****************************/
+
+void flexran_set_enb_vars(mid_t mod_id, ran_name_t ran);
+
+int flexran_get_current_time_ms (mid_t mod_id, int subframe_flag);
+
+/*Return the current frame number
+ *Could be using implementation specific numbering of frames
+ */
+unsigned int flexran_get_current_frame(mid_t mod_id);
+
+/*Return the current SFN (0-1023)*/
+unsigned int flexran_get_current_system_frame_num(mid_t mod_id);
+
+unsigned int flexran_get_current_subframe(mid_t mod_id);
+
+/*Return the frame and subframe number in compact 16-bit format.
+ Bits 0-3 subframe, rest for frame. Required by FlexRAN protocol*/
+uint16_t flexran_get_sfn_sf (mid_t mod_id);
+
+/* Return a future frame and subframe number that is ahead_of_time
+ subframes later in compact 16-bit format. Bits 0-3 subframe,
+ rest for frame */
+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);
+
+/* Get the rnti of a UE with id ue_id */
+int flexran_get_ue_crnti (mid_t mod_id, mid_t ue_id);
+
+/* Get the RLC buffer status report of a ue for a designated
+ logical channel id */
+int flexran_get_ue_bsr (mid_t mod_id, mid_t ue_id, lcid_t lcid);
+
+/* Get power headroom of UE with id ue_id */
+int flexran_get_ue_phr (mid_t mod_id, mid_t ue_id);
+
+/* Get the UE wideband CQI */
+int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id);
+
+/* Get the transmission queue size for a UE with a channel_id logical channel id */
+int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id);
+
+/* Update the timing advance status (find out whether a timing advance command is required) */
+int flexran_update_TA(mid_t mod_id, mid_t ue_id, int CC_id);
+
+/* Return timing advance MAC control element for a designated cell and UE */
+int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id, int CC_id);
+
+/* Get the number of active component carriers for a specific UE */
+int flexran_get_active_CC(mid_t mod_id, mid_t ue_id);
+
+/* Get the rank indicator for a designated cell and UE */
+int flexran_get_current_RI(mid_t mod_id, mid_t ue_id, int CC_id);
+
+/* See TS 36.213, section 10.1 */
+int flexran_get_n1pucch_an(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, section 5.4 */
+int flexran_get_nRB_CQI(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, section 5.4 */
+int flexran_get_deltaPUCCH_Shift(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, section 5.7.1 */
+int flexran_get_prach_ConfigIndex(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, section 5.7.1 */
+int flexran_get_prach_FreqOffset(mid_t mod_id, int CC_id);
+
+/* See TS 36.321 */
+int flexran_get_maxHARQ_Msg3Tx(mid_t mod_id, int CC_id);
+
+/* Get the length of the UL cyclic prefix */
+int flexran_get_ul_cyclic_prefix_length(mid_t mod_id, int CC_id);
+
+/* Get the length of the DL cyclic prefix */
+int flexran_get_dl_cyclic_prefix_length(mid_t mod_id, int CC_id);
+
+/* Get the physical cell id of a cell */
+int flexran_get_cell_id(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, section 5.5.3.2 */
+int flexran_get_srs_BandwidthConfig(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, table 5.5.3.3-1 and 2 */
+int flexran_get_srs_SubframeConfig(mid_t mod_id, int CC_id);
+
+/* Boolean value. See TS 36.211,
+ section 5.5.3.2. TDD only */
+int flexran_get_srs_MaxUpPts(mid_t mod_id, int CC_id);
+
+/* Get number of DL resource blocks */
+int flexran_get_N_RB_DL(mid_t mod_id, int CC_id);
+
+/* Get number of UL resource blocks */
+int flexran_get_N_RB_UL(mid_t mod_id, int CC_id);
+
+/* Get number of resource block groups */
+int flexran_get_N_RBG(mid_t mod_id, int CC_id);
+
+/* Get DL/UL subframe assignment. TDD only */
+int flexran_get_subframe_assignment(mid_t mod_id, int CC_id);
+
+/* TDD only. See TS 36.211, table 4.2.1 */
+int flexran_get_special_subframe_assignment(mid_t mod_id, int CC_id);
+
+/* Get the duration of the random access response window in subframes */
+int flexran_get_ra_ResponseWindowSize(mid_t mod_id, int CC_id);
+
+/* Get timer used for random access */
+int flexran_get_mac_ContentionResolutionTimer(mid_t mod_id, int CC_id);
+
+/* Get type of duplex mode (FDD/TDD) */
+int flexran_get_duplex_mode(mid_t mod_id, int CC_id);
+
+/* Get the SI window length */
+long flexran_get_si_window_length(mid_t mod_id, int CC_id);
+
+/* Get the number of PDCCH symbols configured for the cell */
+int flexran_get_num_pdcch_symb(mid_t mod_id, int CC_id);
+
+/* See TS 36.213, sec 5.1.1.1 */
+int flexran_get_tpc(mid_t mod_id, mid_t ue_id);
+
+/* Get the first available HARQ process for a specific cell and UE during
+ a designated frame and subframe. Returns 0 for success. The id and the
+ status of the HARQ process are stored in id and status respectively */
+int flexran_get_harq(const mid_t mod_id, const uint8_t CC_id, const mid_t ue_id,
+ const int frame, const uint8_t subframe, int *id, int *round);
+
+/* Uplink power control management*/
+int flexran_get_p0_pucch_dbm(mid_t mod_id, mid_t ue_id, int CC_id);
+
+int flexran_get_p0_nominal_pucch(mid_t mod_id, int CC_id);
+
+int flexran_get_p0_pucch_status(mid_t mod_id, mid_t ue_id, int CC_id);
+
+int flexran_update_p0_pucch(mid_t mod_id, mid_t ue_id, int CC_id);
+
+
+/*
+ * ************************************
+ * Get Messages for UE Configuration Reply
+ * ************************************
+ */
+
+/* Get timer in subframes. Controls the synchronization
+ status of the UE, not the actual timing
+ advance procedure. See TS 36.321 */
+int flexran_get_time_alignment_timer(mid_t mod_id, mid_t ue_id);
+
+/* Get measurement gap configuration. See TS 36.133 */
+int flexran_get_meas_gap_config(mid_t mod_id, mid_t ue_id);
+
+/* Get measurement gap configuration offset if applicable */
+int flexran_get_meas_gap_config_offset(mid_t mod_id, mid_t ue_id);
+
+/* DL aggregated bit-rate of non-gbr bearer
+ per UE. See TS 36.413 */
+int flexran_get_ue_aggregated_max_bitrate_dl (mid_t mod_id, mid_t ue_id);
+
+/* UL aggregated bit-rate of non-gbr bearer
+ per UE. See TS 36.413 */
+int flexran_get_ue_aggregated_max_bitrate_ul (mid_t mod_id, mid_t ue_id);
+
+/* Only half-duplex support. FDD
+ operation. Boolean value */
+int flexran_get_half_duplex(mid_t ue_id);
+
+/* Support of intra-subframe hopping.
+ Boolean value */
+int flexran_get_intra_sf_hopping(mid_t ue_id);
+
+/* UE support for type 2 hopping with
+ n_sb>1 */
+int flexran_get_type2_sb_1(mid_t ue_id);
+
+/* Get the UE category */
+int flexran_get_ue_category(mid_t ue_id);
+
+/* UE support for resource allocation
+ type 1 */
+int flexran_get_res_alloc_type1(mid_t ue_id);
+
+/* Get UE transmission mode */
+int flexran_get_ue_transmission_mode(mid_t mod_id, mid_t ue_id);
+
+/* Boolean value. See TS 36.321 */
+int flexran_get_tti_bundling(mid_t mod_id, mid_t ue_id);
+
+/* The max HARQ retransmission for UL.
+ See TS 36.321 */
+int flexran_get_maxHARQ_TX(mid_t mod_id, mid_t ue_id);
+
+/* See TS 36.213 */
+int flexran_get_beta_offset_ack_index(mid_t mod_id, mid_t ue_id);
+
+/* See TS 36.213 */
+int flexran_get_beta_offset_ri_index(mid_t mod_id, mid_t ue_id);
+
+/* See TS 36.213 */
+int flexran_get_beta_offset_cqi_index(mid_t mod_id, mid_t ue_id);
+
+/* Boolean. See TS36.213, Section 10.1 */
+int flexran_get_simultaneous_ack_nack_cqi(mid_t mod_id, mid_t ue_id);
+
+/* Boolean. See TS 36.213, Section 8.2 */
+int flexran_get_ack_nack_simultaneous_trans(mid_t mod_id,mid_t ue_id);
+
+/* Get aperiodic CQI report mode */
+int flexran_get_aperiodic_cqi_rep_mode(mid_t mod_id,mid_t ue_id);
+
+/* Get ACK/NACK feedback mode. TDD only */
+int flexran_get_tdd_ack_nack_feedback(mid_t mod_id, mid_t ue_id);
+
+/* See TS36.213, section 10.1 */
+int flexran_get_ack_nack_repetition_factor(mid_t mod_id, mid_t ue_id);
+
+/* Boolean. Extended buffer status report size */
+int flexran_get_extended_bsr_size(mid_t mod_id, mid_t ue_id);
+
+/* Get number of UE transmission antennas */
+int flexran_get_ue_transmission_antenna(mid_t mod_id, mid_t ue_id);
+
+/* Get logical channel group of a channel with id lc_id */
+int flexran_get_lcg(mid_t ue_id, mid_t lc_id);
+
+/* Get direction of logical channel with id lc_id */
+int flexran_get_direction(mid_t ue_id, mid_t lc_id);
+
+/*******************
+ * timer primitves
+ *******************/
+
+#define TIMER_NULL -1
+#define TIMER_TYPE_INVALIDE -2
+#define TIMER_SETUP_FAILED -3
+#define TIMER_REMOVED_FAILED -4
+#define TIMER_ELEMENT_NOT_FOUND -5
+
+
+/* Type of the callback executed when the timer expired */
+typedef Protocol__FlexranMessage *(*flexran_agent_timer_callback_t)(void*);
+
+typedef enum {
+ /* oneshot timer: */
+ FLEXRAN_AGENT_TIMER_TYPE_ONESHOT = 0x0,
+
+ /* periodic timer */
+ FLEXRAN_AGENT_TIMER_TYPE_PERIODIC = 0x1,
+
+ /* Inactive state: initial state for any timer. */
+ FLEXRAN_AGENT_TIMER_TYPE_EVENT_DRIVEN = 0x2,
+
+ /* Max number of states available */
+ FLEXRAN_AGENT_TIMER_TYPE_MAX,
+} flexran_agent_timer_type_t;
+
+typedef enum {
+ /* Inactive state: initial state for any timer. */
+ FLEXRAN_AGENT_TIMER_STATE_INACTIVE = 0x0,
+
+ /* Inactive state: initial state for any timer. */
+ FLEXRAN_AGENT_TIMER_STATE_ACTIVE = 0x1,
+
+ /* Inactive state: initial state for any timer. */
+ FLEXRAN_AGENT_TIMER_STATE_STOPPED = 0x2,
+
+ /* Max number of states available */
+ FLEXRAN_AGENT_TIMER_STATE_MAX,
+} flexran_agent_timer_state_t;
+
+typedef struct flexran_agent_timer_args_s{
+ mid_t mod_id;
+ Protocol__FlexranMessage *msg;
+} flexran_agent_timer_args_t;
+
+
+
+typedef struct flexran_agent_timer_element_s{
+ RB_ENTRY(flexran_agent_timer_element_s) entry;
+
+ agent_id_t agent_id;
+ instance_t instance;
+
+ flexran_agent_timer_type_t type;
+ flexran_agent_timer_state_t state;
+
+ uint32_t interval_sec;
+ uint32_t interval_usec;
+
+ long timer_id; /* Timer id returned by the timer API*/
+ xid_t xid; /*The id of the task as received by the controller
+ message*/
+
+ flexran_agent_timer_callback_t cb;
+ flexran_agent_timer_args_t *timer_args;
+
+} flexran_agent_timer_element_t;
+
+typedef struct flexran_agent_timer_instance_s{
+ RB_HEAD(flexran_agent_map, flexran_agent_timer_element_s) flexran_agent_head;
+}flexran_agent_timer_instance_t;
+
+
+err_code_t flexran_agent_init_timer(void);
+
+/* Create a timer for some agent related event with id xid. Will store the id
+ of the generated timer in timer_id */
+err_code_t flexran_agent_create_timer(uint32_t interval_sec,
+ uint32_t interval_usec,
+ agent_id_t agent_id,
+ instance_t instance,
+ uint32_t timer_type,
+ xid_t xid,
+ flexran_agent_timer_callback_t cb,
+ void* timer_args,
+ long *timer_id);
+
+/* Destroy all existing timers */
+err_code_t flexran_agent_destroy_timers(void);
+
+/* Destroy the timer with the given timer_id */
+err_code_t flexran_agent_destroy_timer(long timer_id);
+
+/* Destroy the timer for task with id xid */
+err_code_t flexran_agent_destroy_timer_by_task_id(xid_t xid);
+
+/* Stop a timer */
+err_code_t flexran_agent_stop_timer(long timer_id);
+
+/* Restart the given timer */
+err_code_t flexran_agent_restart_timer(long *timer_id);
+
+/* Find the timer with the given timer_id */
+struct flexran_agent_timer_element_s * get_timer_entry(long timer_id);
+
+/* Obtain the protocol message stored in the given expired timer */
+Protocol__FlexranMessage * flexran_agent_process_timeout(long timer_id, void* timer_args);
+
+/* Comparator function comparing two timers. Decides the ordering of the timers */
+int flexran_agent_compare_timer(struct flexran_agent_timer_element_s *a, struct flexran_agent_timer_element_s *b);
+
+/*Specify a delay in nanoseconds to timespec and sleep until then*/
+void flexran_agent_sleep_until(struct timespec *ts, int delay);
+
+/* RB_PROTOTYPE is for .h files */
+RB_PROTOTYPE(flexran_agent_map, flexran_agent_timer_element_s, entry, flexran_agent_compare_timer);
+
+
+#endif
diff --git a/openair2/ENB_APP/flexran_agent_common_internal.c b/openair2/ENB_APP/flexran_agent_common_internal.c
new file mode 100644
index 0000000000..3026190863
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_common_internal.c
@@ -0,0 +1,392 @@
+/*
+ * 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.0 (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_common_internal.c
+ * \brief internal functions for common message primitves and utilities
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#include
+#include
+
+#include "flexran_agent_common_internal.h"
+#include "flexran_agent_mac_internal.h"
+
+int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length) {
+
+ yaml_parser_t parser;
+ yaml_event_t event;
+
+ int done = 0;
+ int mapping_started = 0;
+
+ LOG_I(ENB_APP, "Time to apply a new policy \n");
+
+ yaml_parser_initialize(&parser);
+
+ yaml_parser_set_input_string(&parser, policy, strlen(policy));
+
+ while (!done) {
+ if (!yaml_parser_parse(&parser, &event))
+ goto error;
+
+ switch (event.type) {
+ case YAML_STREAM_START_EVENT:
+ case YAML_STREAM_END_EVENT:
+ case YAML_DOCUMENT_START_EVENT:
+ case YAML_DOCUMENT_END_EVENT:
+ break;
+ case YAML_MAPPING_START_EVENT:
+ mapping_started = 1;
+ break;
+ case YAML_MAPPING_END_EVENT:
+ mapping_started = 0;
+ break;
+ case YAML_SCALAR_EVENT:
+ // Check the system name and call the proper handler
+ if (strcmp(event.data.scalar.value, "mac") == 0) {
+ LOG_D(ENB_APP, "This is intended for the mac system\n");
+ // Call the mac handler
+ if (parse_mac_config(mod_id, &parser) == -1) {
+ goto error;
+ }
+ } else if (strcmp(event.data.scalar.value, "rlc") == 0) {
+ // Call the RLC handler
+ LOG_D(ENB_APP, "This is intended for the rlc system\n");
+ // TODO : Just skip it for now
+ if (skip_system_section(&parser) == -1) {
+ goto error;
+ }
+ } else if (strcmp(event.data.scalar.value, "pdcp") == 0) {
+ // Call the PDCP handler
+ LOG_D(ENB_APP, "This is intended for the pdcp system\n");
+ // TODO : Just skip it for now
+ if (skip_system_section(&parser) == -1) {
+ goto error;
+ }
+ } else if (strcmp(event.data.scalar.value, "rrc") == 0) {
+ // Call the RRC handler
+ LOG_D(ENB_APP, "This is intended for the rrc system\n");
+ // TODO : Just skip it for now
+ if (skip_system_section(&parser) == -1) {
+ goto error;
+ }
+ } else {
+ goto error;
+ }
+ break;
+ default:
+ // We are not expecting to find any other type of event at this level
+ // of the hierarchy
+ yaml_event_delete(&event);
+ goto error;
+ }
+
+ done = (event.type == YAML_STREAM_END_EVENT);
+
+ yaml_event_delete(&event);
+ }
+
+ return 0;
+
+ error:
+ yaml_parser_delete(&parser);
+ return -1;
+
+}
+
+int skip_system_section(yaml_parser_t *parser) {
+ yaml_event_t event;
+
+ int done = 0;
+
+ int sequence_started = 0;
+ int mapping_started = 0;
+
+ while (!done) {
+ if (!yaml_parser_parse(parser, &event))
+ goto error;
+
+ switch (event.type) {
+
+ case YAML_SEQUENCE_START_EVENT:
+ LOG_D(ENB_APP, "A sequence just started as expected\n");
+ sequence_started = 1;
+ break;
+ case YAML_SEQUENCE_END_EVENT:
+ LOG_D(ENB_APP, "A sequence ended\n");
+ sequence_started = 0;
+ break;
+ case YAML_MAPPING_START_EVENT:
+ if (!sequence_started) {
+ goto error;
+ }
+ LOG_D(ENB_APP, "A mapping started\n");
+ mapping_started = 1;
+ break;
+ case YAML_MAPPING_END_EVENT:
+ if (!mapping_started) {
+ goto error;
+ }
+ LOG_D(ENB_APP, "A mapping ended\n");
+ mapping_started = 0;
+ break;
+ case YAML_SCALAR_EVENT:
+ if (!mapping_started) {
+ goto error;
+ }
+ // Entered a subsystem section. Let's skip it
+ if (skip_subsystem_section(parser) == -1) {
+ goto error;
+ }
+ }
+
+ done = (event.type == YAML_SEQUENCE_END_EVENT);
+
+ yaml_event_delete(&event);
+
+ }
+
+ return 0;
+
+ error:
+ yaml_event_delete(&event);
+ return -1;
+}
+
+int skip_subsystem_section(yaml_parser_t *parser) {
+
+ yaml_event_t event;
+
+ int done = 0;
+ int mapping_started = 0;
+
+ while (!done) {
+ if (!yaml_parser_parse(parser, &event))
+ goto error;
+
+ switch (event.type) {
+ case YAML_MAPPING_START_EVENT:
+ LOG_D(ENB_APP, "The mapping of the subsystem started\n");
+ mapping_started = 1;
+ break;
+ case YAML_MAPPING_END_EVENT:
+ LOG_D(ENB_APP, "The mapping of the subsystem ended\n");
+ mapping_started = 0;
+ break;
+ case YAML_SCALAR_EVENT:
+ if (!mapping_started) {
+ goto error;
+ }
+ // Check what key needs to be set
+ if (strcmp(event.data.scalar.value, "behavior") == 0) {
+ LOG_D(ENB_APP, "Skipping the behavior attribute\n");
+ yaml_event_delete(&event);
+ if (!yaml_parser_parse(parser, &event)) {
+ goto error;
+ }
+ if (event.type == YAML_SCALAR_EVENT) {
+ break;
+ } else {
+ goto error;
+ }
+ } else if (strcmp(event.data.scalar.value, "parameters") == 0) {
+ LOG_D(ENB_APP, "Skipping the parameters for this subsystem\n");
+ if (skip_subsystem_parameters_config(parser) == -1) {
+ goto error;
+ }
+ }
+ break;
+ default:
+ goto error;
+ }
+
+ done = (event.type == YAML_MAPPING_END_EVENT);
+ yaml_event_delete(&event);
+ }
+
+ return 0;
+
+ error:
+ yaml_event_delete(&event);
+ return -1;
+}
+
+int skip_subsystem_parameters_config(yaml_parser_t *parser) {
+ yaml_event_t event;
+
+ void *param;
+
+ int done = 0;
+ int mapping_started = 0;
+
+ while (!done) {
+
+ if (!yaml_parser_parse(parser, &event))
+ goto error;
+
+ switch (event.type) {
+ // We are expecting a mapping of parameters
+ case YAML_MAPPING_START_EVENT:
+ LOG_D(ENB_APP, "The mapping of the parameters started\n");
+ mapping_started = 1;
+ break;
+ case YAML_MAPPING_END_EVENT:
+ LOG_D(ENB_APP, "The mapping of the parameters ended\n");
+ mapping_started = 0;
+ break;
+ case YAML_SCALAR_EVENT:
+ if (!mapping_started) {
+ goto error;
+ }
+ // Check what key needs to be set
+ LOG_D(ENB_APP, "Skipping parameter %s\n", event.data.scalar.value);
+ if (skip_parameter_modification(parser) == -1 ) {
+ goto error;
+ }
+ break;
+ default:
+ goto error;
+ }
+
+ done = (event.type == YAML_MAPPING_END_EVENT);
+ yaml_event_delete(&event);
+ }
+
+ return 0;
+
+ error:
+ yaml_event_delete(&event);
+ return -1;
+}
+
+
+int skip_parameter_modification(yaml_parser_t *parser) {
+ yaml_event_t event;
+
+ int done = 0;
+ int is_array = 0;
+ int i = 0;
+
+ while (!done) {
+ if (!yaml_parser_parse(parser, &event)) {
+ goto error;
+ }
+
+ // Expecting either a scalar or a sequence
+ switch (event.type) {
+ case YAML_SEQUENCE_START_EVENT:
+ is_array = 1;
+ break;
+ case YAML_SCALAR_EVENT:
+ if ((strcmp(event.data.scalar.tag, YAML_INT_TAG) == 0) ||
+ (strcmp(event.data.scalar.tag, YAML_FLOAT_TAG) == 0) ||
+ (strcmp(event.data.scalar.tag, YAML_STR_TAG) == 0) ||
+ (strcmp(event.data.scalar.tag, YAML_BOOL_TAG) == 0)) {
+ // Do nothing
+ } else {
+ // No other type is supported at the moment, so it should be considered an error
+ // if we reach here
+ goto error;
+ }
+ if (is_array) {
+ i++;
+ } else {
+ done = 1;
+ }
+ break;
+ case YAML_SEQUENCE_END_EVENT:
+ done = 1;
+ break;
+ default:
+ goto error;
+ }
+ yaml_event_delete(&event);
+ }
+
+ return 0;
+
+ error:
+ yaml_event_delete(&event);
+ return -1;
+}
+
+int apply_parameter_modification(void *parameter, yaml_parser_t *parser) {
+ yaml_event_t event;
+
+ int done = 0;
+ int is_array = 0;
+ int i = 0;
+
+ char *endptr;
+
+ while (!done) {
+ if (!yaml_parser_parse(parser, &event)) {
+ goto error;
+ }
+
+ // Expecting either a scalar or a sequence
+ switch (event.type) {
+ case YAML_SEQUENCE_START_EVENT:
+ is_array = 1;
+ break;
+ case YAML_SCALAR_EVENT:
+ if (strcmp(event.data.scalar.tag, YAML_INT_TAG) == 0) {
+ ((int *) parameter)[i] = strtol(event.data.scalar.value, &endptr, 10);
+ } else if (strcmp(event.data.scalar.tag, YAML_FLOAT_TAG) == 0) {
+ ((float *) parameter)[i] = strtof(event.data.scalar.value, &endptr);
+ } else if (strcmp(event.data.scalar.tag, YAML_STR_TAG) == 0) {
+ strncpy(&((char *) parameter)[i], event.data.scalar.value, event.data.scalar.length);
+ } else if (strcmp(event.data.scalar.tag, YAML_BOOL_TAG) == 0) {
+ if (strcmp(event.data.scalar.value, "true") == 0) {
+ ((int *) parameter)[i] = 1;
+ } else {
+ ((int *) parameter)[i] = 0;
+ }
+ } else {
+ // No other type is supported at the moment, so it should be considered an error
+ // if we reach here
+ goto error;
+ }
+ if (is_array) {
+ i++;
+ } else {
+ done = 1;
+ }
+ break;
+ case YAML_SEQUENCE_END_EVENT:
+ done = 1;
+ break;
+ default:
+ goto error;
+ }
+ yaml_event_delete(&event);
+ }
+
+ return 0;
+
+ error:
+ yaml_event_delete(&event);
+ return -1;
+
+}
diff --git a/openair2/ENB_APP/flexran_agent_common_internal.h b/openair2/ENB_APP/flexran_agent_common_internal.h
new file mode 100644
index 0000000000..c8f78aafe9
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_common_internal.h
@@ -0,0 +1,56 @@
+/*
+ * 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.0 (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_common_internal.h
+ * \brief internal agent functions for common message primitves and utilities
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef FLEXRAN_AGENT_COMMON_INTERNAL_H_
+#define FLEXRAN_AGENT_COMMON_INTERNAL_H_
+
+#include
+
+#include "flexran_agent_defs.h"
+
+int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length);
+
+int apply_parameter_modification(void *parameter, yaml_parser_t *parser);
+
+// This can be used when parsing for a specific system that is not yet implmeneted
+// in order to skip its configuration, without affecting the rest
+int skip_system_section(yaml_parser_t *parser);
+
+// This can be used when parsing for a specific subsystem that is not yet implmeneted
+// in order to skip its configuration, without affecting the rest
+int skip_subsystem_section(yaml_parser_t *parser);
+
+// This can be used when parsing for the parameters of a specific subsystem
+//that is not yet implmeneted in order to skip its configuration, without affecting the rest
+int skip_subsystem_parameters_config(yaml_parser_t *parser);
+
+// This can be used when configuring the parameters of a specific subsystem
+//that is not yet implmeneted in order to skip its configuration, without affecting the rest
+int skip_parameter_modification(yaml_parser_t *parser);
+
+#endif
diff --git a/openair2/ENB_APP/flexran_agent_defs.h b/openair2/ENB_APP/flexran_agent_defs.h
new file mode 100644
index 0000000000..d60510b0c7
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_defs.h
@@ -0,0 +1,125 @@
+/*
+ * 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.0 (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_defs.h
+ * \brief FlexRAN agent common definitions
+ * \author Navid Nikaein and Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+#ifndef FLEXRAN_AGENT_DEFS_H_
+#define FLEXRAN_AGENT_DEFS_H_
+
+#include
+#include
+#include
+#include
+
+#include "link_manager.h"
+
+#define NUM_MAX_ENB 2
+#define NUM_MAX_UE 2048
+#define DEFAULT_FLEXRAN_AGENT_IPv4_ADDRESS "127.0.0.1"
+#define DEFAULT_FLEXRAN_AGENT_PORT 2210
+#define DEFAULT_FLEXRAN_AGENT_CACHE "/mnt/oai_agent_cache"
+
+typedef enum {
+
+ FLEXRAN_AGENT_DEFAULT=0,
+
+ FLEXRAN_AGENT_PHY=1,
+ FLEXRAN_AGENT_MAC=2,
+ FLEXRAN_AGENT_RLC=3,
+ FLEXRAN_AGENT_PDCP=4,
+ FLEXRAN_AGENT_RRC=5,
+ FLEXRAN_AGENT_S1AP=6,
+ FLEXRAN_AGENT_GTP=7,
+ FLEXRAN_AGENT_X2AP=8,
+
+ FLEXRAN_AGENT_MAX=9,
+
+} agent_id_t;
+
+typedef enum {
+ /* no action */
+ FLEXRAN_AGENT_ACTION_NONE = 0x0,
+
+ /* send action */
+ FLEXRAN_AGENT_ACTION_SEND = 0x1,
+
+ /* apply action */
+ FLEXRAN_AGENT_ACTION_APPLY = 0x2,
+
+ /* clear action */
+ FLEXRAN_AGENT_ACTION_CLEAR = 0x4,
+
+ /* write action */
+ FLEXRAN_AGENT_ACTION_WRITE = 0x8,
+
+ /* filter action */
+ FLEXRAN_AGENT_ACTION_FILTER = 0x10,
+
+ /* preprocess action */
+ FLEXRAN_AGENT_ACTION_PREPROCESS = 0x20,
+
+ /* meter action */
+ FLEXRAN_AGENT_ACTION_METER = 0x40,
+
+ /* Max number of states available */
+ FLEXRAN_AGENT_ACTION_MAX = 0x7f,
+} agent_action_t;
+
+
+typedef enum {
+
+ RAN_LTE_OAI= 0,
+
+ /* Max number of states available */
+ RAN_NAME_MAX = 0x7f,
+} ran_name_t;
+
+typedef uint8_t xid_t;
+typedef uint8_t mid_t; // module or enb id
+typedef uint8_t lcid_t;
+typedef int32_t err_code_t;
+
+
+
+typedef struct {
+ /* general info */
+
+ /* stats */
+
+ uint32_t total_rx_msg;
+ uint32_t total_tx_msg;
+
+ uint32_t rx_msg[NUM_MAX_ENB];
+ uint32_t tx_msg[NUM_MAX_ENB];
+
+} flexran_agent_info_t;
+
+typedef struct {
+ mid_t enb_id;
+ flexran_agent_info_t agent_info;
+
+} flexran_agent_instance_t;
+
+#endif
diff --git a/openair2/ENB_APP/flexran_agent_extern.h b/openair2/ENB_APP/flexran_agent_extern.h
new file mode 100644
index 0000000000..3a03239e6f
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_extern.h
@@ -0,0 +1,48 @@
+/*
+ * 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.0 (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 ENB_APP/extern.h
+ * \brief FlexRAN agent - mac interface primitives
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ * \mail x.foukas@sms.ed.ac.uk
+ */
+
+#ifndef __FLEXRAN_AGENT_EXTERN_H__
+#define __FLEXRAN_AGENT_EXTERN_H__
+
+#include "flexran_agent_defs.h"
+#include "flexran_agent_mac_defs.h"
+
+
+//extern msg_context_t shared_ctxt[NUM_MAX_ENB][FLEXRAN_AGENT_MAX];
+
+/* full path of the local cache for storing VSFs */
+extern char local_cache[40];
+
+/* Control module interface for the communication of the MAC Control Module with the agent */
+extern AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];
+
+/* Flag indicating whether the VSFs for the MAC control module have been registered */
+extern unsigned int mac_agent_registered[NUM_MAX_ENB];
+
+#endif
diff --git a/openair2/ENB_APP/flexran_agent_handler.c b/openair2/ENB_APP/flexran_agent_handler.c
new file mode 100644
index 0000000000..4967e46923
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_handler.c
@@ -0,0 +1,189 @@
+/*
+ * 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.0 (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_handler.c
+ * \brief FlexRAN agent tx and rx message handler
+ * \author Xenofon Foukas and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+
+#include "flexran_agent_common.h"
+#include "flexran_agent_mac.h"
+#include "log.h"
+
+#include "assertions.h"
+
+flexran_agent_message_decoded_callback agent_messages_callback[][3] = {
+ {flexran_agent_hello, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_HELLO_MSG*/
+ {flexran_agent_echo_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REQUEST_MSG*/
+ {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REPLY_MSG*/ //Must add handler when receiving echo reply
+ {flexran_agent_mac_handle_stats, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REQUEST_MSG*/
+ {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG*/
+ {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_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_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*/
+ {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG*/
+ {flexran_agent_control_delegation, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DELEGATION_MSG*/
+ {flexran_agent_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_AGENT_RECONFIGURATION_MSG*/
+};
+
+flexran_agent_message_destruction_callback message_destruction_callback[] = {
+ flexran_agent_destroy_hello,
+ flexran_agent_destroy_echo_request,
+ flexran_agent_destroy_echo_reply,
+ flexran_agent_mac_destroy_stats_request,
+ flexran_agent_mac_destroy_stats_reply,
+ flexran_agent_mac_destroy_sf_trigger,
+ flexran_agent_mac_destroy_sr_info,
+ flexran_agent_destroy_enb_config_request,
+ flexran_agent_destroy_enb_config_reply,
+ flexran_agent_destroy_ue_config_request,
+ flexran_agent_destroy_ue_config_reply,
+ flexran_agent_destroy_lc_config_request,
+ flexran_agent_destroy_lc_config_reply,
+ flexran_agent_mac_destroy_dl_config,
+ flexran_agent_destroy_ue_state_change,
+ flexran_agent_destroy_control_delegation,
+ flexran_agent_destroy_agent_reconfiguration,
+};
+
+static const char *flexran_agent_direction2String[] = {
+ "", /* not_set */
+ "originating message", /* originating message */
+ "successfull outcome", /* successfull outcome */
+ "unsuccessfull outcome", /* unsuccessfull outcome */
+};
+
+
+Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id,
+ uint8_t *data,
+ uint32_t size){
+
+ Protocol__FlexranMessage *decoded_message, *reply_message;
+ err_code_t err_code;
+ DevAssert(data != NULL);
+
+ if (flexran_agent_deserialize_message(data, size, &decoded_message) < 0) {
+ err_code= PROTOCOL__FLEXRAN_ERR__MSG_DECODING;
+ goto error;
+ }
+
+ if ((decoded_message->msg_case > sizeof(agent_messages_callback) / (3 * sizeof(flexran_agent_message_decoded_callback))) ||
+ (decoded_message->msg_dir > PROTOCOL__FLEXRAN_DIRECTION__UNSUCCESSFUL_OUTCOME)){
+ err_code= PROTOCOL__FLEXRAN_ERR__MSG_NOT_HANDLED;
+ goto error;
+ }
+
+ if (agent_messages_callback[decoded_message->msg_case-1][decoded_message->msg_dir-1] == NULL) {
+ err_code= PROTOCOL__FLEXRAN_ERR__MSG_NOT_SUPPORTED;
+ goto error;
+
+ }
+
+ err_code = ((*agent_messages_callback[decoded_message->msg_case-1][decoded_message->msg_dir-1])(mod_id, (void *) decoded_message, &reply_message));
+ if ( err_code < 0 ){
+ goto error;
+ } else if (err_code == 1) { //If err_code > 1, we do not want to dispose the message yet
+ protocol__flexran_message__free_unpacked(decoded_message, NULL);
+ }
+ return reply_message;
+
+error:
+ LOG_E(FLEXRAN_AGENT,"errno %d occured\n",err_code);
+ return NULL;
+
+}
+
+
+
+void * flexran_agent_pack_message(Protocol__FlexranMessage *msg,
+ uint32_t * size){
+
+ void * buffer;
+ err_code_t err_code = PROTOCOL__FLEXRAN_ERR__NO_ERR;
+
+ if (flexran_agent_serialize_message(msg, &buffer, size) < 0 ) {
+ err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENCODING;
+ goto error;
+ }
+
+ // free the msg --> later keep this in the data struct and just update the values
+ //TODO call proper destroy function
+ err_code = ((*message_destruction_callback[msg->msg_case-1])(msg));
+
+ DevAssert(buffer !=NULL);
+
+ LOG_D(FLEXRAN_AGENT,"Serilized the enb mac stats reply (size %d)\n", *size);
+
+ return buffer;
+
+ error :
+ LOG_E(FLEXRAN_AGENT,"errno %d occured\n",err_code);
+
+ return NULL;
+}
+
+Protocol__FlexranMessage *flexran_agent_handle_timed_task(void *args) {
+ err_code_t err_code;
+ flexran_agent_timer_args_t *timer_args = (flexran_agent_timer_args_t *) args;
+
+ Protocol__FlexranMessage *timed_task, *reply_message;
+ timed_task = timer_args->msg;
+ err_code = ((*agent_messages_callback[timed_task->msg_case-1][timed_task->msg_dir-1])(timer_args->mod_id, (void *) timed_task, &reply_message));
+ if ( err_code < 0 ){
+ goto error;
+ }
+
+ return reply_message;
+
+ error:
+ LOG_E(FLEXRAN_AGENT,"errno %d occured\n",err_code);
+ return NULL;
+}
+
+Protocol__FlexranMessage* flexran_agent_process_timeout(long timer_id, void* timer_args){
+
+ struct flexran_agent_timer_element_s *found = get_timer_entry(timer_id);
+
+ if (found == NULL ) goto error;
+ LOG_I(FLEXRAN_AGENT, "Found the entry (%p): timer_id is 0x%lx 0x%lx\n", found, timer_id, found->timer_id);
+
+ if (timer_args == NULL)
+ LOG_W(FLEXRAN_AGENT,"null timer args\n");
+
+ return found->cb(timer_args);
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "can't get the timer element\n");
+ return TIMER_ELEMENT_NOT_FOUND;
+}
+
+err_code_t flexran_agent_destroy_flexran_message(Protocol__FlexranMessage *msg) {
+ return ((*message_destruction_callback[msg->msg_case-1])(msg));
+}
diff --git a/openair2/ENB_APP/flexran_agent_net_comm.c b/openair2/ENB_APP/flexran_agent_net_comm.c
new file mode 100644
index 0000000000..6e39d6089f
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_net_comm.c
@@ -0,0 +1,192 @@
+/*
+ * 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.0 (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_net_comm.c
+ * \brief FlexRAN agent network interface abstraction
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#include "flexran_agent_net_comm.h"
+#include "log.h"
+
+flexran_agent_channel_t *agent_channel[NUM_MAX_ENB][FLEXRAN_AGENT_MAX];
+flexran_agent_channel_instance_t channel_instance;
+int flexran_agent_channel_id = 0;
+
+int flexran_agent_msg_send(mid_t mod_id, agent_id_t agent_id, void *data, int size, int priority) {
+ /*Check if agent id is valid*/
+ if (agent_id >= FLEXRAN_AGENT_MAX || agent_id < 0) {
+ goto error;
+ }
+ flexran_agent_channel_t *channel;
+ channel = agent_channel[mod_id][agent_id];
+
+ /*Check if agent has a channel registered*/
+ if (channel == NULL) {
+ goto error;
+ }
+
+ return channel->msg_send(data, size, priority, channel->channel_info);
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "No channel registered for agent with id %d\n", agent_id);
+ return -1;
+}
+
+int flexran_agent_msg_recv(mid_t mod_id, agent_id_t agent_id, void **data, int *size, int *priority) {
+ /*Check if agent id is valid*/
+ if (agent_id >= FLEXRAN_AGENT_MAX || agent_id < 0) {
+ goto error;
+ }
+ flexran_agent_channel_t *channel;
+ channel = agent_channel[mod_id][agent_id];
+
+ /*Check if agent has a channel registered*/
+ if (channel == NULL) {
+ goto error;
+ }
+
+ return channel->msg_recv(data, size, priority, channel->channel_info);
+
+ error:
+ LOG_E(FLEXRAN_AGENT, "No channel registered for agent with id %d\n", agent_id);
+ return -1;
+}
+
+int flexran_agent_register_channel(mid_t mod_id, flexran_agent_channel_t *channel, agent_id_t agent_id) {
+ int i;
+
+ if (channel == NULL) {
+ return -1;
+ }
+
+ if (agent_id == FLEXRAN_AGENT_MAX) {
+ for (i = 0; i < FLEXRAN_AGENT_MAX; i++) {
+ agent_channel[mod_id][i] = channel;
+ }
+ } else {
+ agent_channel[mod_id][agent_id] = channel;
+ }
+ return 0;
+}
+
+void flexran_agent_unregister_channel(mid_t mod_id, agent_id_t agent_id) {
+ int i;
+
+ if (agent_id == FLEXRAN_AGENT_MAX) {
+ for (i = 0; i < FLEXRAN_AGENT_MAX; i++) {
+ agent_channel[mod_id][i] = NULL;
+ }
+ } else {
+ agent_channel[mod_id][agent_id] = NULL;
+ }
+}
+
+int flexran_agent_create_channel(void *channel_info,
+ int (*msg_send)(void *data, int size, int priority, void *channel_info),
+ int (*msg_recv)(void **data, int *size, int *priority, void *channel_info),
+ void (*release)(flexran_agent_channel_t *channel)) {
+
+ int channel_id = ++flexran_agent_channel_id;
+ flexran_agent_channel_t *channel = (flexran_agent_channel_t *) malloc(sizeof(flexran_agent_channel_t));
+ channel->channel_id = channel_id;
+ channel->channel_info = channel_info;
+ channel->msg_send = msg_send;
+ channel->msg_recv = msg_recv;
+ channel->release = release;
+
+ /*element should be a real pointer*/
+ RB_INSERT(flexran_agent_channel_map, &channel_instance.flexran_agent_head, channel);
+
+ LOG_I(FLEXRAN_AGENT,"Created a new channel with id 0x%lx\n", channel->channel_id);
+
+ return channel_id;
+}
+
+int flexran_agent_destroy_channel(int channel_id) {
+ int i, j;
+
+ /*Check to see if channel exists*/
+ struct flexran_agent_channel_s *e = NULL;
+ struct flexran_agent_channel_s search;
+ memset(&search, 0, sizeof(struct flexran_agent_channel_s));
+
+ e = RB_FIND(flexran_agent_channel_map, &channel_instance.flexran_agent_head, &search);
+
+ if (e == NULL) {
+ return -1;
+ }
+
+ /*Unregister the channel from all agents*/
+ for (i = 0; i < NUM_MAX_ENB; i++) {
+ for (j = 0; j < FLEXRAN_AGENT_MAX; j++) {
+ if (agent_channel[i][j] != NULL) {
+ if (agent_channel[i][j]->channel_id == e->channel_id) {
+ agent_channel[i][j] == NULL;
+ }
+ }
+ }
+ }
+
+ /*Remove the channel from the tree and free memory*/
+ RB_REMOVE(flexran_agent_channel_map, &channel_instance.flexran_agent_head, e);
+ e->release(e);
+ free(e);
+
+ return 0;
+}
+
+err_code_t flexran_agent_init_channel_container(void) {
+ int i, j;
+ LOG_I(FLEXRAN_AGENT, "init RB tree for channel container\n");
+
+ RB_INIT(&channel_instance.flexran_agent_head);
+
+ for (i = 0; i < NUM_MAX_ENB; i++) {
+ for (j = 0; j < FLEXRAN_AGENT_MAX; j++) {
+ agent_channel[i][j] == NULL;
+ }
+ }
+
+ return 0;
+}
+
+RB_GENERATE(flexran_agent_channel_map, flexran_agent_channel_s, entry, flexran_agent_compare_channel);
+
+int flexran_agent_compare_channel(struct flexran_agent_channel_s *a, struct flexran_agent_channel_s *b) {
+ if (a->channel_id < b->channel_id) return -1;
+ if (a->channel_id > b->channel_id) return 1;
+
+ // equal timers
+ return 0;
+}
+
+flexran_agent_channel_t * get_channel(int channel_id) {
+
+ struct flexran_agent_channel_s search;
+ memset(&search, 0, sizeof(struct flexran_agent_channel_s));
+ search.channel_id = channel_id;
+
+ return RB_FIND(flexran_agent_channel_map, &channel_instance.flexran_agent_head, &search);
+
+}
diff --git a/openair2/ENB_APP/flexran_agent_net_comm.h b/openair2/ENB_APP/flexran_agent_net_comm.h
new file mode 100644
index 0000000000..e4aa854c70
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_net_comm.h
@@ -0,0 +1,81 @@
+/*
+ * 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.0 (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_net_comm.h
+ * \brief FlexRAN agent network interface abstraction
+ * \autho Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+#ifndef FLEXRAN_AGENT_NET_COMM_H_
+#define FLEXRAN_AGENT_NET_COMM_H_
+
+#include "flexran_agent_defs.h"
+
+#include "tree.h"
+
+/*Channel related information used for Tx/Rx of protocol messages*/
+typedef struct flexran_agent_channel_s {
+ RB_ENTRY(flexran_agent_channel_s) entry;
+int channel_id;
+void *channel_info;
+/*Callbacks for channel message Tx and Rx*/
+int (*msg_send)(void *data, int size, int priority, void *channel_info);
+int (*msg_recv)(void **data, int *size, int *priority, void *channel_info);
+void (*release)(struct flexran_agent_channel_s *channel);
+} flexran_agent_channel_t;
+
+typedef struct flexran_agent_channel_instance_s{
+ RB_HEAD(flexran_agent_channel_map, flexran_agent_channel_s) flexran_agent_head;
+} flexran_agent_channel_instance_t;
+
+/*Send and receive messages using the channel registered for a specific agent*/
+int flexran_agent_msg_send(mid_t mod_id, agent_id_t agent_id, void *data, int size, int priority);
+int flexran_agent_msg_recv(mid_t mod_id, agent_id_t agent_id, void **data, int *size, int *priority);
+
+/*Register a channel to an agent. Use FLEXRAN_AGENT_MAX to register the
+ *same channel to all agents*/
+int flexran_agent_register_channel(mid_t mod_id, flexran_agent_channel_t *channel, agent_id_t agent_id);
+
+/*Unregister the current channel of an agent. Use FLEXRAN_AGENT_MAX to unregister all channels*/
+void flexran_agent_unregister_channel(mid_t mod_id, agent_id_t agent_id);
+
+/*Create a new channel. Returns the id of the new channel or negative number otherwise*/
+int flexran_agent_create_channel(void *channel_info,
+ int (*msg_send)(void *data, int size, int priority, void *channel_info),
+ int (*msg_recv)(void **data, int *size, int *priority, void *channel_info),
+ void (*release)(flexran_agent_channel_t *channel));
+
+/*Unregister a channel from all agents and destroy it. Returns 0 in case of success*/
+int flexran_agent_destroy_channel(int channel_id);
+
+/*Return an agent communication channel based on its id*/
+flexran_agent_channel_t * get_channel(int channel_id);
+
+/*Should be called before performing any channel operations*/
+err_code_t flexran_agent_init_channel_container(void);
+
+int flexran_agent_compare_channel(struct flexran_agent_channel_s *a, struct flexran_agent_channel_s *b);
+
+/* RB_PROTOTYPE is for .h files */
+RB_PROTOTYPE(flexran_agent_channel_map, flexran_agent_channel_s, entry, flexran_agent_compare_channel);
+
+#endif /*FLEXRAN_AGENT_COMM_H_*/
diff --git a/openair2/ENB_APP/flexran_agent_task_manager.c b/openair2/ENB_APP/flexran_agent_task_manager.c
new file mode 100644
index 0000000000..eaa6a58af8
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_task_manager.c
@@ -0,0 +1,304 @@
+/*
+ * 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.0 (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_task_manager.h
+ * \brief Implementation of scheduled tasks manager for the FlexRAN agent
+ * \author Xenofon Foukas
+ * \date January 2016
+ * \version 0.1
+ * \email: x.foukas@sms.ed.ac.uk
+ * @ingroup _mac
+ */
+
+#include
+#include
+#include
+
+#include "flexran_agent_task_manager.h"
+#include "flexran_agent_common.c"
+
+
+/* Util macros */
+#define LEFT(x) (2 * (x) + 1)
+#define RIGHT(x) (2 * (x) + 2)
+#define PARENT(x) ((x - 1) / 2)
+
+flexran_agent_task_t *flexran_agent_task_create(Protocol__FlexranMessage *msg,
+ uint16_t frame_num, uint8_t subframe_num) {
+ flexran_agent_task_t *task = NULL;
+ task = malloc(sizeof(flexran_agent_task_t));
+
+ if (task == NULL)
+ goto error;
+
+ task->frame_num = frame_num;
+ task->subframe_num = subframe_num;
+ task->task = msg;
+
+ return task;
+
+ error:
+ return NULL;
+}
+
+void flexran_agent_task_destroy(flexran_agent_task_t *task) {
+ if (task == NULL)
+ return;
+
+ /* TODO: must free the task properly */
+ free(task->task);
+ free(task);
+}
+
+flexran_agent_task_queue_t *flexran_agent_task_queue_init(mid_t mod_id, size_t capacity,
+ int (*cmp)(mid_t mod_id, const flexran_agent_task_t *t1,
+ const flexran_agent_task_t *t2)) {
+ flexran_agent_task_queue_t *queue = NULL;
+
+ queue = malloc(sizeof(flexran_agent_task_queue_t));
+ if (queue == NULL)
+ goto error;
+
+ /* If no comparator was given, use the default one */
+ if (cmp == NULL)
+ queue->cmp = _flexran_agent_task_queue_cmp;
+ else
+ queue->cmp = cmp;
+
+ queue->mod_id = mod_id;
+
+ queue->first_frame = 0;
+ queue->first_subframe = 0;
+
+ queue->task = malloc(capacity * sizeof(flexran_agent_task_t *));
+ if (queue->task == NULL)
+ goto error;
+
+ queue->count = 0;
+ queue->capacity = capacity;
+
+ queue->mutex = malloc(sizeof(pthread_mutex_t));
+ if (queue->mutex == NULL)
+ goto error;
+ if (pthread_mutex_init(queue->mutex, NULL))
+ goto error;
+
+ return queue;
+
+ error:
+ if (queue != NULL) {
+ free(queue->mutex);
+ free(queue->task);
+ free(queue);
+ }
+ return NULL;
+}
+
+flexran_agent_task_queue_t *flexran_agent_task_queue_default_init(mid_t mod_id) {
+ return flexran_agent_task_queue_init(mod_id, DEFAULT_CAPACITY, NULL);
+}
+
+void flexran_agent_task_queue_destroy(flexran_agent_task_queue_t *queue) {
+ int i;
+
+ if (queue == NULL)
+ return;
+
+ for (i = 0; i < queue->count; i++) {
+ flexran_agent_task_destroy(queue->task[i]);
+ }
+ free(queue->task);
+ free(queue->mutex);
+ free(queue);
+}
+
+int flexran_agent_task_queue_put(flexran_agent_task_queue_t *queue, flexran_agent_task_t *task) {
+ size_t i;
+ flexran_agent_task_t *tmp = NULL;
+ int realloc_status, err_code;
+
+ if (pthread_mutex_lock(queue->mutex)) {
+ /*TODO*/
+ err_code = -1;
+ goto error;
+ }
+
+ if (queue->count >= queue->capacity) {
+ /*TODO: need to call realloc heap*/
+ realloc_status = _flexran_agent_task_queue_realloc_heap(queue);
+ if (realloc_status != HEAP_OK) {
+ err_code = realloc_status;
+ goto error;
+ }
+ }
+
+ queue->task[queue->count] = task;
+ i = queue->count;
+ queue->count++;
+ /*Swap elements to maintain heap properties*/
+ while(i > 0 && queue->cmp(queue->mod_id, queue->task[i], queue->task[PARENT(i)]) > 0) {
+ tmp = queue->task[i];
+ queue->task[i] = queue->task[PARENT(i)];
+ queue->task[PARENT(i)] = tmp;
+ i = PARENT(i);
+ }
+
+ if (pthread_mutex_unlock(queue->mutex)) {
+ // LOG_E(MAC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+ exit(1);
+ }
+ return 0;
+
+ error:
+ /*TODO*/
+ return err_code;
+}
+
+
+int flexran_agent_task_queue_get_current_task(flexran_agent_task_queue_t *queue, flexran_agent_task_t **task) {
+ int err_code;
+
+ if (pthread_mutex_lock(queue->mutex)) {
+ /*TODO*/
+ err_code = -1;
+ goto error;
+ }
+
+ if (queue->count < 1) {
+ /* Priority Queue is empty */
+ err_code = HEAP_EMPTY;
+ goto error;
+ }
+
+ /* Find current frame and subframe number */
+ uint16_t curr_frame = flexran_get_current_frame(queue->mod_id);
+ uint8_t curr_subframe = flexran_get_current_subframe(queue->mod_id);
+
+ /* If no task is scheduled for the current subframe, return without any task */
+ if(queue->task[0]->frame_num != curr_frame || queue->task[0]->subframe_num != curr_subframe) {
+ *task = NULL;
+ return 0;
+ }
+ /* Otherwise, the first task should be returned */
+ *task = queue->task[0];
+ queue->task[0] = queue->task[queue->count-1];
+ queue->count--;
+ /* Restore heap property */
+ _flexran_agent_task_queue_heapify(queue, 0);
+
+ /*If queue has no element*/
+ if (queue->count < 1) {
+ queue->first_frame = 0;
+ queue->first_subframe = 0;
+ } else {
+ queue->first_frame = queue->task[0]->frame_num;
+ queue->first_subframe = queue->task[0]->subframe_num;
+ }
+
+ if (pthread_mutex_unlock(queue->mutex)) {
+ // LOG_E(MAC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+ exit(1);
+ }
+ return HEAP_OK;
+
+ error:
+ /*TODO*/
+ return err_code;
+}
+
+/*Warning: Internal function. Should not be called as API function. Not thread safe*/
+void _flexran_agent_task_queue_heapify(flexran_agent_task_queue_t *queue, size_t idx) {
+ /* left index, right index, largest */
+ flexran_agent_task_t *tmp = NULL;
+ size_t l_idx, r_idx, lrg_idx;
+
+ l_idx = LEFT(idx);
+ r_idx = RIGHT(idx);
+
+ /* Left child exists, compare left child with its parent */
+ if (l_idx < queue->count && queue->cmp(queue->mod_id, queue->task[l_idx], queue->task[idx]) > 0) {
+ lrg_idx = l_idx;
+ } else {
+ lrg_idx = idx;
+ }
+
+ /* Right child exists, compare right child with the largest element */
+ if (r_idx < queue->count && queue->cmp(queue->mod_id, queue->task[r_idx], queue->task[lrg_idx]) > 0) {
+ lrg_idx = r_idx;
+ }
+
+ /* At this point largest element was determined */
+ if (lrg_idx != idx) {
+ /* Swap between the index at the largest element */
+ tmp = queue->task[lrg_idx];
+ queue->task[lrg_idx] = queue->task[idx];
+ queue->task[idx] = tmp;
+ /* Heapify again */
+ _flexran_agent_task_queue_heapify(queue, lrg_idx);
+ }
+}
+
+/*Warning: Internal function. Should not be called as API function. Not thread safe*/
+int _flexran_agent_task_queue_realloc_heap(flexran_agent_task_queue_t *queue) {
+ flexran_agent_task_t **resized_task_heap;
+ if (queue->count >= queue->capacity) {
+ size_t task_size = sizeof(flexran_agent_task_t);
+
+ resized_task_heap = realloc(queue->task, (2*queue->capacity) * task_size);
+ if (resized_task_heap != NULL) {
+ queue->capacity *= 2;
+ queue->task = (flexran_agent_task_t **) resized_task_heap;
+ return HEAP_OK;
+ } else return HEAP_REALLOCERROR;
+ }
+ return HEAP_NOREALLOC;
+}
+
+int _flexran_agent_task_queue_cmp(mid_t mod_id, const flexran_agent_task_t *t1, const flexran_agent_task_t *t2) {
+ if ((t1->frame_num == t2->frame_num) && (t1->subframe_num == t2->subframe_num))
+ return 0;
+
+ uint16_t curr_frame = flexran_get_current_frame(mod_id);
+ uint8_t curr_subframe = flexran_get_current_subframe(mod_id);
+
+ int f_offset, sf_offset, tmp1, tmp2;
+
+ /*Check if the offsets have the same sign and compare the tasks position frame-wise*/
+ tmp1 = t1->frame_num - curr_frame;
+ tmp2 = t2->frame_num - curr_frame;
+ if ((tmp1 >= 0) ^ (tmp2 < 0)) {
+ f_offset = tmp2 - tmp1;
+ }
+ else {
+ f_offset = tmp1 - tmp2;
+ }
+ /*Do the same for the subframe*/
+ tmp1 = t1->subframe_num - curr_subframe;
+ tmp2 = t2->subframe_num - curr_subframe;
+ if ((tmp1 >= 0) ^ (tmp2 < 0))
+ sf_offset = tmp2 - tmp1;
+ else
+ sf_offset = tmp1 - tmp2;
+
+ /*Subframe position matters only if f_offset is 0. Multiply f_offset by 100
+ to be the only comparisson parameter in all other cases */
+ return f_offset*100 + sf_offset;
+}
diff --git a/openair2/ENB_APP/flexran_agent_task_manager.h b/openair2/ENB_APP/flexran_agent_task_manager.h
new file mode 100644
index 0000000000..1b14f1f6f6
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_task_manager.h
@@ -0,0 +1,156 @@
+/*
+ * 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.0 (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_task_manager.h
+ * \brief Implementation of scheduled tasks manager for the FlexRAN agent
+ * \author Xenofon Foukas
+ * \date January 2016
+ * \version 0.1
+ * \email: x.foukas@sms.ed.ac.uk
+ * @ingroup _mac
+ */
+
+#ifndef FLEXRAN_AGENT_TASK_MANAGER_
+#define FLEXRAN_AGENT_TASK_MANAGER_
+
+#include
+#include
+
+#include "flexran.pb-c.h"
+
+#include "flexran_agent_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEFAULT_CAPACITY 512
+
+/**
+ * The structure containing the enb agent task to be executed
+ */
+typedef struct flexran_agent_task_s {
+ /* The frame in which the task needs to be executed */
+ uint16_t frame_num;
+ /* The subframe in which the task needs to be executed */
+ uint8_t subframe_num;
+ /* The task to be executed in the form of a Protocol__FlexranMessage */
+ Protocol__FlexranMessage *task;
+} flexran_agent_task_t;
+
+/**
+ * Priority Queue Structure for tasks
+ */
+typedef struct flexran_agent_task_queue_s {
+ mid_t mod_id;
+ /* The amount of allocated memory for agent tasks in the heap*/
+ volatile size_t capacity;
+ /* The actual size of the tasks heap at a certain time */
+ volatile size_t count;
+ /* The earliest frame that has a pending task */
+ volatile uint16_t first_frame;
+ /* The earliest subframe within the frame that has a pending task */
+ volatile uint8_t first_subframe;
+ /* An array of prioritized tasks stored in a heap */
+ flexran_agent_task_t **task;
+ /* A pointer to a comparator function, used to prioritize elements */
+ int (*cmp)(mid_t mod_id, const flexran_agent_task_t *t1, const flexran_agent_task_t *t2);
+ pthread_mutex_t *mutex;
+} flexran_agent_task_queue_t;
+
+typedef enum {
+ HEAP_OK = 0,
+ HEAP_EMPTY,
+ HEAP_FAILED,
+ HEAP_REALLOCERROR,
+ HEAP_NOREALLOC,
+ HEAP_FATAL,
+} heapstatus_e;
+
+/**
+ * Allocate memory for a task in the queue
+ */
+flexran_agent_task_t *flexran_agent_task_create(Protocol__FlexranMessage *msg,
+ uint16_t frame_num, uint8_t subframe_num);
+
+/**
+ * Free memory for a task of the queue
+ */
+void flexran_agent_task_destroy(flexran_agent_task_t *task);
+
+/**
+ * Allocate initial memory for storing the tasks
+ */
+ flexran_agent_task_queue_t *flexran_agent_task_queue_init(mid_t mod_id, size_t capacity,
+ int (*cmp)(mid_t mod_id, const flexran_agent_task_t *t1,
+ const flexran_agent_task_t *t2));
+
+/**
+ * Allocate initial memory for storing the tasks using default parameters
+ */
+flexran_agent_task_queue_t *flexran_agent_task_queue_default_init(mid_t mod_id);
+
+/**
+ * De-allocate memory for the tasks queue
+ */
+void flexran_agent_task_queue_destroy(flexran_agent_task_queue_t *queue);
+
+/**
+ * Insert task into the queue
+ */
+int flexran_agent_task_queue_put(flexran_agent_task_queue_t *queue, flexran_agent_task_t *task);
+
+/**
+ * Remove the task with the highest priority from the queue
+ * task becomes NULL if there is no task for the current frame and subframe
+ */
+int flexran_agent_task_queue_get_current_task(flexran_agent_task_queue_t *queue, flexran_agent_task_t **task);
+
+/**
+ * Check if the top priority task is for a specific frame and subframe
+ */
+int flexran_agent_task_queue_has_upcoming_task (flexran_agent_task_queue_t *queue,
+ const uint16_t frame, const uint8_t subframe);
+
+/**
+ * Restructure heap after modifications
+ */
+void _flexran_agent_task_queue_heapify(flexran_agent_task_queue_t *queue, size_t idx);
+
+/**
+ * Reallocate memory once the heap reaches max size
+ */
+int _flexran_agent_task_queue_realloc_heap(flexran_agent_task_queue_t *queue);
+
+/**
+ * Compare two agent tasks based on frame and subframe
+ * returns 0 if tasks t1, t2 have the same priority
+ * return negative value if t1 needs to be executed after t2
+ * return positive value if t1 preceeds t2
+ * Need to give eNB id for the comparisson based on the current frame-subframe
+ */
+ int _flexran_agent_task_queue_cmp(mid_t mod_id, const flexran_agent_task_t *t1, const flexran_agent_task_t *t2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*FLEXRAN_AGENT_TASK_MANAGER_*/
diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c
index 3fbcadafbb..e4252ed500 100644
--- a/openair2/LAYER2/MAC/config.c
+++ b/openair2/LAYER2/MAC/config.c
@@ -70,6 +70,9 @@ void ue_mac_reset(module_id_t module_idP,uint8_t eNB_index)
UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
+//Set BSR Trigger Bmp and remove timer flags
+ UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
+
// stop ongoing RACH procedure
// discard explicitly signaled ra_PreambleIndex and ra_RACH_MaskIndex, if any
@@ -178,8 +181,14 @@ rrc_mac_config_req(
if (logicalChannelConfig->ul_SpecificParameters) {
UE_mac_inst[Mod_idP].scheduling_info.bucket_size[logicalChannelIdentity]=logicalChannelConfig->ul_SpecificParameters->prioritisedBitRate *
logicalChannelConfig->ul_SpecificParameters->bucketSizeDuration; // set the max bucket size
- UE_mac_inst[Mod_idP].scheduling_info.LCGID[logicalChannelIdentity]=*logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup;
- LOG_D(MAC,"[CONFIG][UE %d] LCID %d is attached to the LCGID %d\n",Mod_idP,logicalChannelIdentity,*logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup);
+ if (logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup != NULL) {
+ UE_mac_inst[Mod_idP].scheduling_info.LCGID[logicalChannelIdentity]=*logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup;
+ LOG_D(MAC,"[CONFIG][UE %d] LCID %d is attached to the LCGID %d\n",Mod_idP,logicalChannelIdentity,*logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup);
+ }
+ else {
+ UE_mac_inst[Mod_idP].scheduling_info.LCGID[logicalChannelIdentity] = MAX_NUM_LCGID;
+ }
+ UE_mac_inst[Mod_idP].scheduling_info.LCID_buffer_remain[logicalChannelIdentity] = 0;
} else {
LOG_E(MAC,"[CONFIG][UE %d] LCID %d NULL ul_SpecificParameters\n",Mod_idP,logicalChannelIdentity);
mac_xface->macphy_exit("NULL ul_SpecificParameters");
@@ -212,6 +221,7 @@ rrc_mac_config_req(
} else {
UE_mac_inst[Mod_idP].scheduling_info.maxHARQ_Tx = (uint16_t) MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5;
}
+ mac_xface->phy_config_harq_ue(Mod_idP,0,eNB_index,UE_mac_inst[Mod_idP].scheduling_info.maxHARQ_Tx);
if (mac_MainConfig->ul_SCH_Config->retxBSR_Timer) {
UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer = (uint16_t) mac_MainConfig->ul_SCH_Config->retxBSR_Timer;
@@ -225,12 +235,34 @@ rrc_mac_config_req(
if (mac_MainConfig->ext1 && mac_MainConfig->ext1->sr_ProhibitTimer_r9) {
UE_mac_inst[Mod_idP].scheduling_info.sr_ProhibitTimer = (uint16_t) *mac_MainConfig->ext1->sr_ProhibitTimer_r9;
} else {
- UE_mac_inst[Mod_idP].scheduling_info.sr_ProhibitTimer = (uint16_t) 0;
+ UE_mac_inst[Mod_idP].scheduling_info.sr_ProhibitTimer = 0;
}
+ if (mac_MainConfig->ext2 && mac_MainConfig->ext2->mac_MainConfig_v1020) {
+ if (mac_MainConfig->ext2->mac_MainConfig_v1020->extendedBSR_Sizes_r10) {
+ UE_mac_inst[Mod_idP].scheduling_info.extendedBSR_Sizes_r10 = (uint16_t) *mac_MainConfig->ext2->mac_MainConfig_v1020->extendedBSR_Sizes_r10;
+ } else {
+ UE_mac_inst[Mod_idP].scheduling_info.extendedBSR_Sizes_r10 = (uint16_t)0;
+ }
+ if (mac_MainConfig->ext2->mac_MainConfig_v1020->extendedPHR_r10) {
+ UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = (uint16_t) *mac_MainConfig->ext2->mac_MainConfig_v1020->extendedPHR_r10;
+ } else {
+ UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = (uint16_t)0;
+ }
+ } else {
+ UE_mac_inst[Mod_idP].scheduling_info.extendedBSR_Sizes_r10 = (uint16_t)0;
+ UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = (uint16_t)0;
+ }
#endif
- UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_SF = get_sf_periodicBSRTimer(UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_Timer);
- UE_mac_inst[Mod_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer);
+ UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING;
+ UE_mac_inst[Mod_idP].scheduling_info.retxBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING;
+
+ UE_mac_inst[Mod_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
+
+ LOG_D(MAC,"[UE %d]: periodic BSR %d (SF), retx BSR %d (SF)\n",
+ Mod_idP,
+ UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_SF,
+ UE_mac_inst[Mod_idP].scheduling_info.retxBSR_SF);
UE_mac_inst[Mod_idP].scheduling_info.drx_config = mac_MainConfig->drx_Config;
UE_mac_inst[Mod_idP].scheduling_info.phr_config = mac_MainConfig->phr_Config;
@@ -252,6 +284,7 @@ rrc_mac_config_req(
UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_SF = get_sf_perioidicPHR_Timer(UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_Timer);
UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_SF = get_sf_prohibitPHR_Timer(UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_Timer);
UE_mac_inst[Mod_idP].scheduling_info.PathlossChange_db = get_db_dl_PathlossChange(UE_mac_inst[Mod_idP].scheduling_info.PathlossChange);
+ UE_mac_inst[Mod_idP].PHR_reporting_active = 0;
LOG_D(MAC,"[UE %d] config PHR (%d): periodic %d (SF) prohibit %d (SF) pathlosschange %d (db) \n",
Mod_idP,
(mac_MainConfig->phr_Config)?mac_MainConfig->phr_Config->present:-1,
diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h
index 2235c3e1c4..15c0f3fb0e 100644
--- a/openair2/LAYER2/MAC/defs.h
+++ b/openair2/LAYER2/MAC/defs.h
@@ -133,10 +133,18 @@
/*!\brief maximum value for channel quality indicator */
#define MAX_CQI_VALUE 15
+/*!\brief value for indicating BSR Timer is not running */
+#define MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF)
#define LCID_EMPTY 0
#define LCID_NOT_EMPTY 1
+/*!\brief minimum RLC PDU size to be transmitted = min RLC Status PDU or RLC UM PDU SN 5 bits */
+#define MIN_RLC_PDU_SIZE (2)
+
+/*!\brief minimum MAC data needed for transmitting 1 min RLC PDU size + 1 byte MAC subHeader */
+#define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE)
+
/*
* eNB part
*/
@@ -222,11 +230,10 @@ typedef struct {
typedef BSR_SHORT BSR_TRUNCATED;
/*!\brief mac control element: long buffer status report for all logical channel group ID*/
typedef struct {
- uint32_t Buffer_size3:6;
- uint32_t Buffer_size2:6;
- uint32_t Buffer_size1:6;
- uint32_t Buffer_size0:6;
- uint32_t padding:8;
+ uint8_t Buffer_size3:6;
+ uint8_t Buffer_size2:6;
+ uint8_t Buffer_size1:6;
+ uint8_t Buffer_size0:6;
} __attribute__((__packed__))BSR_LONG;
#define BSR_LONG_SIZE (sizeof(BSR_LONG))
@@ -336,6 +343,12 @@ typedef struct {
#define SHORT_BSR 29
/*!\brief LCID of long BSR for ULSCH */
#define LONG_BSR 30
+/*!\bitmaps for BSR Triggers */
+#define BSR_TRIGGER_NONE (0) /* No BSR Trigger */
+#define BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */
+#define BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */
+#define BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */
+
/*! \brief Downlink SCH PDU Structure */
typedef struct {
@@ -462,6 +475,13 @@ typedef struct {
//
uint32_t total_ulsch_pdus_rx;
+
+ /// MAC agent-related stats
+ /// total number of scheduling decisions
+ int sched_decisions;
+ /// missed deadlines
+ int missed_deadlines;
+
} eNB_STATS;
/*! \brief eNB statistics for the connected UEs*/
typedef struct {
@@ -602,6 +622,12 @@ typedef struct {
/// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received)
boolean_t configured;
+ /// MCS from last scheduling
+ uint8_t mcs[8];
+
+ /// TPC from last scheduling
+ uint8_t oldTPC[8];
+
// PHY interface info
/// DCI format for DLSCH
@@ -945,8 +971,12 @@ typedef enum {
typedef struct {
/// buffer status for each lcgid
uint8_t BSR[MAX_NUM_LCGID]; // should be more for mesh topology
- /// keep the number of bytes in rlc buffer for each lcid
- uint16_t BSR_bytes[MAX_NUM_LCGID];
+ /// keep the number of bytes in rlc buffer for each lcgid
+ int32_t BSR_bytes[MAX_NUM_LCGID];
+ /// after multiplexing buffer remain for each lcid
+ int32_t LCID_buffer_remain[MAX_NUM_LCID];
+ /// sum of all lcid buffer size
+ uint16_t All_lcid_buffer_size_lastTTI;
/// buffer status for each lcid
uint8_t LCID_status[MAX_NUM_LCID];
/// SR pending as defined in 36.321
@@ -958,11 +988,11 @@ typedef struct {
/// retxBSR-Timer, default value is sf2560
uint16_t retxBSR_Timer;
/// retxBSR_SF, number of subframe before triggering a regular BSR
- int16_t retxBSR_SF;
+ uint16_t retxBSR_SF;
/// periodicBSR-Timer, default to infinity
uint16_t periodicBSR_Timer;
/// periodicBSR_SF, number of subframe before triggering a periodic BSR
- int16_t periodicBSR_SF;
+ uint16_t periodicBSR_SF;
/// default value is 0: not configured
uint16_t sr_ProhibitTimer;
/// sr ProhibitTime running
@@ -987,6 +1017,12 @@ typedef struct {
int16_t prohibitPHR_SF;
///DL Pathloss Change in db
uint16_t PathlossChange_db;
+
+ /// default value is false
+ uint16_t extendedBSR_Sizes_r10;
+ /// default value is false
+ uint16_t extendedPHR_r10;
+
//Bj bucket usage per lcid
int16_t Bj[MAX_NUM_LCID];
// Bucket size per lcid
@@ -995,10 +1031,14 @@ typedef struct {
/*!\brief Top level UE MAC structure */
typedef struct {
uint16_t Node_id;
- /// frame counter
- frame_t frame;
- /// subframe counter
- sub_frame_t subframe;
+ /// RX frame counter
+ frame_t rxFrame;
+ /// RX subframe counter
+ sub_frame_t rxSubframe;
+ /// TX frame counter
+ frame_t txFrame;
+ /// TX subframe counter
+ sub_frame_t txSubframe;
/// C-RNTI of UE
uint16_t crnti;
/// C-RNTI of UE before HO
@@ -1074,6 +1114,13 @@ typedef struct {
uint8_t PHR_reporting_active;
/// power backoff due to power management (as allowed by P-MPRc) for this cell
uint8_t power_backoff_db[NUMBER_OF_eNB_MAX];
+ /// BSR report falg management
+ uint8_t BSR_reporting_active;
+ /// retxBSR-Timer expires flag
+ uint8_t retxBSRTimer_expires_flag;
+ /// periodBSR-Timer expires flag
+ uint8_t periodBSRTimer_expires_flag;
+
/// MBSFN_Subframe Configuration
struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; // FIXME replace 8 by MAX_MBSFN_AREA?
/// number of subframe allocation pattern available for MBSFN sync area
diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c
index 373bfd05cb..c5dc8c88b0 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler.c
@@ -52,12 +52,23 @@
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"
+#if defined(FLEXRAN_AGENT_SB_IF)
+//Agent-related headers
+#include "flexran_agent_extern.h"
+#include "flexran_agent_mac.h"
+#include "flexran_agent_mac_proto.h"
+#endif
+
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
+//efine ENABLE_ENB_AGENT_DL_SCHEDULER
+//#define DISABLE_SF_TRIGGER
+//#define DISABLE_CONT_STATS
+
//#define DEBUG_HEADER_PARSING 1
//#define DEBUG_PACKET_TRACE 1
@@ -94,6 +105,10 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
void *DLSCH_dci=NULL;
int size_bits=0,size_bytes=0;
+#if defined(FLEXRAN_AGENT_SB_IF)
+ Protocol__FlexranMessage *msg;
+#endif
+
LOG_D(MAC,"[eNB %d] Frame %d, Subframe %d, entering MAC scheduler (UE_list->head %d)\n",module_idP, frameP, subframeP,UE_list->head);
start_meas(&eNB_mac_inst[module_idP].eNB_scheduler);
@@ -126,8 +141,17 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
eNB_mac_inst[module_idP].UE_list.UE_sched_ctrl[i].cqi_req_timer++;
+
if (mac_xface->get_eNB_UE_stats(module_idP, CC_id, rnti)==NULL) {
- // mac_remove_ue(module_idP, i, frameP, subframeP);
+ //mac_remove_ue(module_idP, i, frameP, subframeP);
+ //Inform the controller about the UE deactivation. Should be moved to RRC agent in the future
+#if defined(FLEXRAN_AGENT_SB_IF)
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_notify_ue_state_change(module_idP,
+ rnti,
+ PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED);
+ }
+#endif
}
else {
// check uplink failure
@@ -309,7 +333,14 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
-
+
+/* #ifndef DISABLE_SF_TRIGGER */
+/* //Send subframe trigger to the controller */
+/* if (mac_agent_registered[module_idP]) { */
+/* agent_mac_xface[module_idP]->flexran_agent_send_sf_trigger(module_idP); */
+/* } */
+/* #endif */
+
//if (subframeP%5 == 0)
//#ifdef EXMIMO
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP,module_idP);
@@ -363,10 +394,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
(mac_xface->frame_parms->tdd_config == 6)) {
//schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);//,calibration_flag);
}
-
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
-
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
case 1:
@@ -378,12 +425,16 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
case 0:
case 1:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7);
+#ifndef FLEXRAN_AGENT_SB_IF
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#endif
break;
case 6:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8);
+#ifndef FLEXRAN_AGENT_SB_IF
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#endif
break;
default:
@@ -391,8 +442,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,1,5);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
}
break;
@@ -403,8 +472,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
// FDD, normal UL/DLSCH
if (mac_xface->frame_parms->frame_type == FDD) { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,2,6);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
}
break;
@@ -421,8 +508,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
// no break here!
case 5:
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
default:
@@ -431,8 +536,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,3,7);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
}
break;
@@ -456,9 +579,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
// no break here!
case 5:
-
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
- fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+ fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
default:
@@ -468,8 +608,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
if (mac_xface->frame_parms->frame_type == FDD) { //FDD
schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP, frameP, subframeP, mbsfn_status);
fill_DLSCH_dci(module_idP, frameP, subframeP, mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
}
}
@@ -486,15 +644,53 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
if (mac_xface->frame_parms->frame_type == FDD) {
schedule_RA(module_idP,frameP,subframeP,1);
schedule_ulsch(module_idP,frameP,cooperation_flag,5,9);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP, frameP, subframeP, mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
} else if ((mac_xface->frame_parms->tdd_config == 0) || // TDD Config 0
(mac_xface->frame_parms->tdd_config == 6)) { // TDD Config 6
//schedule_ulsch(module_idP,cooperation_flag,subframeP);
+#ifndef FLEXRAN_AGENT_SB_IF
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#endif
} else {
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
}
break;
@@ -512,25 +708,65 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
case 1:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2);
// schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
+#ifndef FLEXRAN_AGENT_SB_IF
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#endif
break;
case 6:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
// schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
+#ifndef FLEXRAN_AGENT_SB_IF
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#endif
break;
case 5:
schedule_RA(module_idP,frameP,subframeP,2);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
case 3:
case 4:
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
default:
@@ -538,8 +774,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,6,0);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
}
break;
@@ -553,13 +807,49 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
case 3:
case 4:
schedule_RA(module_idP,frameP,subframeP,3); // 3 = Msg3 subframeP, not
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
case 5:
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
default:
@@ -567,8 +857,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,7,1);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
}
break;
@@ -587,8 +895,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
// schedule_RA(module_idP,subframeP);
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
default:
@@ -596,8 +922,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,8,2);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
}
break;
@@ -610,29 +954,101 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
case 1:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
schedule_RA(module_idP,frameP,subframeP,7); // 7 = Msg3 subframeP, not
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
case 3:
case 4:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
case 6:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);
//schedule_RA(module_idP,frameP,subframeP);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
case 2:
case 5:
//schedule_RA(module_idP,frameP,subframeP);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
break;
default:
@@ -640,8 +1056,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,9,3);
+#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+ if (mac_agent_registered[module_idP]) {
+ agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+ module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ &msg);
+
+ flexran_apply_dl_scheduling_decisions(module_idP,
+ frameP,
+ subframeP,
+ mbsfn_status,
+ msg);
+ flexran_agent_mac_destroy_dl_config(msg);
+ }
+#endif
}
break;
@@ -654,6 +1088,15 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
for (CC_id=0;CC_idflexran_agent_send_update_mac_stats(module_idP);
+ }
+#endif
+#endif
+
/*
int dummy=0;
for (i=0;
@@ -673,7 +1116,6 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
DCI_pdu[CC_id]->dci_alloc[i].firstCCE,
DCI_pdu[CC_id]->num_pdcch_symbols);
-
LOG_D(MAC,"frameP %d, subframeP %d\n",frameP,subframeP);
*/
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
index 23ba001d4c..e24281b89a 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
@@ -648,7 +648,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un
if (opt_enabled==1) {
trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0],
rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id),
- eNB->subframe,0,0);
+ eNB->frame, eNB->subframe,0,0);
LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n",
module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length);
}
@@ -664,7 +664,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \n",
module_idP,CC_id,frameP,subframeP);
// Get candidate harq_pid from PHY
- mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,0);
+ mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,openair_harq_RA);
if (round>0) {
//RA_template->wait_ack_Msg4++;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
index 312de660a4..fb01532068 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
@@ -311,6 +311,7 @@ schedule_SI(
0xffff,
4,
0xffff,
+ eNB->frame,
eNB->subframe,
0,
0);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
index 3e7f601ef8..399fd701ce 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
@@ -641,6 +641,7 @@ schedule_ue_spec(
switch (mac_xface->get_transmission_mode(module_idP,CC_id,rnti)) {
case 1:
case 2:
+ case 7:
default:
switch (frame_parms[CC_id]->N_RB_DL) {
case 6:
@@ -725,7 +726,8 @@ schedule_ue_spec(
}
break;
-
+ /*
+ // this code is disabled for now - needs to be done properly
case 4:
// if (nb_rb>10) {
((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->ndi1 = 0;
@@ -763,6 +765,7 @@ schedule_ue_spec(
((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dl_power_off = 1;//dl_pow_off[UE_id];
break;
+ */
}
add_ue_dlsch_info(module_idP,
@@ -1106,7 +1109,7 @@ schedule_ue_spec(
if (opt_enabled == 1) {
trace_pdu(1, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
TBS, module_idP, 3, UE_RNTI(module_idP,UE_id),
- eNB->subframe,0,0);
+ eNB->frame, eNB->subframe,0,0);
LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n",
module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), TBS);
}
@@ -1417,8 +1420,9 @@ schedule_ue_spec(
break;
+ /*
+ // disabled for now as this needs to be done properly
case 4:
- // if (nb_rb>10) {
((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->mcs1 = mcs;
((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->ndi1 = 1;
@@ -1426,15 +1430,6 @@ schedule_ue_spec(
((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->TPC = tpc;
- //}
- /* else {
- ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->mcs1 = eNB_UE_stats->DL_cqi[0];
- ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
- ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->ndi1 = 1;
- ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->rv1 = round&3;
- ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->tpmi = 5;
- ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
- }*/
break;
case 5:
@@ -1465,6 +1460,7 @@ schedule_ue_spec(
((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->TPC = tpc;
break;
+ */
}
// Toggle NDI for next time
@@ -1560,6 +1556,8 @@ fill_DLSCH_dci(
case 1:
case 2:
+
+ case 7:
LOG_D(MAC,"[eNB %d] CC_id %d Adding UE %d spec DCI for %d PRBS \n",module_idP, CC_id, UE_id, nb_rb);
if (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.frame_type == TDD) {
@@ -1744,9 +1742,9 @@ fill_DLSCH_dci(
break;
+ /*
case 4:
- //if (nb_rb>10) {
// DCI format 2_2A
((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub);
((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->rah = 0;
@@ -1758,17 +1756,6 @@ fill_DLSCH_dci(
sizeof_DCI2_5MHz_2A_TDD_t,
format2,
0);
- /*}
- else {
- ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub);
- add_ue_spec_dci(DCI_pdu,
- DLSCH_dci,
- rnti,
- sizeof(DCI2_5MHz_2A_L10PRB_TDD_t),
- 2,//aggregation,
- sizeof_DCI2_5MHz_2A_L10PRB_TDD_t,
- format2_2A_L10PRB);
- }*/
break;
case 5:
@@ -1798,6 +1785,7 @@ fill_DLSCH_dci(
format1E_2A_M10PRB,
0);
break;
+ */
}
}
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c
index 383c18f736..1dac7af704 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c
@@ -621,7 +621,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra
if (opt_enabled ==1 ) {
trace_pdu(1, (uint8_t *)eNB_mac_inst[module_idP].common_channels[CC_id].MCH_pdu.payload,
TBS, module_idP, 6, 0xffff, // M_RNTI = 6 in wirehsark
- eNB_mac_inst[module_idP].subframe,0,0);
+ eNB_mac_inst[module_idP].frame, eNB_mac_inst[module_idP].subframe,0,0);
LOG_D(OPT,"[eNB %d][MCH] CC_id %d Frame %d : MAC PDU with size %d\n",
module_idP, CC_id, frameP, TBS);
}
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
index 5d72f6fc9d..ffd9630648 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
@@ -146,7 +146,7 @@ rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP)
return (rnti);
}
- LOG_E(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);
}
@@ -1006,7 +1006,7 @@ void dump_CCE_table(int *CCE_table,const int nCCE,const unsigned short rnti,cons
for (i=0;iUE_template[CC_id][UE_id];
UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
- if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,1) == -1 ) {
+ if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL) == -1 ) {
LOG_W(MAC,"[eNB %d] Scheduler Frame %d, subframeP %d: candidate harq_pid from PHY for UE %d CC %d RNTI %x\n",
module_idP,frameP,subframeP, UE_id, CC_id, rnti);
continue;
diff --git a/openair2/LAYER2/MAC/extern.h b/openair2/LAYER2/MAC/extern.h
index 8726cb1349..aed8424561 100644
--- a/openair2/LAYER2/MAC/extern.h
+++ b/openair2/LAYER2/MAC/extern.h
@@ -43,12 +43,18 @@
//#include "SIMULATION/simulation_defs.h"
#endif //PHY_EMUL
#include "PHY_INTERFACE/defs.h"
+#include "RRC/LITE/defs.h"
extern const uint32_t BSR_TABLE[BSR_TABLE_SIZE];
//extern uint32_t EBSR_Level[63];
+extern const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE];
+//extern uint32_t Extended_BSR_TABLE[63]; ----currently not used
extern UE_MAC_INST *UE_mac_inst;
extern eNB_MAC_INST *eNB_mac_inst;
+extern eNB_RRC_INST *eNB_rrc_inst;
+extern UE_RRC_INST *UE_rrc_inst;
+extern UE_MAC_INST *ue_mac_inst;
extern MAC_RLC_XFACE *Mac_rlc_xface;
extern uint8_t Is_rrc_registered;
diff --git a/openair2/LAYER2/MAC/flexran_agent_mac_proto.h b/openair2/LAYER2/MAC/flexran_agent_mac_proto.h
new file mode 100644
index 0000000000..060e8ab6ca
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_agent_mac_proto.h
@@ -0,0 +1,62 @@
+/*
+ * 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.0 (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_proto.h
+ * \brief MAC functions for FlexRAN agent
+ * \author Xenofon Foukas
+ * \date 2016
+ * \email: x.foukas@sms.ed.ac.uk
+ * \version 0.1
+ * @ingroup _mac
+
+ */
+
+#ifndef __LAYER2_MAC_FLEXRAN_AGENT_MAC_PROTO_H__
+#define __LAYER2_MAC_FLEXRAN_AGENT_MAC_PROTO_H__
+
+#include "flexran_agent_defs.h"
+#include "header.pb-c.h"
+#include "flexran.pb-c.h"
+
+/*
+ * Default scheduler used by the eNB agent
+ */
+void flexran_schedule_ue_spec_default(mid_t mod_id, uint32_t frame, uint32_t subframe,
+ int *mbsfn_flag, Protocol__FlexranMessage **dl_info);
+
+/*
+ * Data plane function for applying the DL decisions of the scheduler
+ */
+void flexran_apply_dl_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag,
+ const Protocol__FlexranMessage *dl_scheduling_info);
+
+/*
+ * Data plane function for applying the UE specific DL decisions of the scheduler
+ */
+void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag,
+ uint32_t n_dl_ue_data, const Protocol__FlexDlData **dl_ue_data);
+
+/*
+ * Data plane function for filling the DCI structure
+ */
+void flexran_fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti, const Protocol__FlexDlDci *dl_dci);
+
+#endif
diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c
new file mode 100644
index 0000000000..ff3ef32bd6
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c
@@ -0,0 +1,537 @@
+/*
+ * 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.0 (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_scheduler_dataplane.c
+ * \brief data plane procedures related to eNB scheduling
+ * \author Xenofon Foukas
+ * \date 2016
+ * \email: x.foukas@sms.ed.ac.uk
+ * \version 0.1
+ * @ingroup _mac
+
+ */
+
+#include "assertions.h"
+#include "PHY/defs.h"
+#include "PHY/extern.h"
+
+#include "SCHED/defs.h"
+#include "SCHED/extern.h"
+
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+#include "LAYER2/MAC/defs.h"
+#include "LAYER2/MAC/proto.h"
+#include "LAYER2/MAC/extern.h"
+#include "LAYER2/MAC/flexran_dci_conversions.h"
+
+#include "UTIL/LOG/log.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
+#include "OCG.h"
+#include "OCG_extern.h"
+
+#include "RRC/LITE/extern.h"
+#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
+
+#include "header.pb-c.h"
+#include "flexran.pb-c.h"
+
+#include "SIMULATION/TOOLS/defs.h" // for taus
+
+
+void flexran_apply_dl_scheduling_decisions(mid_t mod_id,
+ uint32_t frame,
+ uint32_t subframe,
+ int *mbsfn_flag,
+ const Protocol__FlexranMessage *dl_scheduling_info) {
+
+ Protocol__FlexDlMacConfig *mac_config = dl_scheduling_info->dl_mac_config_msg;
+
+ // Check if there is anything to schedule for random access
+ if (mac_config->n_dl_rar > 0) {
+ /*TODO: call the random access data plane function*/
+ }
+
+ // Check if there is anything to schedule for paging/broadcast
+ if (mac_config->n_dl_broadcast > 0) {
+ /*TODO: call the broadcast/paging data plane function*/
+ }
+
+ // Check if there is anything to schedule for the UEs
+ if (mac_config->n_dl_ue_data > 0) {
+ flexran_apply_ue_spec_scheduling_decisions(mod_id, frame, subframe, mbsfn_flag,
+ mac_config->n_dl_ue_data, mac_config->dl_ue_data);
+ }
+
+}
+
+
+void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
+ uint32_t frame,
+ uint32_t subframe,
+ int *mbsfn_flag,
+ uint32_t n_dl_ue_data,
+ const Protocol__FlexDlData **dl_ue_data) {
+
+ uint8_t CC_id;
+ int UE_id;
+ int N_RBG[MAX_NUM_CCs];
+ unsigned char aggregation;
+ mac_rlc_status_resp_t rlc_status;
+ unsigned char ta_len=0;
+ unsigned char header_len = 0, header_len_tmp = 0;
+ unsigned char sdu_lcids[11],offset,num_sdus=0;
+ uint16_t nb_rb,nb_rb_temp,total_nb_available_rb[MAX_NUM_CCs],nb_available_rb;
+ uint16_t TBS,j,sdu_lengths[11],rnti,padding=0,post_padding=0;
+ unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
+ unsigned char round = 0;
+ unsigned char harq_pid = 0;
+
+ LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+ uint16_t sdu_length_total = 0;
+ int mcs;
+ uint16_t min_rb_unit[MAX_NUM_CCs];
+ short ta_update = 0;
+ eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id];
+ UE_list_t *UE_list = &eNB->UE_list;
+ LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
+ int32_t normalized_rx_power, target_rx_power;
+ int32_t tpc=1;
+ static int32_t tpc_accumulated=0;
+ UE_sched_ctrl *ue_sched_ctl;
+
+ int last_sdu_header_len = 0;
+
+ int i;
+
+ Protocol__FlexDlData *dl_data;
+ Protocol__FlexDlDci *dl_dci;
+
+ uint32_t rlc_size, n_lc, lcid;
+
+
+ // For each UE-related command
+ for (i = 0; i < n_dl_ue_data; i++) {
+
+ dl_data = dl_ue_data[i];
+ dl_dci = dl_data->dl_dci;
+
+ CC_id = dl_data->serv_cell_index;
+ frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+
+ rnti = dl_data->rnti;
+ UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]);
+
+ ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+ eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
+
+ round = dl_dci->rv[0];
+ harq_pid = dl_dci->harq_process;
+
+ // If this is a new transmission
+ if (round == 0) {
+ // First we have to deal with the creation of the PDU based on the message instructions
+ rlc_status.bytes_in_buffer = 0;
+
+ TBS = dl_dci->tbs_size[0];
+
+ if (dl_data->n_ce_bitmap > 0) {
+ //Check if there is TA command and set the length appropriately
+ ta_len = (dl_data->ce_bitmap[0] & PROTOCOL__FLEX_CE_TYPE__FLPCET_TA) ? 1 : 0;
+ }
+
+ num_sdus = 0;
+ sdu_length_total = 0;
+
+ if (ta_len > 0) {
+ // Reset the measurement
+ ue_sched_ctl->ta_timer = 20;
+ eNB_UE_stats->timing_advance_update = 0;
+ header_len = ta_len;
+ last_sdu_header_len = ta_len;
+ }
+
+ n_lc = dl_data->n_rlc_pdu;
+ // Go through each one of the channel commands and create SDUs
+ for (i = 0; i < n_lc; i++) {
+ lcid = dl_data->rlc_pdu[i]->rlc_pdu_tb[0]->logical_channel_id;
+ rlc_size = dl_data->rlc_pdu[i]->rlc_pdu_tb[0]->size;
+ LOG_D(MAC,"[TEST] [eNB %d] Frame %d, LCID %d, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
+ mod_id, frame, lcid, CC_id, rlc_size);
+ if (rlc_size > 0) {
+
+ rlc_status = mac_rlc_status_ind(mod_id,
+ rnti,
+ mod_id,
+ frame,
+ ENB_FLAG_YES,
+ MBMS_FLAG_NO,
+ lcid,
+ 0);
+
+ if (rlc_status.bytes_in_buffer > 0) {
+
+ if (rlc_size <= 2) {
+ rlc_size = 3;
+ }
+
+ rlc_status = mac_rlc_status_ind(mod_id,
+ rnti,
+ mod_id,
+ frame,
+ ENB_FLAG_YES,
+ MBMS_FLAG_NO,
+ lcid,
+ rlc_size); // transport block set size
+
+ sdu_lengths[i] = 0;
+
+ LOG_D(MAC, "[TEST] RLC can give %d bytes for LCID %d during second call\n", rlc_status.bytes_in_buffer, lcid);
+
+ if (rlc_status.bytes_in_buffer > 0) {
+
+ sdu_lengths[i] += mac_rlc_data_req(mod_id,
+ rnti,
+ mod_id,
+ frame,
+ ENB_FLAG_YES,
+ MBMS_FLAG_NO,
+ lcid,
+ (char *)&dlsch_buffer[sdu_length_total]);
+
+ LOG_D(MAC,"[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n",mod_id, lcid, CC_id, sdu_lengths[i]);
+ sdu_length_total += sdu_lengths[i];
+ sdu_lcids[i] = lcid;
+
+ UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] += 1;
+ UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[i];
+
+ if (sdu_lengths[i] <= 128) {
+ header_len += 2;
+ last_sdu_header_len = 2;
+ } else {
+ header_len += 3;
+ last_sdu_header_len = 3;
+ }
+ num_sdus++;
+ }
+ }
+ }
+ } // SDU creation end
+
+
+ if (((sdu_length_total + header_len) > 0)) {
+
+ // header_len_tmp = header_len;
+
+ // If we have only a single SDU, header length becomes 1
+ if ((num_sdus + ta_len) == 1) {
+ //if (header_len == 2 || header_len == 3) {
+ header_len = 1;
+ } else {
+ header_len = (header_len - last_sdu_header_len) + 1;
+ }
+
+ // there is a payload
+ if (((sdu_length_total + header_len) > 0)) {
+ // If we need a 1 or 2 bit padding or no padding at all
+ if ((TBS - header_len - sdu_length_total - ta_len) <= 2
+ || (TBS - header_len - sdu_length_total - ta_len) > TBS) { //protect from overflow
+ padding = (TBS - header_len - sdu_length_total - ta_len);
+ post_padding = 0;
+ } else { // The last sdu needs to have a length field, since we add padding
+ padding = 0;
+ header_len = header_len_tmp;
+ post_padding = TBS - sdu_length_total - header_len - ta_len - 1; // 1 is for the postpadding header
+ }
+ }
+
+ ta_update = (ta_len > 0) ? ue_sched_ctl->ta_update : 0;
+
+ // If there is nothing to schedule, just leave
+ if ((sdu_length_total) <= 0) {
+ return;
+ }
+
+ offset = generate_dlsch_header((unsigned char*)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
+ num_sdus, //num_sdus
+ sdu_lengths, //
+ sdu_lcids,
+ 255, // no drx
+ ta_update, // timing advance
+ NULL, // contention res id
+ padding,
+ post_padding);
+
+#ifdef DEBUG_eNB_SCHEDULER
+ LOG_T(MAC,"[eNB %d] First 16 bytes of DLSCH : \n");
+
+ for (i=0; i<16; i++) {
+ LOG_T(MAC,"%x.",dlsch_buffer[i]);
+ }
+
+ LOG_T(MAC,"\n");
+#endif
+ // cycle through SDUs and place in dlsch_buffer
+ memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset],dlsch_buffer,sdu_length_total);
+ // memcpy(&eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]);
+
+ // fill remainder of DLSCH with random data
+ for (j=0; j<(TBS-sdu_length_total-offset); j++) {
+ UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff);
+ }
+
+ //eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset+sdu_lengths[0]+j] = (char)(taus()&0xff);
+ if (opt_enabled == 1) {
+ trace_pdu(1, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
+ TBS, mod_id, 3, UE_RNTI(mod_id, UE_id),
+ eNB->frame, eNB->subframe,0,0);
+ LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n",
+ mod_id, CC_id, frame, UE_RNTI(mod_id,UE_id), TBS);
+ }
+
+ // store stats
+ eNB->eNB_stats[CC_id].dlsch_bytes_tx+=sdu_length_total;
+ eNB->eNB_stats[CC_id].dlsch_pdus_tx+=1;
+ UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->DL_cqi[0];
+
+ UE_list->eNB_UE_stats[CC_id][UE_id].crnti= rnti;
+ UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status=mac_eNB_get_rrc_status(mod_id, rnti);
+ UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid;
+ UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
+
+ //nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
+ //Find the number of resource blocks and set them to the template for retransmissions
+ nb_rb = get_min_rb_unit(mod_id, CC_id);
+ uint16_t stats_tbs = mac_xface->get_TBS_DL(dl_dci->mcs[0], nb_rb);
+
+ while (stats_tbs < TBS) {
+ nb_rb += get_min_rb_unit(mod_id, CC_id);
+ stats_tbs = mac_xface->get_TBS_DL(dl_dci->mcs[0], nb_rb);
+ }
+
+ UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb;
+ UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb;
+ UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=dl_dci->mcs[0];
+ UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=dl_dci->mcs[0];
+ UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS;
+
+ UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes= TBS - sdu_length_total;
+ UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes+= sdu_length_total;
+ UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes+= TBS;
+ UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus+=1;
+
+ //eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->DL_cqi[0]];
+ //eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
+ }
+ } else {
+ // No need to create anything apart of DCI in case of retransmission
+
+ /*TODO: Must add these */
+ // eNB_UE_stats->dlsch_trials[round]++;
+ //UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission+=1;
+ //UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx=nb_rb;
+ //UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx+=nb_rb;
+ //UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx=nCCECC_id];
+ }
+
+ UE_list->UE_template[CC_id][UE_id].oldNDI[dl_dci->harq_process] = dl_dci->ndi[0];
+ eNB_UE_stats->dlsch_mcs1 = dl_dci->mcs[0];
+
+ //Fill the proper DCI of OAI
+ fill_oai_dci(mod_id, CC_id, rnti, dl_dci);
+ }
+}
+
+void fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti,
+ const Protocol__FlexDlDci *dl_dci) {
+
+ void *DLSCH_dci = NULL;
+ DCI_PDU *DCI_pdu;
+
+ unsigned char round = 0;
+ unsigned char harq_pid = 0;
+ LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
+ int size_bits, size_bytes;
+ eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id];
+ UE_list_t *UE_list = &eNB->UE_list;
+ LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+
+ int UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]);
+
+ uint32_t format;
+
+ harq_pid = dl_dci->harq_process;
+ round = dl_dci->rv[0];
+
+ // Note this code is for a specific DCI format
+ DLSCH_dci = (void *)UE_list->UE_template[CC_id][UE_id].DLSCH_DCI[harq_pid];
+ DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu;
+
+ frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+
+ if (dl_dci->has_tpc == 1) {
+ // Check if tpc has been set and reset measurement */
+ if ((dl_dci->tpc == 0) || (dl_dci->tpc == 2)) {
+ eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
+ eNB_UE_stats->Po_PUCCH_update = 0;
+ }
+ }
+
+
+ switch (frame_parms[CC_id]->N_RB_DL) {
+ case 6:
+ if (frame_parms[CC_id]->frame_type == TDD) {
+ if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+ FILL_DCI_TDD_1(DCI1_1_5MHz_TDD_t, DLSCH_dci, dl_dci);
+ size_bytes = sizeof(DCI1_1_5MHz_TDD_t);
+ size_bits = sizeof_DCI1_1_5MHz_TDD_t;
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+ //TODO
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+ //TODO
+ }
+ } else {
+ if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+ FILL_DCI_FDD_1(DCI1_1_5MHz_FDD_t, DLSCH_dci, dl_dci);
+ size_bytes = sizeof(DCI1_1_5MHz_FDD_t);
+ size_bits = sizeof_DCI1_1_5MHz_FDD_t;
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+ //TODO
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+ //TODO
+ }
+ }
+ break;
+ case 25:
+ if (frame_parms[CC_id]->frame_type == TDD) {
+ if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+ FILL_DCI_TDD_1(DCI1_5MHz_TDD_t, DLSCH_dci, dl_dci);
+ size_bytes = sizeof(DCI1_5MHz_TDD_t);
+ size_bits = sizeof_DCI1_5MHz_TDD_t;
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+ //TODO
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+ //TODO
+ }
+ } else {
+ if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+ FILL_DCI_FDD_1(DCI1_5MHz_FDD_t, DLSCH_dci, dl_dci);
+ size_bytes = sizeof(DCI1_5MHz_FDD_t);
+ size_bits = sizeof_DCI1_5MHz_FDD_t;
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+ //TODO
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+ //TODO
+ }
+ }
+ break;
+ case 50:
+ if (frame_parms[CC_id]->frame_type == TDD) {
+ if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+ FILL_DCI_TDD_1(DCI1_10MHz_TDD_t, DLSCH_dci, dl_dci);
+ size_bytes = sizeof(DCI1_10MHz_TDD_t);
+ size_bits = sizeof_DCI1_10MHz_TDD_t;
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+ //TODO
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+ //TODO
+ }
+ } else {
+ if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+ FILL_DCI_FDD_1(DCI1_10MHz_FDD_t, DLSCH_dci, dl_dci);
+ size_bytes = sizeof(DCI1_10MHz_FDD_t);
+ size_bits = sizeof_DCI1_10MHz_FDD_t;
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+ //TODO
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+ //TODO
+ }
+ }
+ break;
+ case 100:
+ if (frame_parms[CC_id]->frame_type == TDD) {
+ if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+ FILL_DCI_TDD_1(DCI1_20MHz_TDD_t, DLSCH_dci, dl_dci);
+ size_bytes = sizeof(DCI1_20MHz_TDD_t);
+ size_bits = sizeof_DCI1_20MHz_TDD_t;
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+ //TODO
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+ //TODO
+ }
+ } else {
+ if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+ FILL_DCI_FDD_1(DCI1_20MHz_FDD_t, DLSCH_dci, dl_dci);
+ size_bytes = sizeof(DCI1_20MHz_FDD_t);
+ size_bits = sizeof_DCI1_20MHz_FDD_t;
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+ //TODO
+ } else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+ //TODO
+ }
+ }
+ break;
+ }
+
+ //Set format to the proper type
+ switch(dl_dci->format) {
+ case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1:
+ format = format1;
+ break;
+ case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1A:
+ format = format1A;
+ break;
+ case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1B:
+ format = format1B;
+ break;
+ case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1C:
+ format = format1C;
+ break;
+ case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D:
+ format = format1E_2A_M10PRB;
+ break;
+ case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2:
+ format = format2;
+ break;
+ case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A:
+ format = format2A;
+ break;
+ case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2B:
+ format = format2B;
+ break;
+ case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_3:
+ format = 3;
+ break;
+ default:
+ /*TODO: Need to deal with unsupported DCI type*/
+ return;
+ }
+
+ add_ue_spec_dci(DCI_pdu,
+ DLSCH_dci,
+ rnti,
+ size_bytes,
+ dl_dci->aggr_level,
+ size_bits,
+ format,
+ 0);
+}
diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c
new file mode 100644
index 0000000000..8975465e77
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c
@@ -0,0 +1,1391 @@
+/*
+ * 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.0 (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_scheduler_dlsch_ue.c
+ * \brief procedures related to eNB for the DLSCH transport channel
+ * \author Xenofon Foukas, Navid Nikaein and Raymond Knopp
+ * \date 2016
+ * \email: x.foukas@sms.ed.ac.uk
+ * \version 0.1
+ * @ingroup _mac
+
+ */
+
+#include "assertions.h"
+#include "PHY/defs.h"
+#include "PHY/extern.h"
+
+#include "SCHED/defs.h"
+#include "SCHED/extern.h"
+
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+#include "LAYER2/MAC/defs.h"
+#include "LAYER2/MAC/proto.h"
+#include "LAYER2/MAC/extern.h"
+#include "UTIL/LOG/log.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
+#include "OCG.h"
+#include "OCG_extern.h"
+
+#include "RRC/LITE/extern.h"
+#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
+
+#include "ENB_APP/flexran_agent_defs.h"
+
+#include "pdcp.h"
+
+#include "header.pb-c.h"
+#include "flexran.pb-c.h"
+#include "flexran_agent_mac.h"
+
+#include "SIMULATION/TOOLS/defs.h" // for taus
+
+#if defined(ENABLE_ITTI)
+# include "intertask_interface.h"
+#endif
+
+#define ENABLE_MAC_PAYLOAD_DEBUG
+
+
+//------------------------------------------------------------------------------
+void
+flexran_schedule_ue_spec_default(mid_t mod_id,
+ uint32_t frame,
+ uint32_t subframe,
+ int *mbsfn_flag,
+ Protocol__FlexranMessage **dl_info)
+//------------------------------------------------------------------------------
+{
+ uint8_t CC_id;
+ int UE_id;
+ int N_RBG[MAX_NUM_CCs];
+ unsigned char aggregation;
+ mac_rlc_status_resp_t rlc_status;
+ unsigned char header_len = 0, header_len_tmp = 0, ta_len = 0;
+ uint16_t nb_rb, nb_rb_temp, total_nb_available_rb[MAX_NUM_CCs], nb_available_rb;
+ uint16_t TBS, j, rnti, padding=0, post_padding=0;
+ unsigned char round = 0;
+ unsigned char harq_pid = 0;
+ void *DLSCH_dci = NULL;
+ uint16_t sdu_length_total = 0;
+ int mcs, mcs_tmp;
+ uint16_t min_rb_unit[MAX_NUM_CCs];
+ eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id];
+ /* TODO: Must move the helper structs to scheduler implementation */
+ UE_list_t *UE_list = &eNB->UE_list;
+ int32_t normalized_rx_power, target_rx_power;
+ int32_t tpc = 1;
+ static int32_t tpc_accumulated=0;
+ UE_sched_ctrl *ue_sched_ctl;
+
+ Protocol__FlexDlData *dl_data[NUM_MAX_UE];
+ int num_ues_added = 0;
+ int channels_added = 0;
+
+ Protocol__FlexDlDci *dl_dci;
+ Protocol__FlexRlcPdu *rlc_pdus[11];
+ uint32_t *ce_bitmap;
+ Protocol__FlexRlcPdu **rlc_pdu;
+ int num_tb;
+ uint32_t ce_flags = 0;
+
+ uint8_t rballoc_sub[25];
+ int i;
+ uint32_t data_to_request;
+ uint32_t dci_tbs;
+ uint8_t ue_has_transmission = 0;
+ uint32_t ndi;
+
+ flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
+
+ if (UE_list->head==-1) {
+ return;
+ }
+
+ start_meas(&eNB->schedule_dlsch);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_IN);
+
+ //weight = get_ue_weight(module_idP,UE_id);
+ aggregation = 2; // set to the maximum aggregation level
+
+ for (CC_id=0; CC_idcommon_channels[CC_id].vrb_map[i] != 0)
+ total_nb_available_rb[CC_id]--;
+
+ N_RBG[CC_id] = flexran_get_N_RBG(mod_id, CC_id);
+
+ // store the global enb stats:
+ eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs;
+ eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb[CC_id];
+ eNB->eNB_stats[CC_id].total_available_prbs += total_nb_available_rb[CC_id];
+ eNB->eNB_stats[CC_id].dlsch_bytes_tx=0;
+ eNB->eNB_stats[CC_id].dlsch_pdus_tx=0;
+ }
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_IN);
+
+ start_meas(&eNB->schedule_dlsch_preprocessor);
+ _dlsch_scheduler_pre_processor(mod_id,
+ frame,
+ subframe,
+ N_RBG,
+ mbsfn_flag);
+ stop_meas(&eNB->schedule_dlsch_preprocessor);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT);
+
+ for (CC_id=0; CC_id0)
+ continue;
+
+ for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
+ rnti = flexran_get_ue_crnti(mod_id, UE_id);
+ ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+
+ if (rnti==NOT_A_RNTI) {
+ LOG_D(MAC,"Cannot find rnti for UE_id %d (num_UEs %d)\n", UE_id,UE_list->num_UEs);
+ // mac_xface->macphy_exit("Cannot find rnti for UE_id");
+ continue;
+ }
+
+ if (flexran_get_ue_crnti(mod_id, UE_id) == NOT_A_RNTI) {
+ LOG_D(MAC,"[eNB] Cannot find UE\n");
+ // mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n");
+ continue;
+ }
+
+ if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) || // no RBs allocated
+ CCE_allocation_infeasible(mod_id, CC_id, 0, subframe, aggregation, rnti)) {
+ LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n",
+ mod_id, frame, UE_id, CC_id);
+ //if(mac_xface->get_transmission_mode(module_idP,rnti)==5)
+ continue; //to next user (there might be rbs availiable for other UEs in TM5
+ // else
+ // break;
+ }
+
+ if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+ set_ue_dai (subframe,
+ flexran_get_subframe_assignment(mod_id, CC_id),
+ UE_id,
+ CC_id,
+ UE_list);
+ //TODO: update UL DAI after DLSCH scheduling
+ //set_ul_DAI(mod_id, UE_id, CC_id, frame, subframe,frame_parms);
+ }
+
+ channels_added = 0;
+
+ // After this point all the UEs will be scheduled
+ dl_data[num_ues_added] = (Protocol__FlexDlData *) malloc(sizeof(Protocol__FlexDlData));
+ protocol__flex_dl_data__init(dl_data[num_ues_added]);
+ dl_data[num_ues_added]->has_rnti = 1;
+ dl_data[num_ues_added]->rnti = rnti;
+ dl_data[num_ues_added]->n_rlc_pdu = 0;
+ dl_data[num_ues_added]->has_serv_cell_index = 1;
+ dl_data[num_ues_added]->serv_cell_index = CC_id;
+
+ nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
+ flexran_get_harq(mod_id, CC_id, UE_id, frame, subframe, &harq_pid, &round);
+ sdu_length_total=0;
+ mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)];
+
+#ifdef EXMIMO
+
+ if (mac_xface->get_transmission_mode(mod_id, CC_id, rnti) == 5) {
+ mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)];
+ mcs = cmin(mcs,16);
+ }
+
+#endif
+
+ // initializing the rb allocation indicator for each UE
+ for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) {
+ UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
+ rballoc_sub[j] = 0;
+ }
+
+ /* LOG_D(MAC,"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", */
+ /* mod_id, frame, UE_id, CC_id, rnti, harq_pid, round, nb_available_rb, */
+ /* eNB_UE_stats->DL_cqi[0], mcs, */
+ /* UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); */
+
+ dl_dci = (Protocol__FlexDlDci*) malloc(sizeof(Protocol__FlexDlDci));
+ protocol__flex_dl_dci__init(dl_dci);
+ dl_data[num_ues_added]->dl_dci = dl_dci;
+
+
+ dl_dci->has_rnti = 1;
+ dl_dci->rnti = rnti;
+ dl_dci->has_harq_process = 1;
+ dl_dci->harq_process = harq_pid;
+
+ /* process retransmission */
+
+ if (round > 0) {
+
+ if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+ UE_list->UE_template[CC_id][UE_id].DAI++;
+ update_ul_dci(mod_id, CC_id, rnti, UE_list->UE_template[CC_id][UE_id].DAI);
+ LOG_D(MAC,"DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n",
+ CC_id, subframe,UE_id,UE_list->UE_template[CC_id][UE_id].DAI);
+ }
+
+ mcs = UE_list->UE_template[CC_id][UE_id].mcs[harq_pid];
+
+ // get freq_allocation
+ nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
+
+ /*TODO: Must add this to FlexRAN agent API */
+ dci_tbs = mac_xface->get_TBS_DL(mcs, nb_rb);
+
+ if (nb_rb <= nb_available_rb) {
+
+ if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
+ for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { // for indicating the rballoc for each sub-band
+ UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
+ }
+ } else {
+ nb_rb_temp = nb_rb;
+ j = 0;
+
+ while((nb_rb_temp > 0) && (j < flexran_get_N_RBG(mod_id, CC_id))) {
+ if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
+ UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
+
+ if((j == flexran_get_N_RBG(mod_id, CC_id) - 1) &&
+ ((flexran_get_N_RB_DL(mod_id, CC_id) == 25)||
+ (flexran_get_N_RB_DL(mod_id, CC_id) == 50))) {
+ nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
+ } else {
+ nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
+ }
+ }
+ j = j + 1;
+ }
+ }
+
+ nb_available_rb -= nb_rb;
+ aggregation = process_ue_cqi(mod_id, UE_id);
+
+ PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
+ PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];
+
+ for(j=0; j < flexran_get_N_RBG(mod_id, CC_id); j++) {
+ PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
+ rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
+ }
+
+ // Keep the old NDI, do not toggle
+ ndi = UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
+ tpc = UE_list->UE_template[CC_id][UE_id].oldTPC[harq_pid];
+ UE_list->UE_template[CC_id][UE_id].mcs[harq_pid] = mcs;
+
+ ue_has_transmission = 1;
+ num_ues_added++;
+ } else {
+ LOG_D(MAC,"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n",
+ mod_id, frame, CC_id, UE_id);
+ ue_has_transmission = 0;
+ }
+ //End of retransmission
+ } else { /* This is a potentially new SDU opportunity */
+ rlc_status.bytes_in_buffer = 0;
+ // Now check RLC information to compute number of required RBs
+ // get maximum TBS size for RLC request
+ //TBS = mac_xface->get_TBS(eNB_UE_stats->DL_cqi[0]<<1,nb_available_rb);
+ TBS = mac_xface->get_TBS_DL(mcs, nb_available_rb);
+ dci_tbs = TBS;
+
+ // check first for RLC data on DCCH
+ // add the length for all the control elements (timing adv, drx, etc) : header + payload
+
+ ta_len = (ue_sched_ctl->ta_update!=0) ? 2 : 0;
+
+ dl_data[num_ues_added]->n_ce_bitmap = 2;
+ dl_data[num_ues_added]->ce_bitmap = (uint32_t *) malloc(sizeof(uint32_t) * 2);
+
+ if (ta_len > 0) {
+ ce_flags |= PROTOCOL__FLEX_CE_TYPE__FLPCET_TA;
+ }
+
+ /*TODO: Add other flags if DRX and other CE are required*/
+
+ // Add the control element flags to the flexran message
+ dl_data[num_ues_added]->ce_bitmap[0] = ce_flags;
+ dl_data[num_ues_added]->ce_bitmap[1] = ce_flags;
+
+ // TODO : Need to prioritize DRBs
+ // Loop through the UE logical channels (DCCH, DCCH1, DTCH for now)
+ for (j = 1; j < NB_RB_MAX; j++) {
+ header_len+=3;
+
+ // Need to see if we have space for data from this channel
+ if (dci_tbs - ta_len - header_len - sdu_length_total > 0) {
+ LOG_D(MAC, "[TEST]Requested %d bytes from RLC buffer on channel %d during first call\n", dci_tbs-ta_len-header_len);
+ //If we have space, we need to see how much data we can request at most (if any available)
+ rlc_status = mac_rlc_status_ind(mod_id,
+ rnti,
+ mod_id,
+ frame,
+ ENB_FLAG_YES,
+ MBMS_FLAG_NO,
+ j,
+ (dci_tbs-ta_len-header_len)); // transport block set size
+
+ //If data are available in channel j
+ if (rlc_status.bytes_in_buffer > 0) {
+ LOG_D(MAC, "[TEST]Have %d bytes in DCCH buffer during first call\n", rlc_status.bytes_in_buffer);
+ //Fill in as much as possible
+ data_to_request = cmin(dci_tbs-ta_len-header_len, rlc_status.bytes_in_buffer);
+ if (data_to_request < 128) { //The header will be one byte less
+ header_len--;
+ }
+ /* if (j == 1 || j == 2) { */
+ /* data_to_request+=0;
+ /* } */
+ LOG_D(MAC, "[TEST]Will request %d from channel %d\n", data_to_request, j);
+ rlc_pdus[channels_added] = (Protocol__FlexRlcPdu *) malloc(sizeof(Protocol__FlexRlcPdu));
+ protocol__flex_rlc_pdu__init(rlc_pdus[channels_added]);
+ rlc_pdus[channels_added]->n_rlc_pdu_tb = 2;
+ rlc_pdus[channels_added]->rlc_pdu_tb = (Protocol__FlexRlcPduTb **) malloc(sizeof(Protocol__FlexRlcPduTb *) * 2);
+ rlc_pdus[channels_added]->rlc_pdu_tb[0] = (Protocol__FlexRlcPduTb *) malloc(sizeof(Protocol__FlexRlcPduTb));
+ protocol__flex_rlc_pdu_tb__init(rlc_pdus[channels_added]->rlc_pdu_tb[0]);
+ rlc_pdus[channels_added]->rlc_pdu_tb[0]->has_logical_channel_id = 1;
+ rlc_pdus[channels_added]->rlc_pdu_tb[0]->logical_channel_id = j;
+ rlc_pdus[channels_added]->rlc_pdu_tb[0]->has_size = 1;
+ rlc_pdus[channels_added]->rlc_pdu_tb[0]->size = data_to_request;
+ rlc_pdus[channels_added]->rlc_pdu_tb[1] = (Protocol__FlexRlcPduTb *) malloc(sizeof(Protocol__FlexRlcPduTb));
+ protocol__flex_rlc_pdu_tb__init(rlc_pdus[channels_added]->rlc_pdu_tb[1]);
+ rlc_pdus[channels_added]->rlc_pdu_tb[1]->has_logical_channel_id = 1;
+ rlc_pdus[channels_added]->rlc_pdu_tb[1]->logical_channel_id = j;
+ rlc_pdus[channels_added]->rlc_pdu_tb[1]->has_size = 1;
+ rlc_pdus[channels_added]->rlc_pdu_tb[1]->size = data_to_request;
+ dl_data[num_ues_added]->n_rlc_pdu++;
+ channels_added++;
+ //Set this to the max value that we might request
+ sdu_length_total += data_to_request;
+ } else {
+ //Take back the assumption of a header for this channel
+ header_len -= 3;
+ } //End rlc_status.bytes_in_buffer <= 0
+ } //end of if dci_tbs - ta_len - header_len > 0
+ } // End of iterating the logical channels
+
+ // Add rlc_pdus to the dl_data message
+ dl_data[num_ues_added]->rlc_pdu = (Protocol__FlexRlcPdu **) malloc(sizeof(Protocol__FlexRlcPdu *) *
+ dl_data[num_ues_added]->n_rlc_pdu);
+ for (i = 0; i < dl_data[num_ues_added]->n_rlc_pdu; i++) {
+ dl_data[num_ues_added]->rlc_pdu[i] = rlc_pdus[i];
+ }
+
+ // there is a payload
+ if (( dl_data[num_ues_added]->n_rlc_pdu > 0)) {
+ // Now compute number of required RBs for total sdu length
+ // Assume RAH format 2
+ // adjust header lengths
+ header_len_tmp = header_len;
+
+ if (header_len == 2 || header_len == 3) { //Only one SDU, remove length field
+ header_len = 1;
+ } else { //Remove length field from the last SDU
+ header_len--;
+ }
+
+ mcs_tmp = mcs;
+ if (mcs_tmp == 0) {
+ nb_rb = 4; // don't let the TBS get too small
+ } else {
+ nb_rb=min_rb_unit[CC_id];
+ }
+
+ LOG_D(MAC,"[TEST]The initial number of resource blocks was %d\n", nb_rb);
+ LOG_D(MAC,"[TEST] The initial mcs was %d\n", mcs_tmp);
+
+ TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb);
+ LOG_D(MAC,"[TEST]The TBS during rate matching was %d\n", TBS);
+
+ while (TBS < (sdu_length_total + header_len + ta_len)) {
+ nb_rb += min_rb_unit[CC_id]; //
+ LOG_D(MAC, "[TEST]Had to increase the number of RBs\n");
+ if (nb_rb > nb_available_rb) { // if we've gone beyond the maximum number of RBs
+ // (can happen if N_RB_DL is odd)
+ TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_available_rb);
+ nb_rb = nb_available_rb;
+ break;
+ }
+
+ TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb);
+ }
+
+ if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
+ LOG_D(MAC, "[TEST]We had the exact number of rbs. Time to fill the rballoc subband\n");
+ for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { // for indicating the rballoc for each sub-band
+ UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
+ }
+ } else {
+ nb_rb_temp = nb_rb;
+ j = 0;
+ LOG_D(MAC, "[TEST]Will only partially fill the bitmap\n");
+ while((nb_rb_temp > 0) && (j < flexran_get_N_RBG(mod_id, CC_id))) {
+ if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
+ UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
+ if ((j == flexran_get_N_RBG(mod_id, CC_id) - 1) &&
+ ((flexran_get_N_RB_DL(mod_id, CC_id) == 25)||
+ (flexran_get_N_RB_DL(mod_id, CC_id) == 50))) {
+ nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id] + 1;
+ } else {
+ nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
+ }
+ }
+ j = j+1;
+ }
+ }
+
+ PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
+ PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];
+
+ for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) {
+ PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
+ }
+
+ // decrease mcs until TBS falls below required length
+ while ((TBS > (sdu_length_total + header_len + ta_len)) && (mcs_tmp > 0)) {
+ mcs_tmp--;
+ TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb);
+ }
+
+ // if we have decreased too much or we don't have enough RBs, increase MCS
+ while ((TBS < (sdu_length_total + header_len + ta_len)) &&
+ ((( ue_sched_ctl->dl_pow_off[CC_id] > 0) && (mcs_tmp < 28)) || ( (ue_sched_ctl->dl_pow_off[CC_id]==0) && (mcs_tmp <= 15)))) {
+ mcs_tmp++;
+ TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb);
+ }
+
+ dci_tbs = TBS;
+ mcs = mcs_tmp;
+
+ aggregation = process_ue_cqi(mod_id,UE_id);
+ dl_dci->has_aggr_level = 1;
+ dl_dci->aggr_level = aggregation;
+
+ UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb;
+
+ if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+ UE_list->UE_template[CC_id][UE_id].DAI++;
+ // printf("DAI update: subframeP %d: UE %d, DAI %d\n",subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].DAI);
+ //#warning only for 5MHz channel
+ update_ul_dci(mod_id, CC_id, rnti, UE_list->UE_template[CC_id][UE_id].DAI);
+ }
+
+ // do PUCCH power control
+ // this is the normalized RX power
+ normalized_rx_power = flexran_get_p0_pucch_dbm(mod_id,UE_id, CC_id); //eNB_UE_stats->Po_PUCCH_dBm;
+ target_rx_power = flexran_get_p0_nominal_pucch(mod_id, CC_id) + 10; //mac_xface->get_target_pucch_rx_power(mod_id, CC_id) + 10;
+
+ // this assumes accumulated tpc
+ // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
+ int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe;
+
+ if (((framex10psubframe+10)<=(frame*10+subframe)) || //normal case
+ ((framex10psubframe>(frame*10+subframe)) && (((10240-framex10psubframe+frame*10+subframe)>=10)))) //frame wrap-around
+ if (flexran_get_p0_pucch_status(mod_id, UE_id, CC_id) == 1) {
+ flexran_update_p0_pucch(mod_id, UE_id, CC_id);
+
+ UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame = frame;
+ UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe = subframe;
+ if (normalized_rx_power>(target_rx_power+1)) {
+ tpc = 0; //-1
+ tpc_accumulated--;
+ } else if (normalized_rx_power<(target_rx_power-1)) {
+ tpc = 2; //+1
+ tpc_accumulated++;
+ } else {
+ tpc = 1; //0
+ }
+ LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
+ mod_id, frame, subframe, harq_pid, tpc,
+ tpc_accumulated, normalized_rx_power, target_rx_power);
+ } // Po_PUCCH has been updated
+ else {
+ tpc = 1; //0
+ } // time to do TPC update
+ else {
+ tpc = 1; //0
+ }
+
+ for(i=0; iframe_parms.N_RBG; i++) {
+ rballoc_sub[i] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][i];
+ }
+
+ // Toggle NDI
+ LOG_D(MAC,"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n",
+ CC_id, frame, subframe, UE_id,
+ UE_list->UE_template[CC_id][UE_id].rnti,harq_pid, UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]);
+ UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]= 1 - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
+ ndi = UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
+
+ UE_list->UE_template[CC_id][UE_id].mcs[harq_pid] = mcs;
+ UE_list->UE_template[CC_id][UE_id].oldTPC[harq_pid] = tpc;
+
+ // Increase the pointer for the number of scheduled UEs
+ num_ues_added++;
+ ue_has_transmission = 1;
+ } else { // There is no data from RLC or MAC header, so don't schedule
+ ue_has_transmission = 0;
+ }
+ } // End of new scheduling
+
+ // If we has transmission or retransmission
+ if (ue_has_transmission) {
+ switch (mac_xface->get_transmission_mode(mod_id, CC_id, rnti)) {
+ case 1:
+ case 2:
+ default:
+ dl_dci->has_res_alloc = 1;
+ dl_dci->res_alloc = 0;
+ dl_dci->has_vrb_format = 1;
+ dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+ dl_dci->has_format = 1;
+ dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1;
+ dl_dci->has_rb_bitmap = 1;
+ dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+ dl_dci->has_rb_shift = 1;
+ dl_dci->rb_shift = 0;
+ dl_dci->n_ndi = 1;
+ dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+ dl_dci->ndi[0] = ndi;
+ dl_dci->n_rv = 1;
+ dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+ dl_dci->rv[0] = round & 3;
+ dl_dci->has_tpc = 1;
+ dl_dci->tpc = tpc;
+ dl_dci->n_mcs = 1;
+ dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+ dl_dci->mcs[0] = mcs;
+ dl_dci->n_tbs_size = 1;
+ dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+ dl_dci->tbs_size[0] = dci_tbs;
+ if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+ dl_dci->has_dai = 1;
+ dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+ }
+ break;
+ case 3:
+ dl_dci->has_res_alloc = 1;
+ dl_dci->res_alloc = 0;
+ dl_dci->has_vrb_format = 1;
+ dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+ dl_dci->has_format = 1;
+ dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A;
+ dl_dci->has_rb_bitmap = 1;
+ dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+ dl_dci->has_rb_shift = 1;
+ dl_dci->rb_shift = 0;
+ dl_dci->n_ndi = 2;
+ dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+ dl_dci->ndi[0] = ndi;
+ dl_dci->ndi[1] = ndi;
+ dl_dci->n_rv = 2;
+ dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+ dl_dci->rv[0] = round & 3;
+ dl_dci->rv[1] = round & 3;
+ dl_dci->has_tpc = 1;
+ dl_dci->tpc = tpc;
+ dl_dci->n_mcs = 2;
+ dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+ dl_dci->mcs[0] = mcs;
+ dl_dci->mcs[1] = mcs;
+ dl_dci->n_tbs_size = 2;
+ dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+ dl_dci->tbs_size[0] = dci_tbs;
+ dl_dci->tbs_size[1] = dci_tbs;
+ if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+ dl_dci->has_dai = 1;
+ dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+ }
+ break;
+ case 4:
+ dl_dci->has_res_alloc = 1;
+ dl_dci->res_alloc = 0;
+ dl_dci->has_vrb_format = 1;
+ dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+ dl_dci->has_format = 1;
+ dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A;
+ dl_dci->has_rb_bitmap = 1;
+ dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+ dl_dci->has_rb_shift = 1;
+ dl_dci->rb_shift = 0;
+ dl_dci->n_ndi = 2;
+ dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+ dl_dci->ndi[0] = ndi;
+ dl_dci->ndi[1] = ndi;
+ dl_dci->n_rv = 2;
+ dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+ dl_dci->rv[0] = round & 3;
+ dl_dci->rv[1] = round & 3;
+ dl_dci->has_tpc = 1;
+ dl_dci->tpc = tpc;
+ dl_dci->n_mcs = 2;
+ dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+ dl_dci->mcs[0] = mcs;
+ dl_dci->mcs[1] = mcs;
+ dl_dci->n_tbs_size = 2;
+ dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+ dl_dci->tbs_size[0] = dci_tbs;
+ dl_dci->tbs_size[1] = dci_tbs;
+ if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+ dl_dci->has_dai = 1;
+ dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+ }
+ break;
+ case 5:
+ dl_dci->has_res_alloc = 1;
+ dl_dci->res_alloc = 0;
+ dl_dci->has_vrb_format = 1;
+ dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+ dl_dci->has_format = 1;
+ dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D;
+ dl_dci->has_rb_bitmap = 1;
+ dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+ dl_dci->has_rb_shift = 1;
+ dl_dci->rb_shift = 0;
+ dl_dci->n_ndi = 1;
+ dl_dci->ndi = 1;
+ dl_dci->ndi[0] = ndi;
+ dl_dci->n_rv = 1;
+ dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+ dl_dci->rv[0] = round & 3;
+ dl_dci->has_tpc = 1;
+ dl_dci->tpc = tpc;
+ dl_dci->n_mcs = 1;
+ dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+ dl_dci->mcs[0] = mcs;
+ dl_dci->n_tbs_size = 1;
+ dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+ dl_dci->tbs_size[0] = dci_tbs;
+ if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+ dl_dci->has_dai = 1;
+ dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+ }
+
+ if(ue_sched_ctl->dl_pow_off[CC_id] == 2) {
+ ue_sched_ctl->dl_pow_off[CC_id] = 1;
+ }
+
+ dl_dci->has_dl_power_offset = 1;
+ dl_dci->dl_power_offset = ue_sched_ctl->dl_pow_off[CC_id];
+ dl_dci->has_precoding_info = 1;
+ dl_dci->precoding_info = 5; // Is this right??
+
+ break;
+ case 6:
+ dl_dci->has_res_alloc = 1;
+ dl_dci->res_alloc = 0;
+ dl_dci->has_vrb_format = 1;
+ dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+ dl_dci->has_format = 1;
+ dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D;
+ dl_dci->has_rb_bitmap = 1;
+ dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+ dl_dci->has_rb_shift = 1;
+ dl_dci->rb_shift = 0;
+ dl_dci->n_ndi = 1;
+ dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+ dl_dci->ndi[0] = ndi;
+ dl_dci->n_rv = 1;
+ dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+ dl_dci->rv[0] = round & 3;
+ dl_dci->has_tpc = 1;
+ dl_dci->tpc = tpc;
+ dl_dci->n_mcs = 1;
+ dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+ dl_dci->mcs[0] = mcs;
+ if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+ dl_dci->has_dai = 1;
+ dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+ }
+
+ dl_dci->has_dl_power_offset = 1;
+ dl_dci->dl_power_offset = ue_sched_ctl->dl_pow_off[CC_id];
+ dl_dci->has_precoding_info = 1;
+ dl_dci->precoding_info = 5; // Is this right??
+ break;
+ }
+ }
+
+ if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+
+ /* TODO */
+ //set_ul_DAI(mod_id, UE_id, CC_id, frame, subframe, frame_parms);
+ }
+ } // UE_id loop
+ } // CC_id loop
+
+ // Add all the dl_data elements to the flexran message
+ (*dl_info)->dl_mac_config_msg->n_dl_ue_data = num_ues_added;
+ (*dl_info)->dl_mac_config_msg->dl_ue_data = (Protocol__FlexDlData **) malloc(sizeof(Protocol__FlexDlData *) * num_ues_added);
+ for (i = 0; i < num_ues_added; i++) {
+ (*dl_info)->dl_mac_config_msg->dl_ue_data[i] = dl_data[i];
+ }
+
+ stop_meas(&eNB->schedule_dlsch);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_OUT);
+}
+
+// This function stores the downlink buffer for all the logical channels
+void _store_dlsch_buffer (module_id_t Mod_id,
+ frame_t frameP,
+ sub_frame_t subframeP)
+{
+
+ int UE_id,i;
+ rnti_t rnti;
+ mac_rlc_status_resp_t rlc_status;
+ UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
+ UE_TEMPLATE *UE_template;
+
+ for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
+
+ UE_template = &UE_list->UE_template[UE_PCCID(Mod_id,UE_id)][UE_id];
+
+ // clear logical channel interface variables
+ UE_template->dl_buffer_total = 0;
+ UE_template->dl_pdus_total = 0;
+
+ for(i=0; i< MAX_NUM_LCID; i++) {
+ UE_template->dl_buffer_info[i]=0;
+ UE_template->dl_pdus_in_buffer[i]=0;
+ UE_template->dl_buffer_head_sdu_creation_time[i]=0;
+ UE_template->dl_buffer_head_sdu_remaining_size_to_send[i]=0;
+ }
+
+ rnti = UE_RNTI(Mod_id,UE_id);
+
+ for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels
+
+ rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 );
+ UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel
+ UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer;
+ UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ;
+ UE_template->dl_buffer_head_sdu_creation_time_max = cmax(UE_template->dl_buffer_head_sdu_creation_time_max,
+ rlc_status.head_sdu_creation_time );
+ UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = rlc_status.head_sdu_remaining_size_to_send;
+ UE_template->dl_buffer_head_sdu_is_segmented[i] = rlc_status.head_sdu_is_segmented;
+ UE_template->dl_buffer_total += UE_template->dl_buffer_info[i];//storing the total dlsch buffer
+ UE_template->dl_pdus_total += UE_template->dl_pdus_in_buffer[i];
+
+#ifdef DEBUG_eNB_SCHEDULER
+
+ /* note for dl_buffer_head_sdu_remaining_size_to_send[i] :
+ * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent
+ */
+ if (UE_template->dl_buffer_info[i]>0)
+ LOG_D(MAC,
+ "[eNB %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n",
+ Mod_id, frameP, subframeP, UE_id,
+ i, UE_template->dl_pdus_in_buffer[i],UE_template->dl_buffer_info[i],
+ UE_template->dl_buffer_head_sdu_creation_time[i],
+ UE_template->dl_buffer_head_sdu_remaining_size_to_send[i],
+ UE_template->dl_buffer_head_sdu_is_segmented[i]
+ );
+
+#endif
+
+ }
+
+ //#ifdef DEBUG_eNB_SCHEDULER
+ if ( UE_template->dl_buffer_total>0)
+ LOG_D(MAC,"[eNB %d] Frame %d Subframe %d : RLC status for UE %d : total DL buffer size %d and total number of pdu %d \n",
+ Mod_id, frameP, subframeP, UE_id,
+ UE_template->dl_buffer_total,
+ UE_template->dl_pdus_total
+ );
+
+ //#endif
+ }
+}
+
+
+// This function returns the estimated number of RBs required by each UE for downlink scheduling
+void _assign_rbs_required (module_id_t Mod_id,
+ frame_t frameP,
+ sub_frame_t subframe,
+ uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
+ int min_rb_unit[MAX_NUM_CCs])
+{
+
+
+ rnti_t rnti;
+ uint16_t TBS = 0;
+ LTE_eNB_UE_stats *eNB_UE_stats[MAX_NUM_CCs];
+ int UE_id,n,i,j,CC_id,pCCid,tmp;
+ UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
+ // UE_TEMPLATE *UE_template;
+
+ // clear rb allocations across all CC_ids
+ for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
+ pCCid = UE_PCCID(Mod_id,UE_id);
+ rnti = UE_list->UE_template[pCCid][UE_id].rnti;
+
+ //update CQI information across component carriers
+ for (n=0; nnumactiveCCs[UE_id]; n++) {
+ CC_id = UE_list->ordered_CCids[n][UE_id];
+ eNB_UE_stats[CC_id] = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti);
+ eNB_UE_stats[CC_id]->dlsch_mcs1=cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)];
+ }
+
+ // provide the list of CCs sorted according to MCS
+ for (i=0; inumactiveCCs[UE_id]; i++) {
+ for (j=i+1; jnumactiveCCs[UE_id]; j++) {
+ DevAssert( j < MAX_NUM_CCs );
+
+ if (eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]]->dlsch_mcs1 >
+ eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]]->dlsch_mcs1) {
+ tmp = UE_list->ordered_CCids[i][UE_id];
+ UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id];
+ UE_list->ordered_CCids[j][UE_id] = tmp;
+ }
+ }
+ }
+
+ /* NN --> RK
+ * check the index of UE_template"
+ */
+ if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total> 0) {
+ LOG_D(MAC,"[preprocessor] assign RB for UE %d\n",UE_id);
+
+ for (i=0; inumactiveCCs[UE_id]; i++) {
+ CC_id = UE_list->ordered_CCids[i][UE_id];
+ eNB_UE_stats[CC_id] = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti);
+
+ if (eNB_UE_stats[CC_id]->dlsch_mcs1==0) {
+ nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small
+ } else {
+ nb_rbs_required[CC_id][UE_id] = min_rb_unit[CC_id];
+ }
+
+ TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);
+
+ LOG_D(MAC,"[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n",
+ UE_id, CC_id, UE_list->UE_template[pCCid][UE_id].dl_buffer_total,
+ nb_rbs_required[CC_id][UE_id],eNB_UE_stats[CC_id]->dlsch_mcs1,TBS);
+
+ /* calculating required number of RBs for each UE */
+ while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total) {
+ nb_rbs_required[CC_id][UE_id] += min_rb_unit[CC_id];
+
+ if (nb_rbs_required[CC_id][UE_id] > flexran_get_N_RB_DL(Mod_id, CC_id)) {
+ TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1, flexran_get_N_RB_DL(Mod_id, CC_id));
+ nb_rbs_required[CC_id][UE_id] = flexran_get_N_RB_DL(Mod_id, CC_id);
+ break;
+ }
+
+ TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);
+ } // end of while
+
+ LOG_D(MAC,"[eNB %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB %d (TBS %d, mcs %d)\n",
+ Mod_id, frameP,UE_id, CC_id, min_rb_unit[CC_id], nb_rbs_required[CC_id][UE_id], TBS, eNB_UE_stats[CC_id]->dlsch_mcs1);
+ }
+ }
+ }
+}
+
+// This function scans all CC_ids for a particular UE to find the maximum round index of its HARQ processes
+int _maxround(module_id_t Mod_id,uint16_t rnti,int frame,sub_frame_t subframe,uint8_t ul_flag )
+{
+
+ uint8_t round,round_max=0,UE_id;
+ int CC_id;
+ UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
+
+ for (CC_id=0; CC_idUE_sched_ctrl[UE_id].round[CC_id];
+ if (round > round_max) {
+ round_max = round;
+ }
+ }
+
+ return round_max;
+}
+
+// This function scans all CC_ids for a particular UE to find the maximum DL CQI
+int _maxcqi(module_id_t Mod_id,int32_t UE_id)
+{
+
+ LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+ UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
+ int CC_id,n;
+ int CQI = 0;
+
+ for (n=0; nnumactiveCCs[UE_id]; n++) {
+ CC_id = UE_list->ordered_CCids[n][UE_id];
+ eNB_UE_stats = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,UE_RNTI(Mod_id,UE_id));
+
+ if (eNB_UE_stats==NULL) {
+ mac_xface->macphy_exit("maxcqi: could not get eNB_UE_stats\n");
+ return 0; // not reached
+ }
+
+ if (eNB_UE_stats->DL_cqi[0] > CQI) {
+ CQI = eNB_UE_stats->DL_cqi[0];
+ }
+ }
+
+ return(CQI);
+}
+
+
+// This fuction sorts the UE in order their dlsch buffer and CQI
+void _sort_UEs (module_id_t Mod_idP,
+ int frameP,
+ sub_frame_t subframeP)
+{
+
+
+ int UE_id1,UE_id2;
+ int pCC_id1,pCC_id2;
+ int cqi1,cqi2,round1,round2;
+ int i=0,ii=0;//,j=0;
+ rnti_t rnti1,rnti2;
+
+ UE_list_t *UE_list = &eNB_mac_inst[Mod_idP].UE_list;
+
+ for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
+
+ for(ii=UE_list->next[i]; ii>=0; ii=UE_list->next[ii]) {
+
+ UE_id1 = i;
+ rnti1 = UE_RNTI(Mod_idP,UE_id1);
+ if(rnti1 == NOT_A_RNTI)
+ continue;
+ if (UE_list->UE_sched_ctrl[UE_id1].ul_out_of_sync == 1)
+ continue;
+ pCC_id1 = UE_PCCID(Mod_idP,UE_id1);
+ cqi1 = _maxcqi(Mod_idP,UE_id1); //
+ round1 = _maxround(Mod_idP,rnti1,frameP,subframeP,0);
+
+ UE_id2 = ii;
+ rnti2 = UE_RNTI(Mod_idP,UE_id2);
+ if(rnti2 == NOT_A_RNTI)
+ continue;
+ if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1)
+ continue;
+ cqi2 = _maxcqi(Mod_idP,UE_id2);
+ round2 = _maxround(Mod_idP,rnti2,frameP,subframeP,0); //mac_xface->get_ue_active_harq_pid(Mod_id,rnti2,subframe,&harq_pid2,&round2,0);
+ pCC_id2 = UE_PCCID(Mod_idP,UE_id2);
+
+ if(round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order
+ swap_UEs(UE_list,UE_id1,UE_id2,0);
+ } else if (round2 == round1) {
+ // RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels. This should be done on the sum of all information that has to be sent. And still it wouldn't ensure fairness. It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service.
+
+ // first check the buffer status for SRB1 and SRB2
+ if ( (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2]) <
+ (UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) ) {
+ swap_UEs(UE_list,UE_id1,UE_id2,0);
+ } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max <
+ UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max ) {
+ swap_UEs(UE_list,UE_id1,UE_id2,0);
+ } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total <
+ UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total ) {
+ swap_UEs(UE_list,UE_id1,UE_id2,0);
+ } else if (cqi1 < cqi2) {
+ swap_UEs(UE_list,UE_id1,UE_id2,0);
+ }
+ }
+ }
+ }
+}
+
+// This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
+void _dlsch_scheduler_pre_processor (module_id_t Mod_id,
+ frame_t frameP,
+ sub_frame_t subframeP,
+ int N_RBG[MAX_NUM_CCs],
+ int *mbsfn_flag)
+{
+
+ unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], harq_pid=0, total_ue_count;
+ unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX];
+ int UE_id, i;
+ unsigned char round = 0;
+ uint16_t ii,j;
+ 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];
+ uint16_t average_rbs_per_user[MAX_NUM_CCs] = {0};
+ rnti_t rnti;
+ int min_rb_unit[MAX_NUM_CCs];
+ uint16_t r1=0;
+ uint8_t CC_id;
+ UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
+ LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs] = {0};
+
+ int transmission_mode = 0;
+ UE_sched_ctrl *ue_sched_ctl;
+
+ for (CC_id=0; CC_id0) // If this CC is allocated for MBSFN skip it here
+ continue;
+
+ frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id);
+
+
+ min_rb_unit[CC_id]=get_min_rb_unit(Mod_id,CC_id);
+
+ for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
+ UE_id = i;
+ // Initialize scheduling information for all active UEs
+
+
+ _dlsch_scheduler_pre_processor_reset(Mod_id,
+ UE_id,
+ CC_id,
+ frameP,
+ subframeP,
+ N_RBG[CC_id],
+ nb_rbs_required,
+ nb_rbs_required_remaining,
+ rballoc_sub,
+ MIMO_mode_indicator);
+
+ }
+ }
+
+ // Store the DLSCH buffer for each logical channel
+ _store_dlsch_buffer (Mod_id,frameP,subframeP);
+
+ // Calculate the number of RBs required by each UE on the basis of logical channel's buffer
+ _assign_rbs_required (Mod_id,frameP,subframeP,nb_rbs_required,min_rb_unit);
+
+ // Sorts the user on the basis of dlsch logical channel buffer and CQI
+ _sort_UEs (Mod_id,frameP,subframeP);
+
+ total_ue_count = 0;
+
+ // loop over all active UEs
+ for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
+ rnti = flexran_get_ue_crnti(Mod_id, i);
+ if(rnti == NOT_A_RNTI)
+ continue;
+ if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
+ continue;
+ UE_id = i;
+
+ // if there is no available harq_process, skip the UE
+ if (UE_list->UE_sched_ctrl[UE_id].harq_pid[CC_id]<0)
+ continue;
+
+ for (ii=0; ii < UE_num_active_CC(UE_list,UE_id); ii++) {
+ CC_id = UE_list->ordered_CCids[ii][UE_id];
+ ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+ flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round);
+
+ average_rbs_per_user[CC_id]=0;
+
+ frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id);
+
+ // mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0);
+
+ if(round>0) {
+ nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
+ }
+
+ //nb_rbs_required_remaining[UE_id] = nb_rbs_required[UE_id];
+ if (nb_rbs_required[CC_id][UE_id] > 0) {
+ total_ue_count = total_ue_count + 1;
+ }
+
+
+ // hypotetical assignement
+ /*
+ * If schedule is enabled and if the priority of the UEs is modified
+ * The average rbs per logical channel per user will depend on the level of
+ * priority. Concerning the hypothetical assignement, we should assign more
+ * rbs to prioritized users. Maybe, we can do a mapping between the
+ * average rbs per user and the level of priority or multiply the average rbs
+ * per user by a coefficient which represents the degree of priority.
+ */
+
+ if (total_ue_count == 0) {
+ average_rbs_per_user[CC_id] = 0;
+ } else if( (min_rb_unit[CC_id] * total_ue_count) <= (frame_parms[CC_id]->N_RB_DL) ) {
+ average_rbs_per_user[CC_id] = (uint16_t) floor(frame_parms[CC_id]->N_RB_DL/total_ue_count);
+ } else {
+ average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE
+ }
+ }
+ }
+
+ // note: nb_rbs_required is assigned according to total_buffer_dl
+ // extend nb_rbs_required to capture per LCID RB required
+ for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
+ rnti = UE_RNTI(Mod_id,i);
+
+ for (ii=0; iiordered_CCids[ii][i];
+
+ // control channel
+ if (mac_eNB_get_rrc_status(Mod_id,rnti) < RRC_RECONFIGURED) {
+ nb_rbs_required_remaining_1[CC_id][i] = nb_rbs_required[CC_id][i];
+ } else {
+ nb_rbs_required_remaining_1[CC_id][i] = cmin(average_rbs_per_user[CC_id],nb_rbs_required[CC_id][i]);
+
+ }
+ }
+ }
+
+ //Allocation to UEs is done in 2 rounds,
+ // 1st stage: average number of RBs allocated to each UE
+ // 2nd stage: remaining RBs are allocated to high priority UEs
+ for(r1=0; r1<2; r1++) {
+
+ for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
+ for (ii=0; iiordered_CCids[ii][i];
+
+ if(r1 == 0) {
+ nb_rbs_required_remaining[CC_id][i] = nb_rbs_required_remaining_1[CC_id][i];
+ } else { // rb required based only on the buffer - rb allloctaed in the 1st round + extra reaming rb form the 1st round
+ nb_rbs_required_remaining[CC_id][i] = nb_rbs_required[CC_id][i]-nb_rbs_required_remaining_1[CC_id][i]+nb_rbs_required_remaining[CC_id][i];
+ }
+
+ if (nb_rbs_required[CC_id][i]> 0 )
+ LOG_D(MAC,"round %d : nb_rbs_required_remaining[%d][%d]= %d (remaining_1 %d, required %d, pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n",
+ r1, CC_id, i,
+ nb_rbs_required_remaining[CC_id][i],
+ nb_rbs_required_remaining_1[CC_id][i],
+ nb_rbs_required[CC_id][i],
+ UE_list->UE_sched_ctrl[i].pre_nb_available_rbs[CC_id],
+ N_RBG[CC_id],
+ min_rb_unit[CC_id]);
+
+ }
+ }
+
+ if (total_ue_count > 0 ) {
+ for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
+ UE_id = i;
+
+ for (ii=0; iiordered_CCids[ii][UE_id];
+ ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+ flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round);
+ rnti = UE_RNTI(Mod_id,UE_id);
+
+ // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti );
+ if(rnti == NOT_A_RNTI)
+ continue;
+ if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
+ continue;
+
+ transmission_mode = mac_xface->get_transmission_mode(Mod_id,CC_id,rnti);
+ //rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti);
+ /* 1st allocate for the retx */
+
+ // retransmission in data channels
+ // control channel in the 1st transmission
+ // data channel for all TM
+ 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],
+ frame_parms[CC_id]->N_RB_DL,
+ nb_rbs_required,
+ nb_rbs_required_remaining,
+ rballoc_sub,
+ MIMO_mode_indicator);
+ }
+ }
+ } // total_ue_count
+ } // end of for for r1 and r2
+
+ for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
+ UE_id = i;
+ ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+
+ for (ii=0; iiordered_CCids[ii][UE_id];
+ //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id];
+
+ if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0 ) {
+ LOG_D(MAC,"******************DL Scheduling Information for UE%d ************************\n",UE_id);
+ LOG_D(MAC,"dl power offset UE%d = %d \n",UE_id,ue_sched_ctl->dl_pow_off[CC_id]);
+ LOG_D(MAC,"***********RB Alloc for every subband for UE%d ***********\n",UE_id);
+
+ for(j=0; jmu_mimo_mode[UE_id].rballoc_sub[i] = rballoc_sub_UE[CC_id][UE_id][i];
+ LOG_D(MAC,"RB Alloc for UE%d and Subband%d = %d\n",UE_id,j,ue_sched_ctl->rballoc_sub_UE[CC_id][j]);
+ }
+
+ //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id];
+ LOG_D(MAC,"Total RBs allocated for UE%d = %d\n",UE_id,ue_sched_ctl->pre_nb_available_rbs[CC_id]);
+ }
+ }
+ }
+}
+
+#define SF05_LIMIT 1
+
+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[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
+ uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
+ unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],
+ unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]) {
+ int i,j;
+ UE_list_t *UE_list=&eNB_mac_inst[module_idP].UE_list;
+ UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+ rnti_t rnti = UE_RNTI(module_idP,UE_id);
+ uint8_t *vrb_map = eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map;
+ int RBGsize = PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL/N_RBG;
+#ifdef SF05_LIMIT
+ //int subframe05_limit=0;
+ int sf05_upper=-1,sf05_lower=-1;
+#endif
+ LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti);
+
+ flexran_update_TA(module_idP, UE_id, CC_id);
+
+ if (UE_id==0) {
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,ue_sched_ctl->ta_update);
+ }
+ nb_rbs_required[CC_id][UE_id]=0;
+ ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0;
+ ue_sched_ctl->dl_pow_off[CC_id] = 2;
+ nb_rbs_required_remaining[CC_id][UE_id] = 0;
+
+#ifdef SF05_LIMIT
+ switch (N_RBG) {
+ case 6:
+ sf05_lower=0;
+ sf05_upper=5;
+ break;
+ case 8:
+ sf05_lower=2;
+ sf05_upper=5;
+ break;
+ case 13:
+ sf05_lower=4;
+ sf05_upper=7;
+ break;
+ case 17:
+ sf05_lower=7;
+ sf05_upper=9;
+ break;
+ case 25:
+ sf05_lower=11;
+ sf05_upper=13;
+ break;
+ }
+#endif
+ // Initialize Subbands according to VRB map
+ for (i=0; irballoc_sub_UE[CC_id][i] = 0;
+ rballoc_sub[CC_id][i] = 0;
+#ifdef SF05_LIMIT
+ // for avoiding 6+ PRBs around DC in subframe 0-5 (avoid excessive errors)
+
+ if ((subframeP==0 || subframeP==5) &&
+ (i>=sf05_lower && i<=sf05_upper))
+ rballoc_sub[CC_id][i]=1;
+#endif
+ // for SI-RNTI,RA-RNTI and P-RNTI allocations
+ for (j=0;jUE_sched_ctrl[UE_id];
+
+ for(i=0; irballoc_sub_UE[CC_id][i] == 0) &&
+ (nb_rbs_required_remaining[CC_id][UE_id]>0) &&
+ (ue_sched_ctl->pre_nb_available_rbs[CC_id] < nb_rbs_required[CC_id][UE_id])) {
+
+ // if this UE is not scheduled for TM5
+ if (ue_sched_ctl->dl_pow_off[CC_id] != 0 ) {
+
+ if ((i == N_RBG-1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) {
+ rballoc_sub[CC_id][i] = 1;
+ ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
+ MIMO_mode_indicator[CC_id][i] = 1;
+ if (transmission_mode == 5 ) {
+ ue_sched_ctl->dl_pow_off[CC_id] = 1;
+ }
+ nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit+1;
+ ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1;
+ } else {
+ if (nb_rbs_required_remaining[CC_id][UE_id] >= min_rb_unit){
+ rballoc_sub[CC_id][i] = 1;
+ ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
+ MIMO_mode_indicator[CC_id][i] = 1;
+ if (transmission_mode == 5 ) {
+ ue_sched_ctl->dl_pow_off[CC_id] = 1;
+ }
+ nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit;
+ ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit;
+ }
+ }
+ } // dl_pow_off[CC_id][UE_id] ! = 0
+ }
+ }
+}
diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.c
new file mode 100644
index 0000000000..7dec8d0c56
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.c
@@ -0,0 +1,180 @@
+/*
+ * 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.0 (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_scheduler_dlsch_ue_remote.c
+ * \brief procedures related to remote scheduling in the DLSCH transport channel
+ * \author Xenofon Foukas
+ * \date 2016
+ * \email: x.foukas@sms.ed.ac.uk
+ * \version 0.1
+ * @ingroup _mac
+
+ */
+
+#include "flexran_agent_common_internal.h"
+
+#include "flexran_agent_scheduler_dlsch_ue_remote.h"
+
+#include "LAYER2/MAC/defs.h"
+#include "LAYER2/MAC/extern.h"
+
+struct DlMacConfigHead queue_head;
+
+int queue_initialized = 0;
+
+//uint32_t skip_subframe = 1;
+//uint32_t period = 10;
+//uint32_t sched [] = {1, 2, 3};
+
+void flexran_schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, uint32_t subframe,
+ int *mbsfn_flag, Protocol__FlexranMessage **dl_info) {
+
+
+ //if ((subframe == skip_subframe) && (frame % period == 0)) {
+ // LOG_I(MAC, "Will skip subframe %d %d\n", subframe, frame);
+ // for (int i = 0; i < 3; i++) {
+ // LOG_I(MAC, "%d\n", sched[i]);
+ // }
+ //}
+
+ /* if (frame == 500 && subframe == 1) { */
+ /* char policy[] = "rrc: \n - ul_scheduler: \n behavior : tester_function\n parameters:\n period: !!int 3\nmac: \n - dl_scheduler: \n parameters: \n period : !!int 40\n skip_subframe : !!int 3\n sched : [!!int 4, !!int 5, !!int 6]"; */
+ /* apply_reconfiguration_policy(mod_id, policy, strlen(policy)); */
+ /* } */
+
+ eNB_MAC_INST *eNB;
+
+ if (!queue_initialized) {
+ TAILQ_INIT(&queue_head);
+ queue_initialized = 1;
+ }
+
+ eNB = &eNB_mac_inst[mod_id];
+
+ dl_mac_config_element_t *dl_config_elem;
+
+ int diff;
+ LOG_D(MAC, "[TEST] Current frame and subframe %d, %d\n", frame, subframe);
+ // First we check to see if we have a scheduling decision for this sfn_sf already in our queue
+ while(queue_head.tqh_first != NULL) {
+ dl_config_elem = queue_head.tqh_first;
+
+ diff = get_sf_difference(mod_id, dl_config_elem->dl_info->dl_mac_config_msg->sfn_sf);
+ // Check if this decision is for now, for a later or a previous subframe
+ if ( diff == 0) { // Now
+ LOG_D(MAC, "Found a decision for this subframe in the queue. Let's use it!\n");
+ TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs);
+ *dl_info = dl_config_elem->dl_info;
+ free(dl_config_elem);
+ eNB->eNB_stats[mod_id].sched_decisions++;
+ return;
+ } else if (diff < 0) { //previous subframe , delete message and free memory
+ LOG_D(MAC, "Found a decision for a previous subframe in the queue. Let's get rid of it\n");
+ TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs);
+ flexran_agent_mac_destroy_dl_config(dl_config_elem->dl_info);
+ free(dl_config_elem);
+ eNB->eNB_stats[mod_id].sched_decisions++;
+ eNB->eNB_stats[mod_id].missed_deadlines++;
+ } else { // next subframe, nothing to do now
+ LOG_D(MAC, "Found a decision for a future subframe in the queue. Nothing to do now\n");
+ flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
+ return;
+ }
+ }
+
+ //Done with the local cache. Now we need to check if something new arrived
+ flexran_agent_get_pending_dl_mac_config(mod_id, dl_info);
+ while (*dl_info != NULL) {
+
+ diff = get_sf_difference(mod_id, (*dl_info)->dl_mac_config_msg->sfn_sf);
+ if (diff == 0) { // Got a command for this sfn_sf
+ LOG_D(MAC, "Found a decision for this subframe pending. Let's use it\n");
+ eNB->eNB_stats[mod_id].sched_decisions++;
+ return;
+ } else if (diff < 0) {
+ LOG_D(MAC, "Found a decision for a previous subframe. Let's get rid of it\n");
+ flexran_agent_mac_destroy_dl_config(*dl_info);
+ *dl_info = NULL;
+ flexran_agent_get_pending_dl_mac_config(mod_id, dl_info);
+ eNB->eNB_stats[mod_id].sched_decisions++;
+ eNB->eNB_stats[mod_id].missed_deadlines++;
+ } else { // Intended for future subframe. Store it in local cache
+ LOG_D(MAC, "Found a decision for a future subframe in the queue. Let's store it in the cache\n");
+ dl_mac_config_element_t *e = malloc(sizeof(dl_mac_config_element_t));
+ e->dl_info = *dl_info;
+ TAILQ_INSERT_TAIL(&queue_head, e, configs);
+ flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
+ // No need to look for another. Messages arrive ordered
+ return;
+ }
+ }
+
+ // We found no pending command, so we will simply pass an empty one
+ flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
+}
+
+int get_sf_difference(mid_t mod_id, uint32_t sfn_sf) {
+ int diff_in_subframes;
+
+ uint16_t current_frame = flexran_get_current_system_frame_num(mod_id);
+ uint16_t current_subframe = flexran_get_current_subframe(mod_id);
+ uint32_t current_sfn_sf = flexran_get_sfn_sf(mod_id);
+
+ if (sfn_sf == current_sfn_sf) {
+ return 0;
+ }
+
+ uint16_t frame_mask = ((1<<12) - 1);
+ uint16_t frame = (sfn_sf & (frame_mask << 4)) >> 4;
+
+ uint16_t sf_mask = ((1<<4) - 1);
+ uint16_t subframe = (sfn_sf & sf_mask);
+
+ LOG_D(MAC, "[TEST] Target frame and subframe %d, %d\n", frame, subframe);
+
+ if (frame == current_frame) {
+ return subframe - current_subframe;
+ } else if (frame > current_frame) {
+ diff_in_subframes = ((frame*10)+subframe) - ((current_frame*10)+current_subframe);
+
+ // diff_in_subframes = 9 - current_subframe;
+ //diff_in_subframes += (subframe + 1);
+ //diff_in_subframes += (frame-2) * 10;
+ if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) {
+ return -1;
+ } else {
+ return 1;
+ }
+ } else { //frame < current_frame
+ //diff_in_subframes = 9 - current_subframe;
+ //diff_in_subframes += (subframe + 1);
+ //if (frame > 0) {
+ // diff_in_subframes += (frame - 1) * 10;
+ //}
+ //diff_in_subframes += (1023 - current_frame) * 10;
+ diff_in_subframes = 10240 - ((current_frame*10)+current_subframe) + ((frame*10)+subframe);
+ if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+}
diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h
new file mode 100644
index 0000000000..7a02ff2f1d
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h
@@ -0,0 +1,69 @@
+/*
+ * 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.0 (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_scheduler_dlsch_ue_remote.h
+ * \brief Local stub for remote scheduler used by the controller
+ * \author Xenofon Foukas
+ * \date 2016
+ * \email: x.foukas@sms.ed.ac.uk
+ * \version 0.1
+ * @ingroup _mac
+
+ */
+
+#ifndef __LAYER2_MAC_FLEXRAN_AGENT_SCHEDULER_DLSCH_UE_REMOTE_H__
+#define __LAYER2_MAC_FLEXRAN_AGENT_SCHEDULER_DLSCH_UE_REMOTE_H___
+
+#include "flexran.pb-c.h"
+#include "header.pb-c.h"
+
+#include "ENB_APP/flexran_agent_defs.h"
+#include "flexran_agent_mac.h"
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+
+#include
+
+// Maximum value of schedule ahead of time
+// Required to identify if a dl_command is for the future or not
+#define SCHED_AHEAD_SUBFRAMES 20
+
+typedef struct dl_mac_config_element_s {
+ Protocol__FlexranMessage *dl_info;
+ TAILQ_ENTRY(dl_mac_config_element_s) configs;
+} dl_mac_config_element_t;
+
+TAILQ_HEAD(DlMacConfigHead, dl_mac_config_element_s);
+
+/*
+ * Default scheduler used by the eNB agent
+ */
+void flexran_schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, uint32_t subframe,
+ int *mbsfn_flag, Protocol__FlexranMessage **dl_info);
+
+
+// Find the difference in subframes from the given subframe
+// negative for older value
+// 0 for equal
+// positive for future value
+// Based on
+int get_sf_difference(mid_t mod_id, uint32_t sfn_sf);
+
+#endif
diff --git a/openair2/LAYER2/MAC/flexran_dci_conversions.h b/openair2/LAYER2/MAC/flexran_dci_conversions.h
new file mode 100644
index 0000000000..a417c39d20
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_dci_conversions.h
@@ -0,0 +1,51 @@
+/*
+ * 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.0 (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_dci_conversions.h
+ * \brief Conversion helpers from flexran messages to OAI formats DCI
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef LAYER2_MAC_FLEXRAN_DCI_CONVERISIONS_H__
+#define LAYER2_MAC_DCI_FLEXRAN_CONVERISIONS_H__
+
+#define FILL_DCI_FDD_1(TYPE, DCI, FLEXRAN_DCI) \
+ ((TYPE*)DCI)->harq_pid = FLEXRAN_DCI->harq_process; \
+ ((TYPE*)DCI)->rv = FLEXRAN_DCI->rv[0]; \
+ ((TYPE*)DCI)->rballoc = FLEXRAN_DCI->rb_bitmap; \
+ ((TYPE*)DCI)->rah = FLEXRAN_DCI->res_alloc; \
+ ((TYPE*)DCI)->mcs = FLEXRAN_DCI->mcs[0]; \
+ ((TYPE*)DCI)->TPC = FLEXRAN_DCI->tpc; \
+ ((TYPE*)DCI)->ndi = FLEXRAN_DCI->ndi[0];
+
+#define FILL_DCI_TDD_1(TYPE, DCI, FLEXRAN_DCI) \
+ ((TYPE*)DCI)->harq_pid = FLEXRAN_DCI->harq_process; \
+ ((TYPE*)DCI)->rv = FLEXRAN_DCI->rv[0]; \
+ ((TYPE*)DCI)->dai = FLEXRAN_DCI->dai; \
+ ((TYPE*)DCI)->rballoc = FLEXRAN_DCI->rb_bitmap; \
+ ((TYPE*)DCI)->rah = FLEXRAN_DCI->res_alloc; \
+ ((TYPE*)DCI)->mcs = FLEXRAN_DCI->mcs[0]; \
+ ((TYPE*)DCI)->TPC = FLEXRAN_DCI->tpc; \
+ ((TYPE*)DCI)->ndi = FLEXRAN_DCI->ndi[0];
+
+#endif
diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c
index 0fe9d63b6f..203bd3f36f 100644
--- a/openair2/LAYER2/MAC/main.c
+++ b/openair2/LAYER2/MAC/main.c
@@ -527,6 +527,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui
mac_xface->phy_config_dedicated_eNB = phy_config_dedicated_eNB;
mac_xface->phy_config_dedicated_ue = phy_config_dedicated_ue;
+ mac_xface->phy_config_harq_ue = phy_config_harq_ue;
mac_xface->get_lte_frame_parms = get_lte_frame_parms;
mac_xface->get_mu_mimo_mode = get_mu_mimo_mode;
diff --git a/openair2/LAYER2/MAC/openair2_proc.c b/openair2/LAYER2/MAC/openair2_proc.c
index 950713de5a..4b63571277 100644
--- a/openair2/LAYER2/MAC/openair2_proc.c
+++ b/openair2/LAYER2/MAC/openair2_proc.c
@@ -82,7 +82,7 @@ int openair2_stats_read(char *buffer, char **my_buffer, off_t off, int length)
// mod_id used for PDCP and RLC
Mod_id = NB_eNB_INST + ue_id ;
- len+=sprintf(&buffer[len],"UE TTI: %d\n",UE_mac_inst[ue_id].frame);
+ len+=sprintf(&buffer[len],"UE RX TTI: %d\n",UE_mac_inst[ue_id].rxFrame);
for (enb_id= 0; enb_id harq_pid[CC_id],
&ue_sched_ctl->round[CC_id],
- 0);
+ openair_harq_DL);
if (ue_sched_ctl->ta_timer == 0) {
// WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...
@@ -1028,7 +1028,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP,
// This is the actual CC_id in the list
CC_id = UE_list->ordered_ULCCids[n][UE_id];
- mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,1);
+ mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL);
if(round>0) {
nb_allocated_rbs[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid];
diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h
index 4df0c6fa45..9454f3da80 100644
--- a/openair2/LAYER2/MAC/proto.h
+++ b/openair2/LAYER2/MAC/proto.h
@@ -28,6 +28,7 @@
*/
#ifndef __LAYER2_MAC_PROTO_H__
#define __LAYER2_MAC_PROTO_H__
+
/** \addtogroup _mac
* @{
*/
@@ -121,6 +122,7 @@ void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,i
*/
void schedule_ue_spec(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag);
+
/** \brief Function for UE/PHY to compute PUSCH transmit power in power-control procedure.
@param Mod_id Module id of UE
@returns Po_NOMINAL_PUSCH (PREAMBLE_RECEIVED_TARGET_POWER+DELTA_PREAMBLE
@@ -445,6 +447,9 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,u
/* \brief Function called by PHY to process the received RAR. It checks that the preamble matches what was sent by the eNB and provides the timing advance and t-CRNTI.
@param Mod_id Index of UE instance
+@param CC_id Index to a component carrier
+@param frame Frame index
+@param ra_rnti RA_RNTI value
@param dlsch_buffer Pointer to dlsch_buffer containing RAR PDU
@param t_crnti Pointer to PHY variable containing the T_CRNTI
@param preamble_index Preamble Index used by PHY to transmit the PRACH. This should match the received RAR to trigger the rest of
@@ -456,6 +461,7 @@ ue_process_rar(
const module_id_t module_idP,
const int CC_id,
const frame_t frameP,
+ const rnti_t ra_rnti,
uint8_t * const dlsch_buffer,
rnti_t * const t_crnti,
const uint8_t preamble_index
@@ -534,15 +540,20 @@ void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, UE_TEMPLATE *UE_templat
/*! \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.
\param[in] module_idP instance of the UE
-\param[in] subframe t the subframe number
+\param[in] rxFrame the RX frame number
+\param[in] rxSubframe the RX subframe number
+\param[in] txFrame the TX frame number
+\param[in] txSubframe the TX subframe number
\param[in] direction subframe direction
\param[in] eNB_index instance of eNB
@returns L2 state (CONNETION_OK or CONNECTION_LOST or PHY_RESYNCH)
*/
UE_L2_STATE_t ue_scheduler(
const module_id_t module_idP,
- const frame_t frameP,
- const sub_frame_t subframe,
+ const frame_t rxFrameP,
+ const sub_frame_t rxSubframe,
+ const frame_t txFrameP,
+ const sub_frame_t txSubframe,
const lte_subframe_t direction,
const uint8_t eNB_index,
const int CC_id);
@@ -557,21 +568,6 @@ UE_L2_STATE_t ue_scheduler(
*/
int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint16_t buflen);
-/*! \fn int get_bsr_lcgid (module_id_t module_idP);
-\brief determine the lcgid for the bsr
-\param[in] Mod_id instance of the UE
-\param[out] lcgid
-*/
-int get_bsr_lcgid (module_id_t module_idP);
-
-/*! \fn uint8_t get_bsr_len (module_id_t module_idP,uint16_t bufflen);
-\brief determine whether the bsr is short or long assuming that the MAC pdu is built
-\param[in] Mod_id instance of the UE
-\param[in] bufflen size of phy transport block
-\param[out] bsr_len size of bsr control element
-*/
-uint8_t get_bsr_len (module_id_t module_idP, uint16_t buflen);
-
/*! \fn BSR_SHORT * get_bsr_short(module_id_t module_idP, uint8_t bsr_len)
\brief get short bsr level
\param[in] Mod_id instance of the UE
@@ -588,22 +584,21 @@ BSR_SHORT *get_bsr_short(module_id_t module_idP, uint8_t bsr_len);
*/
BSR_LONG * get_bsr_long(module_id_t module_idP, uint8_t bsr_len);
-/*! \fn boolean_t update_bsr(module_id_t module_idP, frame_t frameP, uint8_t lcid)
+/*! \fn boolean_t update_bsr(module_id_t module_idP, frame_t frameP,sub_frame_t subframeP)
\brief get the rlc stats and update the bsr level for each lcid
\param[in] Mod_id instance of the UE
\param[in] frame Frame index
-\param[in] lcid logical channel identifier
*/
-boolean_t update_bsr(module_id_t module_idP, frame_t frameP, eNB_index_t eNB_index, uint8_t lcid, uint8_t lcgid);
+boolean_t update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP,eNB_index_t eNB_index);
-/*! \fn locate (int *table, int size, int value)
+/*! \fn locate_BsrIndexByBufferSize (int *table, int size, int value)
\brief locate the BSR level in the table as defined in 36.321. This function requires that he values in table to be monotonic, either increasing or decreasing. The returned value is not less than 0, nor greater than n-1, where n is the size of table.
\param[in] *table Pointer to BSR table
\param[in] size Size of the table
\param[in] value Value of the buffer
\return the index in the BSR_LEVEL table
*/
-uint8_t locate (const uint32_t *table, int size, int value);
+uint8_t locate_BsrIndexByBufferSize (const uint32_t *table, int size, int value);
/*! \fn int get_sf_periodicBSRTimer(uint8_t periodicBSR_Timer)
diff --git a/openair2/LAYER2/MAC/ra_procedures.c b/openair2/LAYER2/MAC/ra_procedures.c
index ffc8df4792..43bc113798 100644
--- a/openair2/LAYER2/MAC/ra_procedures.c
+++ b/openair2/LAYER2/MAC/ra_procedures.c
@@ -271,8 +271,8 @@ void Msg1_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id
UE_mac_inst[module_idP].RA_attempt_number++;
if (opt_enabled) {
- trace_pdu(0, NULL, 0, module_idP, 2, UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex,
- UE_mac_inst[module_idP].subframe, 0, UE_mac_inst[module_idP].RA_attempt_number);
+ trace_pdu(0, NULL, 0, module_idP, 0 , UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex,
+ UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, UE_mac_inst[module_idP].RA_attempt_number);
LOG_D(OPT,"[UE %d][RAPROC] TX MSG1 Frame %d trace pdu for rnti %x with size %d\n",
module_idP, frameP, 1, UE_mac_inst[module_idP].RA_Msg3_size);
}
@@ -296,7 +296,7 @@ void Msg3_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id
if (opt_enabled) { // msg3
trace_pdu(0, &UE_mac_inst[module_idP].CCCH_pdu.payload[0], UE_mac_inst[module_idP].RA_Msg3_size,
- module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].subframe, 0, 0);
+ module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, 0);
LOG_D(OPT,"[UE %d][RAPROC] MSG3 Frame %d trace pdu Preamble %d with size %d\n",
module_idP, frameP, UE_mac_inst[module_idP].crnti /*UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex*/, UE_mac_inst[module_idP].RA_Msg3_size);
}
@@ -391,7 +391,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
1); //post_padding
return(&UE_mac_inst[module_idP].RA_prach_resources);
- } else if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DCCH] > 0) {
+ } else if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] > 0) {
// This is for triggering a transmission on DCCH using PRACH (during handover, or sending SR for example)
dcch_header_len = 2 + 2; /// SHORT Subheader + C-RNTI control element
rlc_status = mac_rlc_status_ind(module_idP,UE_mac_inst[module_idP].crnti, eNB_indexP,frameP,ENB_FLAG_NO,MBMS_FLAG_NO,
@@ -412,7 +412,12 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
(char *)&ulsch_buff[0]);
LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]);
- update_bsr(module_idP, frameP, eNB_indexP,DCCH,UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]);
+ update_bsr(module_idP, frameP, subframeP,eNB_indexP);
+ UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] =
+ locate_BsrIndexByBufferSize(BSR_TABLE, BSR_TABLE_SIZE, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]]);
+
+ //TO DO: fill BSR infos in UL TBS
+
//header_len +=2;
UE_mac_inst[module_idP].RA_active = 1;
UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
diff --git a/openair2/LAYER2/MAC/rar_tools.c b/openair2/LAYER2/MAC/rar_tools.c
index a637ddf18c..b453b5cca8 100644
--- a/openair2/LAYER2/MAC/rar_tools.c
+++ b/openair2/LAYER2/MAC/rar_tools.c
@@ -118,7 +118,7 @@ unsigned short fill_rar(
if (opt_enabled) {
trace_pdu(1, dlsch_buffer, input_buffer_length, module_idP, 2, 1,
- eNB_mac_inst[module_idP].subframe, 0, 0);
+ eNB_mac_inst[module_idP].frame, eNB_mac_inst[module_idP].subframe, 0, 0);
LOG_D(OPT,"[eNB %d][RAPROC] CC_id %d RAR Frame %d trace pdu for rnti %x and rapid %d size %d\n",
module_idP, CC_id, frameP, eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].rnti,
rarh->RAPID, input_buffer_length);
@@ -133,6 +133,7 @@ ue_process_rar(
const module_id_t module_idP,
const int CC_id,
const frame_t frameP,
+ const rnti_t ra_rnti,
uint8_t* const dlsch_buffer,
rnti_t* const t_crnti,
const uint8_t preamble_index
@@ -168,6 +169,12 @@ ue_process_rar(
LOG_D(MAC,"[UE %d][RAPROC] rar->t_crnti %x\n",module_idP,(uint16_t)rar[5]+(rar[4]<<8));
#endif
+ if (opt_enabled) {
+ LOG_D(OPT,"[UE %d][RAPROC] CC_id %d RAR Frame %d trace pdu for ra-RNTI %x\n",
+ module_idP, CC_id, frameP, ra_rnti);
+ trace_pdu(1, (uint8_t*)rarh, 7, module_idP, 2, ra_rnti,
+ UE_mac_inst[module_idP].rxFrame, UE_mac_inst[module_idP].rxSubframe, 0, 0);
+ }
if (preamble_index == rarh->RAPID) {
*t_crnti = (uint16_t)rar[5]+(rar[4]<<8);//rar->t_crnti;
diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c
index c91c977c3a..cdac22c486 100644
--- a/openair2/LAYER2/MAC/ue_procedures.c
+++ b/openair2/LAYER2/MAC/ue_procedures.c
@@ -70,6 +70,8 @@
#define DEBUG_HEADER_PARSING 1
#define ENABLE_MAC_PAYLOAD_DEBUG 1
+extern uint8_t usim_test;
+
/*
#ifndef USER_MODE
#define msg debug_msg
@@ -91,7 +93,7 @@ void ue_init_mac(module_id_t module_idP)
// default values as deined in 36.331 sec 9.2.2
LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP);
//UE_mac_inst[module_idP].scheduling_info.macConfig=NULL;
- UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560;
+ UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf10240;
UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer=MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity;
UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer = MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20;
UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer = MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20;
@@ -102,13 +104,19 @@ void ue_init_mac(module_id_t module_idP)
UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
UE_mac_inst[module_idP].scheduling_info.maxHARQ_Tx=MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5;
UE_mac_inst[module_idP].scheduling_info.ttiBundling=0;
+ UE_mac_inst[module_idP].scheduling_info.extendedBSR_Sizes_r10=0;
+ UE_mac_inst[module_idP].scheduling_info.extendedPHR_r10=0;
UE_mac_inst[module_idP].scheduling_info.drx_config=NULL;
UE_mac_inst[module_idP].scheduling_info.phr_config=NULL;
- UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer);
- UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);
+ // set init value 0xFFFF, make sure periodic timer and retx time counters are NOT active, after bsr transmission set the value configured by the NW.
+ UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING;
+ UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING;
+ UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
+
UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF = get_sf_perioidicPHR_Timer(UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer);
UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF = get_sf_prohibitPHR_Timer(UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer);
UE_mac_inst[module_idP].scheduling_info.PathlossChange_db = get_db_dl_PathlossChange(UE_mac_inst[module_idP].scheduling_info.PathlossChange);
+ UE_mac_inst[module_idP].PHR_reporting_active = 0;
for (i=0; i < MAX_NUM_LCID; i++) {
LOG_D(MAC,"[UE%d] Applying default logical channel config for LCGID %d\n",module_idP,i);
@@ -121,7 +129,8 @@ void ue_init_mac(module_id_t module_idP)
UE_mac_inst[module_idP].scheduling_info.LCGID[i]=1;
}
- UE_mac_inst[module_idP].scheduling_info.LCID_status[i]=0;
+ UE_mac_inst[module_idP].scheduling_info.LCID_status[i]=LCID_EMPTY;
+ UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[i] = 0;
}
#ifdef CBA
@@ -143,7 +152,7 @@ unsigned char *parse_header(unsigned char *mac_header,
unsigned short tb_length)
{
- unsigned char not_done=1,num_ces=0,num_sdus=0,lcid, num_sdu_cnt;
+ unsigned char not_done=1,num_ces=0,num_cont_res = 0,num_padding = 0,num_sdus=0,lcid, num_sdu_cnt;
unsigned char *mac_header_ptr = mac_header;
unsigned short length,ce_len=0;
@@ -188,6 +197,7 @@ unsigned char *parse_header(unsigned char *mac_header,
num_sdus++;
} else { // This is a control element subheader
if (lcid == SHORT_PADDING) {
+ num_padding ++;
mac_header_ptr++;
} else {
rx_ces[num_ces] = lcid;
@@ -197,6 +207,23 @@ unsigned char *parse_header(unsigned char *mac_header,
if (lcid==TIMING_ADV_CMD) {
ce_len++;
} else if (lcid==UE_CONT_RES) {
+
+ // FNA: check MAC Header is one of thoses defined in Annex B of 36.321
+ // Check there is only 1 Contention Resolution
+ if (num_cont_res) {
+ LOG_W(MAC,"[UE] Msg4 Wrong received format: More than 1 Contention Resolution\n");
+ // exit parsing
+ return NULL;
+
+ }
+
+ // UE_CONT_RES shall never be the last subheader unless this is the only MAC subheader
+ if ((not_done == 0) && ((num_sdus) || (num_ces > 1) || (num_padding))) {
+ LOG_W(MAC,"[UE] Msg4 Wrong received format: Contention Resolution after num_ces=%d num_sdus=%d num_padding=%d\n",num_ces,num_sdus,num_padding);
+ // exit parsing
+ return NULL;
+ }
+ num_cont_res ++;
ce_len+=6;
}
}
@@ -286,6 +313,14 @@ uint32_t ue_get_SR(module_id_t module_idP,int CC_id,frame_t frameP,uint8_t eNB_i
// notify RRC to relase PUCCH/SRS
// clear any configured dl/ul
// initiate RA
+ if (UE_mac_inst[module_idP].scheduling_info.SR_pending){
+ // release all pucch resource
+ UE_mac_inst[module_idP].physicalConfigDedicated = NULL;
+ UE_mac_inst[module_idP].ul_active=0;
+ UE_mac_inst[module_idP].BSR_reporting_active=BSR_TRIGGER_NONE;
+
+ LOG_I(MAC,"[UE %d] Release all SRs \n", module_idP);
+ }
UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
return(0);
@@ -294,12 +329,16 @@ uint32_t ue_get_SR(module_id_t module_idP,int CC_id,frame_t frameP,uint8_t eNB_i
//------------------------------------------------------------------------------
void
-ue_send_sdu(module_id_t module_idP,
+ue_send_sdu(
+ module_id_t module_idP,
uint8_t CC_id,
frame_t frameP,
uint8_t* sdu,
uint16_t sdu_len,
- uint8_t eNB_index) {
+ uint8_t eNB_index
+)
+//------------------------------------------------------------------------------
+{
unsigned char rx_ces[MAX_NUM_CE],num_ce,num_sdu,i,*payload_ptr;
unsigned char rx_lcids[NB_RB_MAX];
@@ -313,7 +352,7 @@ ue_send_sdu(module_id_t module_idP,
if (opt_enabled) {
trace_pdu(1, sdu, sdu_len, module_idP, 3, UE_mac_inst[module_idP].crnti,
- UE_mac_inst[module_idP].subframe, 0, 0);
+ UE_mac_inst[module_idP].rxFrame, UE_mac_inst[module_idP].rxSubframe, 0, 0);
LOG_D(OPT,"[UE %d][DLSCH] Frame %d trace pdu for rnti %x with size %d\n",
module_idP, frameP, UE_mac_inst[module_idP].crnti, sdu_len);
}
@@ -335,6 +374,8 @@ ue_send_sdu(module_id_t module_idP,
LOG_T(MAC,"\n");
#endif
+ if (payload_ptr != NULL) {
+
for (i=0; iBuffer_size0 << 2) | ((long_bsr->Buffer_size1 & 0x30) >> 4);
*(ce_ptr + 1) = ((long_bsr->Buffer_size1 & 0x0F) << 4) | ((long_bsr->Buffer_size2 & 0x3C) >> 2);
*(ce_ptr + 2) = ((long_bsr->Buffer_size2 & 0x03) << 2) | (long_bsr->Buffer_size3 & 0x3F);
- /* Padding */
- *(ce_ptr + 3) = 0;
ce_ptr += BSR_LONG_SIZE;
// printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
@@ -1122,50 +1164,67 @@ unsigned char generate_ulsch_header(uint8_t *mac_header,
LOG_T(MAC,"[UE] sdu subheader %d (lcid %d, %d bytes)\n",i,sdu_lcids[i],sdu_lengths[i]);
#endif
- if ((first_element>0)) {
- mac_header_ptr->E = 1;
-#ifdef DEBUG_HEADER_PARSING
- LOG_D(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
- ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
- ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
- ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
-#endif
- mac_header_ptr+=last_size;
- // printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
- } else {
- first_element=1;
-
+ if ((i == (num_sdus - 1)) && ((short_padding) || (post_padding == 0))) {
+ if (first_element>0) {
+ mac_header_ptr->E = 1;
+ #ifdef DEBUG_HEADER_PARSING
+ LOG_D(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
+ ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
+ ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
+ ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
+ #endif
+ mac_header_ptr+=last_size;
+ }
+ mac_header_ptr->R = 0;
+ mac_header_ptr->E = 0;
+ mac_header_ptr->LCID = sdu_lcids[i];
}
+ else {
+ if ((first_element>0)) {
+ mac_header_ptr->E = 1;
+ #ifdef DEBUG_HEADER_PARSING
+ LOG_D(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
+ ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
+ ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
+ ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
+ #endif
+ mac_header_ptr+=last_size;
+ // printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
+ } else {
+ first_element=1;
- if (sdu_lengths[i] < 128) {
- ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R = 0; // 3
- ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E = 0;
- ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F = 0;
- ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID = sdu_lcids[i];
- ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L = (unsigned char)sdu_lengths[i];
- last_size=2;
-#ifdef DEBUG_HEADER_PARSING
- LOG_D(MAC,"[UE] short sdu\n");
- LOG_T(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d,F%d,L%d)\n",
- ((uint16_t*)mac_header_ptr)[0],
- ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R,
- ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E,
- ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID,
- ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F,
- ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L);
-#endif
- } else {
- ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R = 0;
- ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E = 0;
- ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F = 1;
- ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = sdu_lcids[i];
- ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB = ((unsigned short) sdu_lengths[i]>>8)&0x7f;
- ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB = (unsigned short) sdu_lengths[i]&0xff;
- ((SCH_SUBHEADER_LONG *)mac_header_ptr)->padding = 0x00;
- last_size=3;
-#ifdef DEBUG_HEADER_PARSING
- LOG_D(MAC,"[UE] long sdu\n");
-#endif
+ }
+
+ if (sdu_lengths[i] < 128) {
+ ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R = 0; // 3
+ ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E = 0;
+ ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F = 0;
+ ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID = sdu_lcids[i];
+ ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L = (unsigned char)sdu_lengths[i];
+ last_size=2;
+ #ifdef DEBUG_HEADER_PARSING
+ LOG_D(MAC,"[UE] short sdu\n");
+ LOG_T(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d,F%d,L%d)\n",
+ ((uint16_t*)mac_header_ptr)[0],
+ ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R,
+ ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E,
+ ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID,
+ ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F,
+ ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L);
+ #endif
+ } else {
+ ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R = 0;
+ ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E = 0;
+ ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F = 1;
+ ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = sdu_lcids[i];
+ ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB = ((unsigned short) sdu_lengths[i]>>8)&0x7f;
+ ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB = (unsigned short) sdu_lengths[i]&0xff;
+ ((SCH_SUBHEADER_LONG *)mac_header_ptr)->padding = 0x00;
+ last_size=3;
+ #ifdef DEBUG_HEADER_PARSING
+ LOG_D(MAC,"[UE] long sdu\n");
+ #endif
+ }
}
}
@@ -1183,6 +1242,7 @@ unsigned char generate_ulsch_header(uint8_t *mac_header,
//mac_header_ptr=last_size; // FIXME: should be ++
}
+
if ((ce_ptr-mac_header_control_elements) > 0) {
memcpy((void*)mac_header_ptr,mac_header_control_elements,ce_ptr-mac_header_control_elements);
mac_header_ptr+=(unsigned char)(ce_ptr-mac_header_control_elements);
@@ -1205,27 +1265,36 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
{
mac_rlc_status_resp_t rlc_status;
- uint8_t dcch_header_len=0,dcch1_header_len=0,dtch_header_len=0,dtch_header_len_last=0;
- uint8_t dcch_header_len_tmp=0, dtch_header_len_tmp=0;
- uint8_t bsr_header_len=0, bsr_ce_len=0, bsr_len=0;
+ uint8_t total_rlc_pdu_header_len=0, rlc_pdu_header_len_last=0 ;
+ uint16_t buflen_remain = 0;
+ uint8_t bsr_len=0,bsr_ce_len=0,bsr_header_len=0;
uint8_t phr_header_len=0, phr_ce_len=0,phr_len=0;
- uint8_t lcid=0;
+ uint8_t lcid=0,lcid_rlc_pdu_count=0;
+ boolean_t is_lcid_processed = FALSE;
uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t payload_offset=0,num_sdus=0;
uint8_t ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES];
uint16_t sdu_length_total=0;
- BSR_SHORT bsr_short;
+ BSR_SHORT bsr_short,bsr_truncated;
BSR_LONG bsr_long;
BSR_SHORT *bsr_s=&bsr_short;
BSR_LONG *bsr_l=&bsr_long;
+ BSR_SHORT *bsr_t=&bsr_truncated;
POWER_HEADROOM_CMD phr;
POWER_HEADROOM_CMD *phr_p=&phr;
- unsigned short short_padding=0, post_padding=0;
- int lcgid;
+ unsigned short short_padding=0, post_padding=0, padding_len=0;
int j; // used for padding
// Compute header length
+ int lcg_id = 0;
+ int lcg_id_bsr_trunc = 0;
+ int highest_priority = 16;
+ int num_lcg_id_with_data = 0;
+
+ LOG_D(MAC,"[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n",
+ module_idP, frameP, subframe, buflen);
+
if (CC_id>0) {
LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
mac_xface->macphy_exit("MAC FATAL CC_id>0");
@@ -1253,33 +1322,76 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
}
#endif
- dcch_header_len=2;//sizeof(SCH_SUBHEADER_SHORT);
- dcch1_header_len=2;//sizeof(SCH_SUBHEADER_SHORT);
- // hypo length,in case of long header skip the padding byte
- dtch_header_len=(buflen > 128 ) ? 3 : 2 ; //sizeof(SCH_SUBHEADER_LONG)-1 : sizeof(SCH_SUBHEADER_SHORT);
- bsr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED);
+ bsr_header_len = 0;
phr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED);
- phr_ce_len = (UE_mac_inst[module_idP].PHR_reporting_active == 1) ? 1 /* sizeof(POWER_HEADROOM_CMD)*/: 0;
- if (phr_ce_len > 0) {
+ while (lcg_id < MAX_NUM_LCGID) {
+ if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]){
+ num_lcg_id_with_data ++;
+ }
+ lcg_id ++;
+ }
+
+ if (num_lcg_id_with_data){
+ LOG_D(MAC,"[UE %d] MAC Tx data pending at frame%d subframe %d nb LCG =%d Bytes for LCG0=%d LCG1=%d LCG2=%d LCG3=%d BSR Trigger status =%d TBS=%d\n",
+ module_idP,
+ frameP,
+ subframe,
+ num_lcg_id_with_data,
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[0],
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[1],
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[2],
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[3],
+ UE_mac_inst[module_idP].BSR_reporting_active, buflen);
+
+ }
+ //Restart ReTxBSR Timer at new grant indication (36.321)
+ if (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING){
+ UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);
+ }
+
+ // periodicBSR-Timer expires, trigger BSR
+ if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity)
+ && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF == 0)){
+ // Trigger BSR Periodic
+ UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PERIODIC;
+
+ LOG_D(MAC,"[UE %d] MAC BSR Triggered PeriodicBSR Timer expiry at frame%d subframe %d TBS=%d\n",
+ module_idP, frameP, subframe, buflen);
+
+ }
+
+ //Compute BSR Length if Regular or Periodic BSR is triggered
+ //WARNING: if BSR long is computed, it may be changed to BSR short during or after multiplexing if there remains less than 1 LCGROUP with data after Tx
+ if (UE_mac_inst[module_idP].BSR_reporting_active){
+
+ AssertFatal ((UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_PADDING) == 0 , "Inconsistent BSR Trigger=%d !\n",
+ UE_mac_inst[module_idP].BSR_reporting_active);
+
+ if (buflen >= 4){
+ //A Regular or Periodic BSR can only be sent if TBS >= 4 as transmitting only a BSR is not allowed if UE has data to transmit
+ bsr_header_len = 1;
+
+ if (num_lcg_id_with_data <= 1){
+ bsr_ce_len = sizeof(BSR_SHORT); //1 byte
+ }
+ else{
+ bsr_ce_len = BSR_LONG_SIZE; //3 bytes
+ }
+ }
+ }
+
+ bsr_len = bsr_ce_len + bsr_header_len;
+
+ phr_ce_len = (UE_mac_inst[module_idP].PHR_reporting_active == 1) ? 1 /* sizeof(POWER_HEADROOM_CMD)*/: 0;
+ if ((phr_ce_len > 0) && ((phr_ce_len + phr_header_len + bsr_len) <= buflen)){
phr_len = phr_ce_len + phr_header_len;
LOG_D(MAC,"[UE %d] header size info: PHR len %d (ce%d,hdr%d) buff_len %d\n",
module_idP, phr_len, phr_ce_len, phr_header_len, buflen);
} else {
phr_len=0;
- }
-
- bsr_ce_len = get_bsr_len (module_idP, buflen-phr_len);
-
- if (bsr_ce_len > 0 ) {
- bsr_len = bsr_ce_len + bsr_header_len;
- LOG_D(MAC,"[UE %d] header size info: dcch %d, dcch1 %d, dtch %d, bsr (ce%d,hdr%d) buff_len %d\n",
- module_idP, dcch_header_len,dcch1_header_len,dtch_header_len, bsr_ce_len, bsr_header_len, buflen);
- } else {
- bsr_len=0;
- //LOG_D(MAC,"[UE %d] Empty buffers, send a long BSR to reset the bsr at eNB \n ",Mod_id);
- // bsr_ce_len = sizeof(BSR_LONG);
- //bsr_len = bsr_ce_len + bsr_header_len;
+ phr_header_len = 0;
+ phr_ce_len = 0;
}
// check for UL bandwidth requests and add SR control element
@@ -1287,163 +1399,307 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
// check for UL bandwidth requests and add SR control element
// Check for DCCH first
+// TO DO: Unrool the loop to do it at least once to avoid the if num_sdu
+for (lcid=DCCH; lcid < DTCH ; lcid++) {
+ if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) {
- if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DCCH] == LCID_NOT_EMPTY) {
+ is_lcid_processed = FALSE;
+ lcid_rlc_pdu_count = 0;
- rlc_status = mac_rlc_status_ind(module_idP,
- UE_mac_inst[module_idP].crnti,
- eNB_index,
- frameP,
- ENB_FLAG_NO,
- MBMS_FLAG_NO, // eNB_index
- DCCH,
- (buflen-dcch_header_len-bsr_len-phr_len));
- LOG_D(MAC, "[UE %d] Frame %d : UL-DCCH -> ULSCH, RRC message has %d bytes to "
- "send (Transport Block size %d, mac header len %d)\n",
- module_idP,frameP, rlc_status.bytes_in_buffer,buflen,dcch_header_len);
+ //Multiplex all available DCCH RLC PDUs considering to multiplex the last PDU each time for maximize the data
+ //Adjust at the end of the loop
+ while ((!is_lcid_processed) && (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) {
- sdu_lengths[0] += mac_rlc_data_req(module_idP,
- UE_mac_inst[module_idP].crnti,
- eNB_index,
- frameP,
- ENB_FLAG_NO,
- MBMS_FLAG_NO,
- DCCH,
- (char *)&ulsch_buff[sdu_lengths[0]]);
+ // Workaround for issue in OAI eNB or EPC which are not able to process SRB2 message multiplexed with SRB1 on the same MAC PDU
+ if ((usim_test == 0) && (lcid == DCCH1) && (lcid_rlc_pdu_count == 0) && (num_sdus)) {
- sdu_length_total += sdu_lengths[0];
- sdu_lcids[0] = DCCH;
- LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]);
- num_sdus = 1;
- update_bsr(module_idP, frameP, eNB_index, DCCH, UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]);
- //header_len +=2;
- } else {
- dcch_header_len=0;
- num_sdus = 0;
+ // Skip SRB2 multiplex if at least one SRB1 SDU is already multiplexed
+ break;
+ }
+
+ buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
+
+ rlc_status = mac_rlc_status_ind(module_idP,
+ UE_mac_inst[module_idP].crnti,
+ eNB_index,
+ frameP,
+ ENB_FLAG_NO,
+ MBMS_FLAG_NO, // eNB_index
+ lcid,
+ buflen_remain);
+
+ // Workaround for BO issue in RLC AM ReTx : RLC BO can not be bigger than stored MAC BO
+ if (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] < rlc_status.bytes_in_buffer) {
+
+ LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d\n",
+ module_idP,frameP,subframe,
+ lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count);
+
+ // Skip multiplexing for the LCID
+ break;
+ }
+
+ /*
+ AssertFatal ( UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= rlc_status.bytes_in_buffer, "Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d Frame %d Subrame %d\n",
+ lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count,frameP,subframe);
+ */
+
+ if (rlc_status.bytes_in_buffer > 0) {
+
+
+ LOG_D(MAC, "[UE %d] Frame %d : UL-DCCH -> ULSCH, RLC SRB%d has %d bytes to "
+ "send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n",
+ module_idP,frameP, lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],buflen,bsr_len,phr_len,sdu_length_total,total_rlc_pdu_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
+
+
+ sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
+ UE_mac_inst[module_idP].crnti,
+ eNB_index,
+ frameP,
+ ENB_FLAG_NO,
+ MBMS_FLAG_NO,
+ lcid,
+ (char *)&ulsch_buff[sdu_length_total]);
+
+
+ AssertFatal (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n",
+ lcid,sdu_lengths[num_sdus],UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]);
+
+
+
+ sdu_length_total += sdu_lengths[num_sdus];
+ sdu_lcids[num_sdus] = lcid;
+ LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for SRB%d\n",module_idP,sdu_lengths[num_sdus],lcid);
+ //header_len +=2;
+ // update LCID remain buffer
+ UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] -= sdu_lengths[num_sdus];
+ /* Update BSR : substract transmitted data */
+ if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] >= sdu_lengths[num_sdus]){
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] -= sdu_lengths[num_sdus] ;
+ }
+ else {
+ LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Buffer occupancy =%d for LCGID%d is lower than data transmitted=%d for LCID%d\n",
+ module_idP,frameP,subframe,
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],
+ UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],
+ sdu_lengths[num_sdus],lcid);
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] = 0;
+ }
+
+ //Update the number of LCGID with data as BSR shall reflect status after BSR transmission
+ if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0))
+ {
+ num_lcg_id_with_data --;
+ // Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1
+ if ((bsr_len) && (num_lcg_id_with_data == 1))
+ {
+ bsr_ce_len = sizeof(BSR_SHORT);
+ bsr_len = bsr_ce_len + bsr_header_len;
+ }
+
+ }
+
+ if (buflen == (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1)) {
+ //No more remaining TBS after this PDU
+ //exit the function
+ rlc_pdu_header_len_last = 1;
+ is_lcid_processed = TRUE;
+ }
+ else {
+ rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ;
+
+ //Change to 1 byte if it does not fit in the TBS, ie last PDU
+ if (buflen <= (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) {
+ rlc_pdu_header_len_last = 1;
+ is_lcid_processed = TRUE;
+ }
+ }
+
+ //Update number of SDU
+ num_sdus ++;
+
+ //Update total MAC Header size for RLC PDUs and save last one
+ total_rlc_pdu_header_len += rlc_pdu_header_len_last;
+
+ } //end if (rlc_status.bytes_in_buffer > 0)
+ else {
+ // Switch to next LCID or exit the whole loop
+ is_lcid_processed = TRUE;
+ }
+ lcid_rlc_pdu_count ++;
+ }
+
+ UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY;
+ }
+}
+
+
+// Now Check for DTCH first
+// TO DO: do it according to Logical Channel Prioritization if at least 2 DTCH
+for (lcid=DTCH; lcid < MAX_NUM_LCID ; lcid++) {
+if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) {
+
+ is_lcid_processed = FALSE;
+ lcid_rlc_pdu_count = 0;
+
+ //Multiplex all available DTCH RLC PDUs considering to multiplex the last PDU each time for maximize the data
+ //Adjust at the end of the loop
+ while ((!is_lcid_processed) && (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) {
+
+ buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
+
+ rlc_status = mac_rlc_status_ind(module_idP,
+ UE_mac_inst[module_idP].crnti,
+ eNB_index,
+ frameP,
+ ENB_FLAG_NO,
+ MBMS_FLAG_NO, // eNB_index
+ lcid,
+ buflen_remain);
+
+ // Workaround for BO issue in RLC AM ReTx : RLC BO can not be bigger than stored MAC BO
+ if (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] < rlc_status.bytes_in_buffer) {
+
+ LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d\n",
+ module_idP,frameP,subframe,
+ lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count);
+
+ // Skip multiplexing for the LCID
+ break;
+ }
+
+ /*
+ AssertFatal ( UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= rlc_status.bytes_in_buffer, "Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d Frame %d Subrame %d\n",
+ lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count,frameP,subframe);
+ */
+
+ if (rlc_status.bytes_in_buffer > 0) {
+
+
+ LOG_D(MAC, "[UE %d] Frame %d : UL-DTCH -> ULSCH, RLC LCID%d has %d bytes to "
+ "send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n",
+ module_idP,frameP, lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],buflen,bsr_len,phr_len,sdu_length_total,total_rlc_pdu_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
+
+
+ sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
+ UE_mac_inst[module_idP].crnti,
+ eNB_index,
+ frameP,
+ ENB_FLAG_NO,
+ MBMS_FLAG_NO,
+ lcid,
+ (char *)&ulsch_buff[sdu_length_total]);
+
+ AssertFatal (sdu_lengths[num_sdus] < MAX_ULSCH_PAYLOAD_BYTES, "LCID=%d RLC PDU size = %d is too big\n",
+ lcid,sdu_lengths[num_sdus]);
+
+
+ AssertFatal (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n",
+ lcid,sdu_lengths[num_sdus],UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]);
+
+
+
+ sdu_length_total += sdu_lengths[num_sdus];
+ sdu_lcids[num_sdus] = lcid;
+ LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for LCID%d\n",module_idP,sdu_lengths[num_sdus],lcid);
+ //header_len +=2;
+ // update LCID remain buffer
+ UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] -= sdu_lengths[num_sdus];
+ /* Update BSR : substract transmitted data */
+ if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] >= sdu_lengths[num_sdus]){
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] -= sdu_lengths[num_sdus] ;
+ }
+ else {
+ LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Buffer occupancy =%d for LCGID%d is lower than data transmitted=%d for LCID%d\n",
+ module_idP,frameP,subframe,
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],
+ UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],
+ sdu_lengths[num_sdus],lcid);
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] = 0;
+ }
+
+ //Update the number of LCGID with data as BSR shall reflect status after BSR transmission
+ if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0))
+ {
+ num_lcg_id_with_data --;
+ // Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1
+ if ((bsr_len) && (num_lcg_id_with_data == 1))
+ {
+ bsr_ce_len = sizeof(BSR_SHORT);
+ bsr_len = bsr_ce_len + bsr_header_len;
+ }
+
+ }
+
+ if (buflen == (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1)) {
+ //No more remaining TBS after this PDU
+ //exit the function
+ rlc_pdu_header_len_last = 1;
+ is_lcid_processed = TRUE;
+ }
+ else {
+ rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ;
+
+ //Change to 1 byte if it does not fit in the TBS, ie last PDU
+ if (buflen <= (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) {
+ rlc_pdu_header_len_last = 1;
+ is_lcid_processed = TRUE;
+ }
+ }
+
+ //Update number of SDU
+ num_sdus ++;
+
+ //Update total MAC Header size for RLC PDUs and save last one
+ total_rlc_pdu_header_len += rlc_pdu_header_len_last;
+
+ } //end if (rlc_status.bytes_in_buffer > 0)
+ else {
+ // Switch to next LCID or exit the whole loop
+ is_lcid_processed = TRUE;
+ }
+ lcid_rlc_pdu_count ++;
+ }
+
+ UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY;
+ }
+}
+
+ //lcgid= get_bsr_lcgid(module_idP);
+
+ // Compute BSR Values and update Nb LCGID with data after multiplexing
+ num_lcg_id_with_data = 0;
+ lcg_id_bsr_trunc = 0;
+ for (lcg_id=0;lcg_id ULSCH, RRC message has %d bytes to"
- " send (Transport Block size %d, mac header len %d)\n",
- module_idP,frameP, rlc_status.bytes_in_buffer,buflen,dcch1_header_len);
-
- sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
- UE_mac_inst[module_idP].crnti,
- eNB_index,
- frameP,
- ENB_FLAG_NO,
- MBMS_FLAG_NO,
- DCCH1,
- (char *)&ulsch_buff[sdu_lengths[num_sdus]]);
- sdu_length_total += sdu_lengths[num_sdus];
- sdu_lcids[num_sdus] = DCCH1;
- LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH1\n",module_idP,sdu_lengths[num_sdus]);
- num_sdus++;
- //update_bsr(module_idP, frameP, DCCH1);
- //dcch_header_len +=2; // include dcch1
- } else {
- dcch1_header_len =0;
+ LOG_D(MAC,"[UE %d] Frame %d Subframe %d TX BSR Regular or Periodic size=%d BSR0=%d BSR1=%d BSR2=%d BSR3=%d\n",module_idP,frameP,subframe,bsr_ce_len,
+ UE_mac_inst[module_idP].scheduling_info.BSR[0],
+ UE_mac_inst[module_idP].scheduling_info.BSR[1],
+ UE_mac_inst[module_idP].scheduling_info.BSR[2],
+ UE_mac_inst[module_idP].scheduling_info.BSR[3]);
}
- dtch_header_len=0;
- dtch_header_len_last=0;
- for (lcid=NB_RB_MAX-1; lcid>=DTCH ; lcid--){
- dtch_header_len+=3;
- dtch_header_len_last=3;
-
- if ((UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) &&
- ((bsr_len+phr_len+dcch_header_len+dcch1_header_len+dtch_header_len+sdu_length_total) <= buflen)) {
-
- // optimize the dtch header lenght
- //if ((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH] > 128) &&
- /* if (((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH] >= 128) &&
- ((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH]+bsr_len+phr_len+dcch_header_len+dcch1_header_len+dtch_header_len) > buflen)&&
- buflen >=128 ))
- dtch_header_len = 3;//sizeof(SCH_SUBHEADER_LONG);
- else
- dtch_header_len = 2;//sizeof(SCH_SUBHEADER_SHORT);
- */
- rlc_status = mac_rlc_status_ind(module_idP,
- UE_mac_inst[module_idP].crnti,
- eNB_index,
- frameP,
- ENB_FLAG_NO,
- MBMS_FLAG_NO, // eNB_index
- lcid,
- buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total);
-
- LOG_D(MAC,"[UE %d] Frame %d : UL-DTCH -> ULSCH%d, %d bytes to send (Transport Block size %d, mac header len %d, BSR byte[%d] %d)\n",
- module_idP,frameP, lcid, rlc_status.bytes_in_buffer,buflen,dtch_header_len,
- lcid, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcid]);
-
- if (rlc_status.bytes_in_buffer > 0) {
- sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
- UE_mac_inst[module_idP].crnti,
- eNB_index,
- frameP,
- ENB_FLAG_NO,
- MBMS_FLAG_NO, // eNB_index
- lcid,
- (char *)&ulsch_buff[sdu_length_total]);
-
- //adjust dtch header
- LOG_D(MAC,"[UE %d] TX Got %d bytes for DTCH\n",module_idP,sdu_lengths[num_sdus]);
- sdu_lcids[num_sdus] = lcid;
- sdu_length_total += sdu_lengths[num_sdus];
- if (sdu_lengths[num_sdus] < 128) {
- dtch_header_len --;
- dtch_header_len_last --;
- }
- num_sdus++;
- UE_mac_inst[module_idP].ul_active = update_bsr(module_idP, frameP, eNB_index,lcid, UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]);
- } else {
- dtch_header_len -= 3;
- }
- } else { // no rlc pdu : generate the dummy header
- dtch_header_len -= 3;
- }
- }
-
- lcgid= get_bsr_lcgid(module_idP);
-
- if (lcgid < 0 ) {
- bsr_s = NULL;
- bsr_l = NULL ;
- } else if ((lcgid ==MAX_NUM_LCGID) && (bsr_ce_len == sizeof(BSR_LONG))) {
- bsr_s = NULL;
- bsr_l->Buffer_size0 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0];
- bsr_l->Buffer_size1 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1];
- bsr_l->Buffer_size2 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2];
- bsr_l->Buffer_size3 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3];
- LOG_D(MAC, "[UE %d] Frame %d report long BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 %d)\n", module_idP,frameP,
- UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0],
- UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1],
- UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2],
- UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]);
- } else if (bsr_ce_len == sizeof(BSR_SHORT)) {
- bsr_l = NULL;
- bsr_s->LCGID = lcgid;
- bsr_s->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcgid];
- LOG_D(MAC,"[UE %d] Frame %d report SHORT BSR with level %d for LCGID %d\n",
- module_idP, frameP, UE_mac_inst[module_idP].scheduling_info.BSR[lcgid],lcgid);
- } else {
- bsr_s = NULL;
- bsr_l = NULL;
- }
// build PHR and update the timers
if (phr_ce_len == sizeof(POWER_HEADROOM_CMD)) {
@@ -1458,37 +1714,146 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
LOG_T(MAC,"[UE %d] Frame %d: bsr s %p bsr_l %p, phr_p %p\n", module_idP,frameP,bsr_s, bsr_l, phr_p);
- if (dtch_header_len == 0 )
- dtch_header_len_last =0;
- // adjust the header length
- dcch_header_len_tmp = dcch_header_len;
- dtch_header_len_tmp = dtch_header_len;
-
- if (dtch_header_len==0) {
- dcch_header_len = (dcch_header_len>0)? 1: dcch_header_len;
- } else {
- dtch_header_len_last-=1;
- dtch_header_len= (dtch_header_len >0)? dtch_header_len - dtch_header_len_last : dtch_header_len;
+ // Check BSR padding: it is done after PHR according to Logical Channel Prioritization order
+ // Check for max padding size, ie MAC Hdr for last RLC PDU = 1
+ /* For Padding BSR:
+ - if the number of padding bits is equal to or larger than the size of the Short BSR plus its subheader but smaller than the size of the Long BSR plus its subheader:
+ - if more than one LCG has data available for transmission in the TTI where the BSR is transmitted: report Truncated BSR of the LCG with the highest priority logical channel with data available for transmission;
+ - else report Short BSR.
+ - else if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR.
+ */
+ if (sdu_length_total) {
+ padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - rlc_pdu_header_len_last + sdu_length_total + 1);
+ }
+ else {
+ padding_len = buflen - (bsr_len + phr_len);
}
- if ((buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total) <= 2) {
- short_padding = buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total;
+
+ if ((padding_len) && (bsr_len == 0))
+ {
+ /* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR*/
+ if (padding_len >= (1+BSR_LONG_SIZE))
+ {
+ bsr_ce_len = BSR_LONG_SIZE;
+ bsr_header_len = 1;
+ // Trigger BSR Padding
+ UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PADDING;
+
+
+ } else if (padding_len >= (1+sizeof(BSR_SHORT))) {
+ bsr_ce_len = sizeof(BSR_SHORT);
+ bsr_header_len = 1;
+
+ if (num_lcg_id_with_data > 1)
+ {
+ // REPORT TRUNCATED BSR
+ //Get LCGID of highest priority LCID with data
+ for (lcid=DCCH; lcid < MAX_NUM_LCID ; lcid++) {
+ if (UE_mac_inst[module_idP].logicalChannelConfig[lcid] != NULL) {
+ lcg_id = UE_mac_inst[module_idP].scheduling_info.LCGID[lcid];
+
+ if ((lcg_id < MAX_NUM_LCGID) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id])
+ && (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority)) {
+ highest_priority = UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority;
+ lcg_id_bsr_trunc = lcg_id;
+ }
+ }
+ }
+ }
+ else
+ {
+ //Report SHORT BSR, clear bsr_t
+ bsr_t = NULL;
+ }
+
+ // Trigger BSR Padding
+ UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PADDING;
+ }
+ bsr_len = bsr_header_len + bsr_ce_len;
+ }
+
+ //Fill BSR Infos
+ if (bsr_ce_len == 0 ) {
+ bsr_s = NULL;
+ bsr_l = NULL;
+ bsr_t = NULL;
+ } else if (bsr_ce_len == BSR_LONG_SIZE) {
+ bsr_s = NULL;
+ bsr_t = NULL;
+ bsr_l->Buffer_size0 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0];
+ bsr_l->Buffer_size1 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1];
+ bsr_l->Buffer_size2 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2];
+ bsr_l->Buffer_size3 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3];
+
+ LOG_D(MAC, "[UE %d] Frame %d subframe %d BSR Trig=%d report long BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 %d)\n", module_idP,frameP,subframe,
+ UE_mac_inst[module_idP].BSR_reporting_active,
+ UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0],
+ UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1],
+ UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2],
+ UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]);
+
+ } else if (bsr_ce_len == sizeof(BSR_SHORT)) {
+ bsr_l = NULL;
+ if ((bsr_t != NULL) && (UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_PADDING)) {
+ //Truncated BSR
+ bsr_s = NULL;
+ bsr_t->LCGID = lcg_id_bsr_trunc;
+ bsr_t->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc];
+
+ LOG_D(MAC,"[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n",
+ module_idP, frameP, subframe, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc);
+
+ }
+ else
+ {
+ bsr_t = NULL;
+ bsr_s->LCGID = lcg_id_bsr_trunc;
+ bsr_s->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc];
+
+ LOG_D(MAC,"[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n",
+ module_idP, frameP, subframe, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc);
+ }
+ }
+
+// 1-bit padding or 2-bit padding special padding subheader
+// Check for max padding size, ie MAC Hdr for last RLC PDU = 1
+ if (sdu_length_total) {
+ padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - rlc_pdu_header_len_last + sdu_length_total + 1);
+ }
+ else {
+ padding_len = buflen - (bsr_len + phr_len);
+ }
+
+ if (padding_len <= 2) {
+ short_padding = padding_len;
+ // only add padding header
post_padding = 0;
- } else {
- if ((buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total) == buflen) {
+ //update total MAC Hdr size for RLC data
+ if (sdu_length_total) {
+ total_rlc_pdu_header_len = total_rlc_pdu_header_len - rlc_pdu_header_len_last + 1;
+ rlc_pdu_header_len_last = 1;
+ }
+ }
+ else if (sdu_length_total) {
+ post_padding = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
+ // If by adding MAC Hdr for last RLC PDU the padding is 0 then set MAC Hdr for last RLC PDU = 1 and compute 1 or 2 byte padding
+ if (post_padding == 0) {
+ total_rlc_pdu_header_len -= rlc_pdu_header_len_last;
+ padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
+ short_padding = padding_len;
+ total_rlc_pdu_header_len ++;
+ }
+ }
+ else {
+ if (padding_len == buflen) {// nona mac pdu
*access_mode=CANCELED_ACCESS;
}
short_padding = 0;
- if (dtch_header_len==0) {
- dcch_header_len = dcch_header_len_tmp;
- } else {
- dtch_header_len= dtch_header_len_tmp;
- }
-
- post_padding = buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total -1 ;
+ post_padding = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
}
// Generate header
@@ -1501,33 +1866,64 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
sdu_lcids, // sdu lcid
phr_p, // power headroom
NULL, // crnti
- NULL, // truncated bsr
+ bsr_t, // truncated bsr
bsr_s, // short bsr
bsr_l,
post_padding); // long_bsr
LOG_D(MAC,
- "[UE %d] Generate header :bufflen %d sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d, dcch_header_len %d, dtch_header_len %d, padding %d,post_padding %d, bsr len %d, phr len %d, reminder %d \n",
- module_idP,buflen, sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],payload_offset, dcch_header_len, dtch_header_len,
+ "[UE %d] Generate header :bufflen %d sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d, total_rlc_pdu_header_len %d, padding %d,post_padding %d, bsr len %d, phr len %d, reminder %d \n",
+ module_idP,buflen, sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],payload_offset, total_rlc_pdu_header_len,
short_padding,post_padding, bsr_len, phr_len,buflen-sdu_length_total-payload_offset);
// cycle through SDUs and place in ulsch_buffer
- memcpy(&ulsch_buffer[payload_offset],ulsch_buff,sdu_length_total);
+ if (sdu_length_total) {
+ memcpy(&ulsch_buffer[payload_offset],ulsch_buff,sdu_length_total);
+ }
// fill remainder of DLSCH with random data
- for (j=0; j<(buflen-sdu_length_total-payload_offset); j++) {
- ulsch_buffer[payload_offset+sdu_length_total+j] = (char)(taus()&0xff);
+ if (post_padding) {
+ for (j=0; j<(buflen-sdu_length_total-payload_offset); j++) {
+ ulsch_buffer[payload_offset+sdu_length_total+j] = (char)(taus()&0xff);
+ }
}
LOG_D(MAC,"[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n",
module_idP,payload_offset, sdu_length_total);
UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
+
+ /* Actions when a BSR is sent */
+ if (bsr_ce_len)
+ {
+ LOG_D(MAC,"[UE %d] MAC BSR Sent !! bsr (ce%d,hdr%d) buff_len %d\n",
+ module_idP, bsr_ce_len, bsr_header_len, buflen);
+
+ // Reset ReTx BSR Timer
+ UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);
+
+ LOG_D(MAC,"[UE %d] MAC ReTx BSR Timer Reset =%d\n",
+ UE_mac_inst[module_idP].scheduling_info.retxBSR_SF);
+
+ // Reset Periodic Timer except when BSR is truncated
+ if ((bsr_t == NULL) && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity))
+ {
+ UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer);
+
+ LOG_D(MAC,"[UE %d] MAC Periodic BSR Timer Reset =%d\n",
+ UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF);
+
+ }
+
+ // Reset BSR Trigger flags
+ UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
+ }
+
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_OUT);
stop_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu);
if (opt_enabled) {
- trace_pdu(0, ulsch_buffer, buflen, module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].subframe, 0, 0);
+ trace_pdu(0, ulsch_buffer, buflen, module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, 0);
LOG_D(OPT,"[UE %d][ULSCH] Frame %d trace pdu for rnti %x with size %d\n",
- module_idP, UE_mac_inst[module_idP].subframe, UE_mac_inst[module_idP].crnti, buflen);
+ module_idP, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, UE_mac_inst[module_idP].crnti, buflen);
}
}
@@ -1542,14 +1938,15 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
UE_L2_STATE_t
ue_scheduler(
const module_id_t module_idP,
- const frame_t frameP,
- const sub_frame_t subframeP,
+ const frame_t rxFrameP,
+ const sub_frame_t rxSubframeP,
+ const frame_t txFrameP,
+ const sub_frame_t txSubframeP,
const lte_subframe_t directionP,
const uint8_t eNB_indexP,
const int CC_id)
//------------------------------------------------------------------------------
{
-
int lcid; // lcid index
int TTI= 1;
int bucketsizeduration = -1;
@@ -1558,6 +1955,7 @@ ue_scheduler(
// int8_t lcg_id;
struct RACH_ConfigCommon *rach_ConfigCommon = (struct RACH_ConfigCommon *)NULL;
protocol_ctxt_t ctxt;
+
#if defined(ENABLE_ITTI)
MessageDef *msg_p;
const char *msg_name;
@@ -1567,7 +1965,7 @@ ue_scheduler(
start_meas(&UE_mac_inst[module_idP].ue_scheduler);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_IN);
- PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_NO, UE_mac_inst[module_idP].crnti, frameP, subframeP,eNB_indexP);
+ PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_NO, UE_mac_inst[module_idP].crnti, txFrameP, txSubframeP,eNB_indexP);
#if defined(ENABLE_ITTI)
do {
@@ -1606,11 +2004,13 @@ ue_scheduler(
//LG#ifdef EXMIMO
pdcp_run(&ctxt);
//#endif
- UE_mac_inst[module_idP].frame = frameP;
- UE_mac_inst[module_idP].subframe = subframeP;
+ UE_mac_inst[module_idP].txFrame = txFrameP;
+ UE_mac_inst[module_idP].txSubframe = txSubframeP;
+ UE_mac_inst[module_idP].rxFrame = rxFrameP;
+ UE_mac_inst[module_idP].rxSubframe = rxSubframeP;
#ifdef CELLULAR
- rrc_rx_tx(module_idP, frameP, 0, eNB_indexP);
+ rrc_rx_tx(module_idP, txFrameP, 0, eNB_indexP);
#else
switch (rrc_rx_tx(&ctxt,
@@ -1664,7 +2064,7 @@ ue_scheduler(
//return(RRC_OK);
}
- LOG_I(MAC,"Frame %d: Contention resolution timer %d/%d\n",frameP,UE_mac_inst[module_idP].RA_contention_resolution_cnt,
+ LOG_I(MAC,"Frame %d: Contention resolution timer %d/%d\n",txFrameP,UE_mac_inst[module_idP].RA_contention_resolution_cnt,
((1+rach_ConfigCommon->ra_SupervisionInfo.mac_ContentionResolutionTimer)<<3));
UE_mac_inst[module_idP].RA_contention_resolution_cnt++;
@@ -1680,13 +2080,9 @@ ue_scheduler(
}
- // call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp. This should implement the procedures
- // outlined in Sections 5.4.4 an 5.4.5 of 36.321
- // Put this in another function
-
// Get RLC status info and update Bj for all lcids that are active
- for (lcid=DCCH; lcid <= DTCH; lcid++ ) {
- if ((lcid == 0) ||(UE_mac_inst[module_idP].logicalChannelConfig[lcid])) {
+ for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++ ) {
+ if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]) {
// meausre the Bj
if ((directionP == SF_UL)&& (UE_mac_inst[module_idP].scheduling_info.Bj[lcid] >= 0)) {
if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters) {
@@ -1704,16 +2100,43 @@ ue_scheduler(
}
}
- if (update_bsr(module_idP,frameP, eNB_indexP, lcid, UE_mac_inst[module_idP].scheduling_info.LCGID[lcid])) {
- UE_mac_inst[module_idP].scheduling_info.SR_pending= 1;
- LOG_D(MAC,"[UE %d][SR] Frame %d subframe %d SR for PUSCH is pending for LCGID %d with BSR level %d (%d bytes in RLC)\n",
- module_idP, frameP,subframeP,UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],
- UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],
- UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
+
+ /*
+ if (lcid == DCCH) {
+ LOG_D(MAC,"[UE %d][SR] Frame %d subframe %d Pending data for SRB1=%d for LCGID %d \n",
+ module_idP, frameP,subframeP,UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],
+// UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]);
}
+ */
}
}
+ // Call BSR procedure as described in Section 5.4.5 in 36.321
+
+ // First check ReTxBSR Timer because it is always configured
+ // Decrement ReTxBSR Timer if it is running and not null
+ if ((UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING)
+ && (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != 0)){
+ UE_mac_inst[module_idP].scheduling_info.retxBSR_SF --;
+ }
+
+ // Decrement Periodic Timer if it is running and not null
+ if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING)
+ && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF != 0)){
+ UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF--;
+ }
+
+ //Check whether Regular BSR is triggered
+ if (update_bsr(module_idP,txFrameP, txSubframeP,eNB_indexP) == TRUE) {
+ // call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp. This should implement the procedures
+ // outlined in Sections 5.4.4 an 5.4.5 of 36.321
+ UE_mac_inst[module_idP].scheduling_info.SR_pending= 1;
+ // Regular BSR trigger
+ UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_REGULAR;
+ LOG_D(MAC,"[UE %d][BSR] Regular BSR Triggered Frame %d subframe %d SR for PUSCH is pending\n",
+ module_idP, txFrameP,txSubframeP);
+ }
+
// UE has no valid phy config dedicated || no valid/released SR
if ((UE_mac_inst[module_idP].physicalConfigDedicated == NULL)) {
// cancel all pending SRs
@@ -1926,103 +2349,147 @@ int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8
}
#endif
-int get_bsr_lcgid (module_id_t module_idP)
-{
- int lcgid, lcgid_tmp=-1;
- int num_active_lcgid = 0;
- for (lcgid = 0 ; lcgid < MAX_NUM_LCGID; lcgid++) {
- if (UE_mac_inst[module_idP].scheduling_info.BSR[lcgid] > 0 ) {
- lcgid_tmp = lcgid;
- num_active_lcgid+=1;
- }
- }
-
- if (num_active_lcgid == 0) {
- return -1;
- } else if (num_active_lcgid == 1) {
- return lcgid_tmp;
- } else {
- return MAX_NUM_LCGID;
- }
-}
-
-uint8_t get_bsr_len (module_id_t module_idP, uint16_t buflen)
-{
-
- int lcgid=0;
- uint8_t bsr_len=0, num_lcgid=0;
- int pdu = 0;
-
-
- for (lcgid=0; lcgid < MAX_NUM_LCGID; lcgid++ ) {
- if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] > 0 ) {
- pdu += (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] + bsr_len + 2); //2 = sizeof(SCH_SUBHEADER_SHORT)
- }
-
- if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] > 128 ) { // long header size: adjust the header size
- pdu += 1;
- }
-
- // current phy buff can not transport all sdu for this lcgid -> transmit a bsr for this lcgid
-
- if ( (pdu > buflen) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] > 0 ) ) {
- num_lcgid +=1;
- bsr_len = (num_lcgid >= 2 ) ? sizeof(BSR_LONG) : sizeof(BSR_SHORT) ;
- }
-
- LOG_D(MAC,"BSR Bytes %d for lcgid %d bsr len %d num lcgid %d\n", UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid], lcgid, bsr_len, num_lcgid);
- }
-
- if ( bsr_len > 0 )
- LOG_D(MAC,"[UE %d] Prepare a %s (Transport Block Size %d, MAC pdu Size %d) \n",
- module_idP, map_int_to_str(BSR_names, bsr_len), buflen, pdu);
-
- return bsr_len;
-}
-
-
-boolean_t update_bsr(module_id_t module_idP, frame_t frameP, eNB_index_t eNB_index, uint8_t lcid, uint8_t lcg_id)
+boolean_t update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP,eNB_index_t eNB_index)
{
mac_rlc_status_resp_t rlc_status;
- boolean_t sr_pending = FALSE;
+ boolean_t bsr_regular_triggered = FALSE;
+ uint8_t lcid;
+ uint8_t lcgid;
+ uint8_t num_lcid_with_data = 0; // for LCID with data only if LCGID is defined
+ uint16_t lcgid_buffer_remain[MAX_NUM_LCGID] = {0,0,0,0};
+ int32_t lcid_bytes_in_buffer[MAX_NUM_LCID];
+ /* Array for ordering LCID with data per decreasing priority order */
+ uint8_t lcid_reordered_array[MAX_NUM_LCID]=
+ {MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID};
+ uint8_t pos_next = 0;
+ uint8_t highest_priority = 16;
+ uint8_t array_index = 0;
-
- if ((lcg_id < 0) || (lcg_id >= MAX_NUM_LCGID) ) {
- return sr_pending;
+ // Reset All BSR Infos
+ lcid_bytes_in_buffer[0] = 0;
+ for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++)
+ {
+ // Reset transmission status
+ lcid_bytes_in_buffer[lcid] = 0;
+ UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid]=LCID_EMPTY;
}
- // fixme: need a better way to reset
- if ((lcid == DCCH) || (lcid == DTCH)) {
- UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id]=0;
- UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]=0;
+ for (lcgid=0; lcgid < MAX_NUM_LCGID; lcgid++)
+ {
+ // Reset Buffer Info
+ UE_mac_inst[module_idP].scheduling_info.BSR[lcgid]=0;
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid]=0;
}
- // for (lcid =0 ; lcid < MAX_NUM_LCID; lcid++) {
- if (UE_mac_inst[module_idP].scheduling_info.LCGID[lcid] == lcg_id) {
- rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,ENB_FLAG_NO,MBMS_FLAG_NO,
- lcid,
- 0);
+ //Get Buffer Occupancy and fill lcid_reordered_array
+ for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++)
+ {
+ if (UE_mac_inst[module_idP].logicalChannelConfig[lcid])
+ {
+ lcgid = UE_mac_inst[module_idP].scheduling_info.LCGID[lcid];
+
+ // Store already available data to transmit per Group
+ if (lcgid < MAX_NUM_LCGID)
+ {
+ lcgid_buffer_remain[lcgid] += UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid];
+ }
+
+ rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,ENB_FLAG_NO,MBMS_FLAG_NO,
+ lcid,
+ 0);
+
+ lcid_bytes_in_buffer[lcid] = rlc_status.bytes_in_buffer;
+
+ if (rlc_status.bytes_in_buffer > 0)
+ {
+ LOG_D(MAC,"[UE %d] PDCCH Tick : LCID%d LCGID%d has data to transmit =%d bytes at frame %d subframe %d\n",
+ module_idP, lcid,lcgid,rlc_status.bytes_in_buffer,frameP,subframeP);
+
+ UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_NOT_EMPTY;
+ //Update BSR_bytes and position in lcid_reordered_array only if Group is defined
+ if (lcgid < MAX_NUM_LCGID)
+ {
+ num_lcid_with_data ++;
+ // sum lcid buffer which has same lcgid
+ UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] += rlc_status.bytes_in_buffer;
+
+ //Fill in the array
+ array_index = 0;
+ do
+ {
+ if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority)
+ {
+ //Insert if priority is higher or equal (lower or equal in value)
+ for (pos_next=num_lcid_with_data-1; pos_next > array_index; pos_next--)
+ {
+ lcid_reordered_array[pos_next] = lcid_reordered_array[pos_next - 1];
+
+ }
+ lcid_reordered_array[array_index] = lcid;
+ break;
+
+ }
+ array_index ++;
+ }
+ while ((array_index < num_lcid_with_data) && (array_index < MAX_NUM_LCID));
+ }
+ }
+ }
- if (rlc_status.bytes_in_buffer > 0 ) {
- sr_pending = TRUE;
- UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_NOT_EMPTY;
- UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id] += locate (BSR_TABLE,BSR_TABLE_SIZE, rlc_status.bytes_in_buffer);
- UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id] += rlc_status.bytes_in_buffer;
- // UE_mac_inst[module_idP].scheduling_info.BSR_short_lcid = lcid; // only applicable to short bsr
- LOG_D(MAC,"[UE %d] BSR level %d (LCGID %d, rlc buffer %d byte)\n",
- module_idP, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id],lcg_id, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]);
- } else {
- UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid]=LCID_EMPTY;
- }
}
- //}
- return sr_pending;
+ // Check whether a regular BSR can be triggered according to the first cases in 36.321
+ if (num_lcid_with_data)
+ {
+ LOG_D(MAC,"[UE %d] PDCCH Tick at frame %d subframe %d: NumLCID with data=%d Reordered LCID0=%d LCID1=%d LCID2=%d\n",
+ module_idP, frameP, subframeP,num_lcid_with_data,lcid_reordered_array[0],lcid_reordered_array[1],lcid_reordered_array[2]);
+
+ for (array_index=0; array_index < num_lcid_with_data; array_index++)
+ {
+ lcid = lcid_reordered_array[array_index];
+ /* UL data, for a logical channel which belongs to a LCG, becomes available for transmission in the RLC entity
+ either the data belongs to a logical channel with higher priority than the priorities of the logical channels
+ which belong to any LCG and for which data is already available for transmission
+ */
+ if ((UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] == 0)
+ /* or there is no data available for any of the logical channels which belong to a LCG */
+ ||(lcgid_buffer_remain[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0)
+ )
+ {
+ bsr_regular_triggered = TRUE;
+
+ LOG_D(MAC,"[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%d data become available at frame %d subframe %d\n",
+ module_idP, lcid,UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],frameP, subframeP);
+
+ break;
+ }
+ }
+
+ // Trigger Regular BSR if ReTxBSR Timer has expired and UE has data for transmission
+ if (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF == 0)
+ {
+ bsr_regular_triggered = TRUE;
+
+ if ((UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_REGULAR) == 0) {
+ LOG_I(MAC,"[UE %d] PDCCH Tick : MAC BSR Triggered ReTxBSR Timer expiry at frame %d subframe %d\n",
+ module_idP, frameP, subframeP);
+ }
+
+ }
+ }
+
+ //Store Buffer Occupancy in remain buffers for next TTI
+ for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++)
+ {
+ UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] = lcid_bytes_in_buffer[lcid];
+ }
+
+ return bsr_regular_triggered;
}
-uint8_t locate (const uint32_t *table, int size, int value)
+uint8_t locate_BsrIndexByBufferSize (const uint32_t *table, int size, int value)
{
uint8_t ju, jm, jl;
@@ -2121,7 +2588,7 @@ int get_sf_periodicBSRTimer(uint8_t sf_offset)
case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity:
default:
- return -1;
+ return 0xFFFF;
break;
}
}
diff --git a/openair2/LAYER2/MAC/vars.h b/openair2/LAYER2/MAC/vars.h
index 83d159f910..236439c6e5 100644
--- a/openair2/LAYER2/MAC/vars.h
+++ b/openair2/LAYER2/MAC/vars.h
@@ -45,6 +45,15 @@ const uint32_t BSR_TABLE[BSR_TABLE_SIZE]= {0,10,12,14,17,19,22,26,31,36,42,49,57
1326,1552,1817,2127,2490,2915,3413,3995,4677,5467,6411,7505,8787,10287,12043,14099,
16507,19325,22624,26487,31009,36304,42502,49759,58255,68201,79846,93479,109439, 128125,150000, 300000
};
+// extended bsr table--currently not used
+const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE] = {0,10,13,16,19,23,29,35,43,53,65,80,98,120,147,
+ 181,223,274,337,414,509,625,769,945,1162,1429,
+ 1757,2161,2657,3267,4017,4940,6074,7469,9185,
+ 11294,13888,17077,20999,25822,31752,39045,48012,
+ 59039,72598,89272,109774,134986,165989,204111,
+ 250990,308634,379519,466683,573866,705666,867737,
+ 1067031,1312097,1613447,1984009,2439678,3000000,
+ 6000000};
//uint32_t EBSR_Level[63]={0,10,13,16,19,23,29,35,43,53,65,80,98,120,147,181};
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index fe85c81de0..2ff2d90de9 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -1057,6 +1057,7 @@ rrc_pdcp_config_asn1_req (
#ifdef Rel10
,PMCH_InfoList_r9_t* const pmch_InfoList_r9_pP
#endif
+ ,rb_id_t *const defaultDRB
)
//-----------------------------------------------------------------------------
{
@@ -1078,6 +1079,8 @@ rrc_pdcp_config_asn1_req (
hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
hashtable_rc_t h_rc;
+ hash_key_t key_defaultDRB = HASHTABLE_NOT_A_KEY_VALUE;
+ hashtable_rc_t h_defaultDRB_rc;
#ifdef Rel10
int i,j;
MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
@@ -1098,7 +1101,7 @@ rrc_pdcp_config_asn1_req (
srb_id = srb2add_list_pP->list.array[cnt]->srb_Identity;
srb_toaddmod_p = srb2add_list_pP->list.array[cnt];
rlc_type = RLC_MODE_AM;
- lc_id = srb_id;// + 2;
+ lc_id = srb_id;
key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, srb_id, SRB_FLAG_YES);
h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
@@ -1194,8 +1197,19 @@ rrc_pdcp_config_asn1_req (
drb_toaddmod_p = drb2add_list_pP->list.array[cnt];
drb_id = drb_toaddmod_p->drb_Identity;// + drb_id_offset;
+ if (drb_toaddmod_p->logicalChannelIdentity) {
+ lc_id = *(drb_toaddmod_p->logicalChannelIdentity);
+ } else {
+ LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" logicalChannelIdentity is missing in DRB-ToAddMod information element!\n",
+ PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
+ continue;
+ }
+
+ if (lc_id == 1 || lc_id == 2) {
+ LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity = %d is invalid in RRC message when adding DRB!\n", PROTOCOL_CTXT_ARGS(ctxt_pP), lc_id);
+ continue;
+ }
- lc_id = drb_id + 2;
DevCheck4(drb_id < maxDRB, drb_id, maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, drb_id, SRB_FLAG_NO);
h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
@@ -1211,7 +1225,21 @@ rrc_pdcp_config_asn1_req (
pdcp_p = calloc(1, sizeof(pdcp_t));
h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
- if (h_rc != HASH_TABLE_OK) {
+ // save the first configured DRB-ID as the default DRB-ID
+ if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
+ key_defaultDRB = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag);
+ h_defaultDRB_rc = hashtable_insert(pdcp_coll_p, key_defaultDRB, pdcp_p);
+ } else {
+ h_defaultDRB_rc = HASH_TABLE_OK; // do not trigger any error handling if this is not a default DRB
+ }
+
+ if (h_defaultDRB_rc != HASH_TABLE_OK) {
+ LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD default DRB key 0x%"PRIx64" FAILED\n",
+ PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
+ key_defaultDRB);
+ free(pdcp_p);
+ return TRUE;
+ } else if (h_rc != HASH_TABLE_OK) {
LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD key 0x%"PRIx64" FAILED\n",
PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
key);
@@ -1305,7 +1333,6 @@ rrc_pdcp_config_asn1_req (
for (cnt=0; cntlist.count; cnt++) {
pdrb_id_p = drb2release_list_pP->list.array[cnt];
drb_id = *pdrb_id_p;
- lc_id = drb_id + 2;
key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, srb_id, SRB_FLAG_NO);
h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
@@ -1315,6 +1342,7 @@ rrc_pdcp_config_asn1_req (
drb_id);
continue;
}
+ lc_id = pdcp_p->lcid;
action = CONFIG_ACTION_REMOVE;
pdcp_config_req_asn1 (
@@ -1334,6 +1362,20 @@ rrc_pdcp_config_asn1_req (
kRRCint_pP,
kUPenc_pP);
h_rc = hashtable_remove(pdcp_coll_p, key);
+
+ if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
+ // default DRB being removed. nevertheless this shouldn't happen as removing default DRB is not allowed in standard
+ key_defaultDRB = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag);
+ h_defaultDRB_rc = hashtable_get(pdcp_coll_p, key_defaultDRB, (void**)&pdcp_p);
+
+ if (h_defaultDRB_rc == HASH_TABLE_OK) {
+ h_defaultDRB_rc = hashtable_remove(pdcp_coll_p, key_defaultDRB);
+ } else {
+ LOG_E(PDCP, PROTOCOL_CTXT_FMT" PDCP REMOVE FAILED default DRB\n", PROTOCOL_CTXT_ARGS(ctxt_pP));
+ }
+ } else {
+ key_defaultDRB = HASH_TABLE_OK; // do not trigger any error handling if this is not a default DRB
+ }
}
}
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
index 5bff425abe..366f79dc9d 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
@@ -271,6 +271,7 @@ public_pdcp(void rrc_pdcp_config_req (
* \param[in] kRRCenc RRC encryption key
* \param[in] kRRCint RRC integrity key
* \param[in] kUPenc User-Plane encryption key
+* \param[in] defaultDRB Default DRB ID
* \return A status about the processing, OK or error code.
*/
public_pdcp(
@@ -286,6 +287,7 @@ public_pdcp(
#ifdef Rel10
,PMCH_InfoList_r9_t *pmch_InfoList_r9
#endif
+ ,rb_id_t *const defaultDRB
));
/*! \fn boolean_t pdcp_config_req_asn1 (const protocol_ctxt_t* const ctxt_pP, srb_flag_t srb_flagP, uint32_t action, rb_id_t rb_id, uint8_t rb_sn, uint8_t rb_report, uint16_t header_compression_profile, uint8_t security_mode)
@@ -459,12 +461,25 @@ protected_pdcp(unsigned char pdcp_input_sdu_buffer[MAX_IP_PACKET_SIZE];
protected_pdcp(sdu_size_t pdcp_input_index_header;)
protected_pdcp(sdu_size_t pdcp_input_sdu_size_read;)
protected_pdcp(sdu_size_t pdcp_input_sdu_remaining_size_to_read;)
+
#define PDCP_COLL_KEY_VALUE(mODULE_iD, rNTI, iS_eNB, rB_iD, iS_sRB) \
((hash_key_t)mODULE_iD | \
(((hash_key_t)(rNTI)) << 8) | \
(((hash_key_t)(iS_eNB)) << 24) | \
(((hash_key_t)(rB_iD)) << 25) | \
- (((hash_key_t)(iS_sRB)) << 33))
+ (((hash_key_t)(iS_sRB)) << 33) | \
+ (((hash_key_t)(0x55)) << 34))
+
+// hash key to the same PDCP as indexed by PDCP_COLL_KEY_VALUE(... rB_iD, iS_sRB=0) where rB_iD
+// is the default DRB ID. The hidden code 0x55 indicates the key is indexed by (rB_iD,is_sRB)
+// whereas the hidden code 0xaa indicates the key is for default DRB only
+#define PDCP_COLL_KEY_DEFAULT_DRB_VALUE(mODULE_iD, rNTI, iS_eNB) \
+ ((hash_key_t)mODULE_iD | \
+ (((hash_key_t)(rNTI)) << 8) | \
+ (((hash_key_t)(iS_eNB)) << 24) | \
+ (((hash_key_t)(0xff)) << 25) | \
+ (((hash_key_t)(0x00)) << 33) | \
+ (((hash_key_t)(0xaa)) << 34))
// service id max val is maxServiceCount = 16 (asn1_constants.h)
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
index 8f5d0635f0..eb78a4ca7c 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
@@ -67,6 +67,7 @@ extern int otg_enabled;
#ifdef PDCP_USE_NETLINK
#include
#include
+#include "NETWORK_DRIVER/UE_IP/constant.h"
extern char nl_rx_buf[NL_MAX_PAYLOAD];
extern struct sockaddr_nl nas_src_addr, nas_dest_addr;
@@ -186,7 +187,7 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const ctxt_pP)
ret = sendmsg(nas_sock_fd,&nas_msg_tx,0);
if (ret<0) {
- LOG_D(PDCP, "[PDCP_FIFOS] sendmsg returns %d (errno: %d)\n", ret, errno);
+ LOG_E(PDCP, "[PDCP_FIFOS] sendmsg returns %d (errno: %d)\n", ret, errno);
MSC_LOG_TX_MESSAGE_FAILED(
(ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
(ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
@@ -423,18 +424,22 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
return 0;
# else /* PDCP_USE_NETLINK_QUEUES*/
int len = 1;
+ int msg_len;
rb_id_t rab_id = 0;
-
- while (len > 0) {
+ int rlc_data_req_flag = 3;
+
+ while ((len > 0) && (rlc_data_req_flag !=0)) {
len = recvmsg(nas_sock_fd, &nas_msg_rx, 0);
if (len<=0) {
// nothing in pdcp NAS socket
//LOG_D(PDCP, "[PDCP][NETLINK] Nothing in socket, length %d \n", len);
} else {
+
+ msg_len = len;
for (nas_nlh_rx = (struct nlmsghdr *) nl_rx_buf;
- NLMSG_OK (nas_nlh_rx, len);
- nas_nlh_rx = NLMSG_NEXT (nas_nlh_rx, len)) {
+ NLMSG_OK (nas_nlh_rx, msg_len);
+ nas_nlh_rx = NLMSG_NEXT (nas_nlh_rx, msg_len)) {
if (nas_nlh_rx->nlmsg_type == NLMSG_DONE) {
LOG_D(PDCP, "[PDCP][NETLINK] RX NLMSG_DONE\n");
@@ -491,6 +496,10 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
ctxt.frame = ctxt_cpy.frame;
ctxt.enb_flag = ctxt_cpy.enb_flag;
+#ifdef PDCP_DEBUG
+ LOG_I(PDCP, "[PDCP][NETLINK] pdcp_read_header_g.rb_id = %d\n", pdcp_read_header_g.rb_id);
+#endif
+
if (ctxt_cpy.enb_flag) {
ctxt.module_id = 0;
rab_id = pdcp_read_header_g.rb_id % maxDRB;
@@ -586,11 +595,21 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
}
} else { // enb_flag
if (rab_id != 0) {
- rab_id = rab_id % maxDRB;
- key = PDCP_COLL_KEY_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
- h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
+ if (rab_id == UE_IP_DEFAULT_RAB_ID) {
+ LOG_D(PDCP, "PDCP_COLL_KEY_DEFAULT_DRB_VALUE(module_id=%d, rnti=%x, enb_flag=%d)\n",
+ ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
+ key = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
+ h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
+ } else {
+ rab_id = rab_id % maxDRB;
+ LOG_D(PDCP, "PDCP_COLL_KEY_VALUE(module_id=%d, rnti=%x, enb_flag=%d, rab_id=%d, SRB_FLAG=%d)\n",
+ ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
+ key = PDCP_COLL_KEY_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
+ h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
+ }
if (h_rc == HASH_TABLE_OK) {
+ rab_id = pdcp_p->rb_id;
#ifdef PDCP_DEBUG
LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n",
ctxt.frame,
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
index 2ff1a6c4b6..ded7dc0783 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
@@ -53,6 +53,7 @@ rlc_am_get_buffer_occupancy_in_bytes (
uint32_t header_overhead;
// priority of control trafic
+ rlc_pP->status_buffer_occupancy = 0;
if (rlc_pP->status_requested) {
if (rlc_pP->t_status_prohibit.running == 0) {
#if TRACE_RLC_AM_BO
@@ -64,7 +65,7 @@ rlc_am_get_buffer_occupancy_in_bytes (
}
#endif
- return ((15 + rlc_pP->num_nack_sn*(10+1) + rlc_pP->num_nack_so*(15+15+1) + 7) >> 3);
+ rlc_pP->status_buffer_occupancy = ((15 + rlc_pP->num_nack_sn*(10+1) + rlc_pP->num_nack_so*(15+15+1) + 7) >> 3);
}
}
@@ -113,7 +114,8 @@ config_req_rlc_am (
const protocol_ctxt_t* const ctxt_pP,
const srb_flag_t srb_flagP,
rlc_am_info_t * const config_am_pP,
- const rb_id_t rb_idP
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP
)
{
rlc_union_t *rlc_union_p = NULL;
@@ -135,7 +137,7 @@ config_req_rlc_am (
config_am_pP->t_reordering,
config_am_pP->t_status_prohibit);
rlc_am_init(ctxt_pP, l_rlc_p);
- rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP);
+ rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
rlc_am_configure(ctxt_pP, l_rlc_p,
config_am_pP->max_retx_threshold,
config_am_pP->poll_pdu,
@@ -160,7 +162,8 @@ void config_req_rlc_am_asn1 (
const protocol_ctxt_t* const ctxt_pP,
const srb_flag_t srb_flagP,
const struct RLC_Config__am * const config_am_pP,
- const rb_id_t rb_idP)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP)
{
rlc_union_t *rlc_union_p = NULL;
rlc_am_entity_t *l_rlc_p = NULL;
@@ -201,7 +204,7 @@ void config_req_rlc_am_asn1 (
t_StatusProhibit_tab[config_am_pP->dl_AM_RLC.t_StatusProhibit]);
rlc_am_init(ctxt_pP, l_rlc_p);
- rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP);
+ rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
rlc_am_configure(ctxt_pP, l_rlc_p,
maxRetxThreshold_tab[config_am_pP->ul_AM_RLC.maxRetxThreshold],
pollPDU_tab[config_am_pP->ul_AM_RLC.pollPDU],
@@ -338,6 +341,7 @@ rlc_am_get_pdus (
if (pdu) {
list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
rlc_pP->status_requested = 0;
+ rlc_pP->status_buffer_occupancy = 0;
rlc_am_start_timer_status_prohibit(ctxt_pP, rlc_pP);
return;
}
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h
index 5d038dfdbc..61c6a043cc 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h
@@ -128,31 +128,35 @@ public_rlc_am(void rlc_am_release (
* @{
*/
-/*! \fn void config_req_rlc_am (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, rlc_am_info_t * config_amP, rb_id_t rb_idP)
+/*! \fn void config_req_rlc_am (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, rlc_am_info_t * config_amP, rb_id_t rb_idP, logical_chan_id_t chan_idP)
* \brief Configure the UL and DL parameters of the RLC AM
* \param[in] ctxt_pP Running context.
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
* \param[in] config_amP Configuration parameters for RLC AM instance.
* \param[in] rb_idP Radio bearer identifier.
+* \param[in] chan_idP Transport channel identifier.
*/
public_rlc_am(void config_req_rlc_am (
const protocol_ctxt_t* const ctxtP,
const srb_flag_t srb_flagP,
const rlc_am_info_t * const config_amP,
- const rb_id_t rb_idP);)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP);)
-/*! \fn void config_req_rlc_am_asn1 (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, struct RLC_Config__am * config_amP, rb_id_t rb_idP)
+/*! \fn void config_req_rlc_am_asn1 (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, struct RLC_Config__am * config_amP, rb_id_t rb_idP, logical_chan_id_t chan_idP)
* \brief Configure the UL and DL parameters of the RLC AM with the asn1c autogenerated pameters structs
* \param[in] ctxt_pP Running context.
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
* \param[in] config_amP Configuration parameters for RLC AM instance.
* \param[in] rb_idP Radio bearer identifier.
+* \param[in] chan_idP Transport channel identifier.
*/
public_rlc_am(void config_req_rlc_am_asn1 (
const protocol_ctxt_t* const ctxtP,
const srb_flag_t srb_flagP,
const struct RLC_Config__am * const config_amP,
- const rb_id_t rb_idP);)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP);)
/** @} */
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c
index d1c3d68c52..a7cf302d06 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c
@@ -246,10 +246,11 @@ rlc_am_set_debug_infos(
const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t *const rlc_pP,
const srb_flag_t srb_flagP,
- const rb_id_t rb_idP)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP)
{
-
rlc_pP->rb_id = rb_idP;
+ rlc_pP->channel_id = chan_idP;
if (srb_flagP) {
rlc_pP->is_data_plane = 0;
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h
index 52034b7c77..d088f9f011 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h
@@ -105,13 +105,15 @@ public_rlc_am_init( void rlc_am_configure(const protocol_ctxt_t* const ctxtP,
const uint32_t t_reorderingP,
const uint32_t t_status_prohibitP);)
+
/*! \fn void rlc_am_set_debug_infos(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP)
* \brief Set informations that will be displayed in traces, helping the debug process.
* \param[in] ctxtP Running context.
* \param[in] rlc_pP RLC AM protocol instance pointer.
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
* \param[in] rb_idP Radio bearer identifier.
+* \param[in] chan_idP Transport channel identifier.
*/
-public_rlc_am_init( void rlc_am_set_debug_infos(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP);)
+public_rlc_am_init( void rlc_am_set_debug_infos(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP, const logical_chan_id_t chan_idP);)
/** @} */
#endif
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c
index 4bdb3ca000..d0b023833a 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c
@@ -413,8 +413,9 @@ rlc_am_receive_process_data_pdu (
rlc_am_rx_list_reassemble_rlc_sdus(ctxt_pP, rlc_pP);
}
+ //FNA: fix check VrX out of receiving window
if (rlc_pP->t_reordering.running) {
- if ((rlc_pP->vr_x == rlc_pP->vr_r) || ((rlc_am_in_rx_window(ctxt_pP, rlc_pP, pdu_info_p->sn) == 0) && (rlc_pP->vr_x != rlc_pP->vr_mr))) {
+ if ((rlc_pP->vr_x == rlc_pP->vr_r) || ((rlc_am_in_rx_window(ctxt_pP, rlc_pP, rlc_pP->vr_x) == 0) && (rlc_pP->vr_x != rlc_pP->vr_mr))) {
rlc_am_stop_and_reset_timer_reordering(ctxt_pP, rlc_pP);
}
}
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c
index 100802e28c..e03741707e 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c
@@ -698,8 +698,8 @@ void rlc_am_v9_3_0_test_tx_rx()
rlc_am_init(&g_am_tx, g_frame);
rlc_am_init(&g_am_rx, g_frame);
- rlc_am_set_debug_infos(&g_am_tx, g_frame, 0, 0, 0, 1);
- rlc_am_set_debug_infos(&g_am_rx, g_frame, 1, 1, 1, 1);
+ rlc_am_set_debug_infos(&g_am_tx, g_frame, 0, 0, 0, 1, 1 /* LC-id = DRB-id */);
+ rlc_am_set_debug_infos(&g_am_rx, g_frame, 1, 1, 1, 1, 1 /* LC-id = DRB-id */);
rlc_am_configure(&g_am_tx, g_frame, max_retx_threshold, poll_pdu, poll_byte, t_poll_retransmit, t_reordering, t_status_prohibit);
rlc_am_configure(&g_am_rx, g_frame, max_retx_threshold, poll_pdu, poll_byte, t_poll_retransmit, t_reordering, t_status_prohibit);
diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c
index 90fc084e84..4d75f3ee30 100644
--- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c
+++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c
@@ -29,7 +29,8 @@ void config_req_rlc_tm (
const protocol_ctxt_t* const ctxt_pP,
const srb_flag_t srb_flagP,
const rlc_tm_info_t * const config_tmP,
- const rb_id_t rb_idP
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP
)
{
rlc_union_t *rlc_union_p = NULL;
@@ -48,7 +49,7 @@ void config_req_rlc_tm (
rlc_tm_init(ctxt_pP, rlc_p);
rlc_p->protocol_state = RLC_DATA_TRANSFER_READY_STATE;
- rlc_tm_set_debug_infos(ctxt_pP, rlc_p, rb_idP, srb_flagP);
+ rlc_tm_set_debug_infos(ctxt_pP, rlc_p, srb_flagP, rb_idP, chan_idP);
rlc_tm_configure(ctxt_pP, rlc_p, config_tmP->is_uplink_downlink);
} else {
LOG_E(RLC, PROTOCOL_RLC_TM_CTXT_FMT" CONFIG_REQ RB %u RLC NOT FOUND\n",
@@ -144,9 +145,11 @@ void rlc_tm_set_debug_infos(
const protocol_ctxt_t* const ctxt_pP,
rlc_tm_entity_t * const rlcP,
const srb_flag_t srb_flagP,
- const rb_id_t rb_idP)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP)
{
- rlcP->rb_id = rb_idP;
+ rlcP->rb_id = rb_idP;
+ rlcP->channel_id = chan_idP;
if (srb_flagP) {
rlcP->is_data_plane = 0;
diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h
index f577db47d7..0e400a48ad 100644
--- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h
+++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h
@@ -73,13 +73,14 @@ typedef volatile struct rlc_tm_info_s {
* \param[in] srb_flagP Flag to indicate SRB (1) or DRB (0)
* \param[in] config_tmP Configuration parameters for RLC TM instance.
* \param[in] rb_idP Radio bearer identifier.
-* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
+* \param[in] chan_idP Transport channel identifier.
*/
public_rlc_tm_init( void config_req_rlc_tm (
const protocol_ctxt_t* const ctxt_pP,
const srb_flag_t srb_flagP,
const rlc_tm_info_t * const config_tmP,
- const rb_id_t rb_idP);)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP);)
/*! \fn void rlc_tm_init (const protocol_ctxt_t* const ctxt_pP, rlc_tm_entity_t * const rlcP)
* \brief Initialize a RLC TM protocol instance, initialize all variables, lists, allocate buffers for making this instance ready to be configured with protocol configuration parameters. After this initialization the RLC TM protocol instance will be in RLC_NULL_STATE state.
@@ -120,11 +121,14 @@ protected_rlc_tm_init(void rlc_tm_configure(
* \param[in] rlcP RLC TM protocol instance pointer.
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
* \param[in] rb_idP Radio bearer identifier.
+* \param[in] chan_idP Transport channel identifier
*/
protected_rlc_tm_init(void rlc_tm_set_debug_infos(
const protocol_ctxt_t* const ctxt_pP,
rlc_tm_entity_t * const rlcP,
const srb_flag_t srb_flagP,
- const rb_id_t rb_idP);)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP);)
+
/** @} */
# endif
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
index 3232399d10..51440d0bfa 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
@@ -426,7 +426,7 @@ rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, void *argP, struct mac_data_ind
//-----------------------------------------------------------------------------
struct mac_status_resp
-rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP)
+rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP)
{
struct mac_status_resp status_resp;
uint16_t sdu_size = 0;
@@ -434,6 +434,7 @@ rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP
int32_t diff_time=0;
rlc_um_entity_t *rlc_p = NULL;
mem_block_t *mb_p = NULL;
+ unsigned int max_li_overhead = 0;
status_resp.buffer_occupancy_in_pdus = 0;
status_resp.buffer_occupancy_in_bytes = 0;
@@ -453,7 +454,20 @@ rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP
if ((status_resp.buffer_occupancy_in_bytes > 0) && ((mb_p = list_get_head(&rlc_p->input_sdus)) != NULL)) {
- status_resp.buffer_occupancy_in_bytes += rlc_p->tx_header_min_length_in_bytes;
+ //Fix on full Header size
+ if (enb_flagP == ENB_FLAG_NO)
+ {
+ // compute Length Indicator overhead to inform MAC of maximum full RLC PDU size according to stored SDUs
+ // For UE scheduler
+ // Could be useful for eNB: to be checked
+ if (rlc_p->input_sdus.nb_elements <= 1) {
+ max_li_overhead = 0;
+ } else {
+ unsigned int num_li = rlc_p->input_sdus.nb_elements - 1;
+ max_li_overhead = num_li + (num_li >> 1) + (num_li & 1);
+ }
+ }
+ status_resp.buffer_occupancy_in_bytes += (rlc_p->tx_header_min_length_in_bytes + max_li_overhead);
status_resp.buffer_occupancy_in_pdus = rlc_p->input_sdus.nb_elements;
diff_time = ctxt_pP->frame - ((struct rlc_um_tx_sdu_management *)mb_p->data)->sdu_creation_time;
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h
index d87f1e29d0..5951eaf149 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h
@@ -186,7 +186,7 @@ protected_rlc_um( void rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, rlc_
* \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU.
* \return The maximum number of bytes that can be served by RLC instance to MAC.
*/
-public_rlc_um( struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP);)
+public_rlc_um( struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP, const eNB_flag_t enb_flagP);)
/*! \fn struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
* \brief Gives PDUs to lower layer MAC.
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c
index 688c8f646d..057be0000d 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c
@@ -40,7 +40,8 @@ void config_req_rlc_um (
const protocol_ctxt_t* const ctxt_pP,
const srb_flag_t srb_flagP,
const rlc_um_info_t * const config_um_pP,
- const rb_id_t rb_idP)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP)
{
rlc_union_t *rlc_union_p = NULL;
rlc_um_entity_t *rlc_p = NULL;
@@ -61,7 +62,7 @@ void config_req_rlc_um (
rlc_um_init(ctxt_pP, rlc_p);
if (rlc_um_fsm_notify_event (ctxt_pP, rlc_p, RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_DATA_TRANSFER_READY_STATE_EVENT)) {
- rlc_um_set_debug_infos(ctxt_pP, rlc_p, srb_flagP, rb_idP);
+ rlc_um_set_debug_infos(ctxt_pP, rlc_p, srb_flagP, rb_idP, chan_idP);
rlc_um_configure(
ctxt_pP,
rlc_p,
@@ -87,7 +88,8 @@ void config_req_rlc_um_asn1 (
const mbms_service_id_t mbms_service_idP,
const UL_UM_RLC_t * const ul_rlc_pP,
const DL_UM_RLC_t * const dl_rlc_pP,
- const rb_id_t rb_idP)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP)
{
uint32_t ul_sn_FieldLength = 0;
uint32_t dl_sn_FieldLength = 0;
@@ -135,7 +137,7 @@ void config_req_rlc_um_asn1 (
if (rlc_um_fsm_notify_event (ctxt_pP, rlc_p, RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_DATA_TRANSFER_READY_STATE_EVENT)) {
- rlc_um_set_debug_infos(ctxt_pP,rlc_p, srb_flagP, rb_idP);
+ rlc_um_set_debug_infos(ctxt_pP,rlc_p, srb_flagP, rb_idP, chan_idP);
if (ul_rlc_pP != NULL) {
switch (ul_rlc_pP->sn_FieldLength) {
@@ -416,14 +418,16 @@ void rlc_um_configure(
void rlc_um_set_debug_infos(
const protocol_ctxt_t* const ctxt_pP,
rlc_um_entity_t * const rlc_pP,
- const srb_flag_t srb_flagP,
- const rb_id_t rb_idP)
+ const srb_flag_t srb_flagP,
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP)
{
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [SET DEBUG INFOS] rb_id %d srb_flag %d\n",
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
rb_idP,
srb_flagP);
- rlc_pP->rb_id = rb_idP;
+ rlc_pP->rb_id = rb_idP;
+ rlc_pP->channel_id = chan_idP;
if (srb_flagP) {
rlc_pP->is_data_plane = 0;
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.h
index 97af1cfafa..b6964f9f12 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.h
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.h
@@ -77,12 +77,14 @@ typedef volatile struct {
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
* \param[in] config_umP Configuration parameters for RLC UM instance.
* \param[in] rb_idP Radio bearer identifier.
+* \param[in] chan_idP Transport channel identifier.
*/
public_rlc_um_control_primitives( void config_req_rlc_um (
const protocol_ctxt_t* const ctxt_pP,
const srb_flag_t srb_flagP,
const rlc_um_info_t * const config_umP,
- const rb_id_t rb_idP);)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP);)
/*! \fn void config_req_rlc_um_asn1 (
* const protocol_ctxt_t* const ctxt_pP,
@@ -102,6 +104,7 @@ public_rlc_um_control_primitives( void config_req_rlc_um (
* \param[in] ul_rlc_pP Configuration parameters for RLC UM UL instance.
* \param[in] dl_rlc_pP Configuration parameters for RLC UM DL instance.
* \param[in] rb_idP Radio bearer identifier.
+* \param[in] chan_idP Transport channel identifier.
*/
public_rlc_um_control_primitives( void config_req_rlc_um_asn1 (
const protocol_ctxt_t* const ctxt_pP,
@@ -111,7 +114,8 @@ public_rlc_um_control_primitives( void config_req_rlc_um_asn1 (
const mbms_service_id_t mbms_service_idP,
const UL_UM_RLC_t * const ul_rlc_pP,
const DL_UM_RLC_t * const dl_rlc_pP,
- const rb_id_t rb_idP);)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP);)
/*! \fn void rlc_um_init (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
* \brief Initialize a RLC UM protocol instance, initialize all variables, lists, allocate buffers for making this instance ready to be configured with protocol configuration parameters. After this initialization the RLC UM protocol instance will be in RLC_NULL_STATE state.
@@ -169,13 +173,15 @@ protected_rlc_um_control_primitives(void rlc_um_configure(
* \brief Set debug informations for a RLC UM protocol instance, these informations are only for trace purpose.
* \param[in] ctxtP Running context.
* \param[in] rlc_pP RLC UM protocol instance pointer.
-* \param[in] rb_idP Radio bearer identifier.
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
+* \param[in] rb_idP Radio bearer identifier.
+* \param[in] chan_idP Transport channel identifier.
*/
protected_rlc_um_control_primitives(void rlc_um_set_debug_infos(
const protocol_ctxt_t* const ctxt_pP,
rlc_um_entity_t * const rlc_pP,
const srb_flag_t srb_flagP,
- const rb_id_t rb_idP);)
+ const rb_id_t rb_idP,
+ const logical_chan_id_t chan_idP);)
/** @} */
# endif
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c
index c01e709b41..92f18e72d7 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c
@@ -188,8 +188,8 @@ void rlc_um_v9_3_0_test_windows_10()
rlc_um_init(&um1);
rlc_um_init(&um2);
- rlc_um_set_debug_infos(&um1, g_frame, 0, 0, 0, 1);
- rlc_um_set_debug_infos(&um2, g_frame, 1, 1, 1, 1);
+ rlc_um_set_debug_infos(&um1, g_frame, 0, 0, 0, 1, 1 /*LC-id = RAB-id*/);
+ rlc_um_set_debug_infos(&um2, g_frame, 1, 1, 1, 1, 1 /*LC-id = RAB-id*/);
rlc_um_configure(&um1, g_frame, timer_reordering, sn_field_length, sn_field_length, is_mXch);
rlc_um_configure(&um2, g_frame, timer_reordering, sn_field_length, sn_field_length, is_mXch);
@@ -242,8 +242,8 @@ void rlc_um_v9_3_0_test_windows_5()
rlc_um_init(&um1);
rlc_um_init(&um2);
- rlc_um_set_debug_infos(&um1, g_frame, 0, 0, 0, 1);
- rlc_um_set_debug_infos(&um2, g_frame, 1, 1, 1, 1);
+ rlc_um_set_debug_infos(&um1, g_frame, 0, 0, 0, 1, 1 /* LC-id = DRB-id */);
+ rlc_um_set_debug_infos(&um2, g_frame, 1, 1, 1, 1, 1 /* LC-id = DRB-id */);
rlc_um_configure(&um1, g_frame, timer_reordering, sn_field_length, sn_field_length, is_mXch);
rlc_um_configure(&um2, g_frame, timer_reordering, sn_field_length, sn_field_length, is_mXch);
@@ -471,9 +471,9 @@ void rlc_um_v9_3_0_test_exchange_pdus(rlc_um_entity_t *um_txP,
memset(&mac_rlc_status_resp_tx, 0, sizeof(struct mac_status_resp));
memset(&mac_rlc_status_resp_rx, 0, sizeof(struct mac_status_resp));
- mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status);
+ mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status,ENB_FLAG_YES);
data_request_tx = rlc_um_mac_data_request(um_txP, g_frame);
- mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status);
+ mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status,ENB_FLAG_YES);
data_request_rx = rlc_um_mac_data_request(um_rxP, g_frame);
@@ -517,9 +517,9 @@ void rlc_um_v9_3_0_test_exchange_delayed_pdus(rlc_um_entity_t *um_txP,
memset(&mac_rlc_status_resp_tx, 0, sizeof(struct mac_status_resp));
memset(&mac_rlc_status_resp_rx, 0, sizeof(struct mac_status_resp));
- mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status);
+ mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status,ENB_FLAG_YES);
data_request_tx = rlc_um_mac_data_request(um_txP, g_frame);
- mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status);
+ mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status,ENB_FLAG_YES);
data_request_rx = rlc_um_mac_data_request(um_rxP, g_frame);
@@ -614,8 +614,8 @@ void rlc_um_v9_3_0_test_reordering(uint32_t sn_field_lengthP)
um_info.is_mXch = 0;
srand (0);
- config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER);
- config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER);
+ config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
+ config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
rlc_um_display_rx_window(&um_tx);
@@ -736,8 +736,8 @@ void rlc_um_v9_3_0_test_tx_rx_10(void)
um_info.is_mXch = 0;
srand (0);
- config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER);
- config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER);
+ config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
+ config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
rlc_um_display_rx_window(&um_tx);
@@ -1065,8 +1065,8 @@ void rlc_um_v9_3_0_test_tx_rx_5(void)
um_info.is_mXch = 0;
srand (0);
- config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER);
- config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER);
+ config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
+ config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
rlc_um_display_rx_window(&um_tx);
diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h
index ec5ee629b1..3fd5b8c3bc 100644
--- a/openair2/LAYER2/RLC/rlc.h
+++ b/openair2/LAYER2/RLC/rlc.h
@@ -262,7 +262,18 @@ public_rlc(logical_chan_id_t rlc_mbms_rbid2lcid_eNB[NUMBER_OF_eNB_MAX][NB_RB_
(((hash_key_t)(rNTI)) << 8) | \
(((hash_key_t)(iS_eNB)) << 24) | \
(((hash_key_t)(rB_iD)) << 25) | \
- (((hash_key_t)(iS_sRB)) << 33))
+ (((hash_key_t)(iS_sRB)) << 33) | \
+ (((hash_key_t)(0x05)) << 34))
+
+// index to the same RLC entity as RLC_COLL_KEY_VALUE(), but using LC_id instead
+// the hidden last key indicates if this is a hash-key with RB_id (0x05) or LC_id (0x0a)
+#define RLC_COLL_KEY_LCID_VALUE(eNB_iD, rNTI, iS_eNB, lC_iD, iS_sRB) \
+ ((hash_key_t)eNB_iD | \
+ (((hash_key_t)(rNTI)) << 8) | \
+ (((hash_key_t)(iS_eNB)) << 24) | \
+ (((hash_key_t)(lC_iD)) << 25) | \
+ (((hash_key_t)(iS_sRB)) << 33) | \
+ (((hash_key_t)(0x0a)) << 34))
// service id max val is maxServiceCount = 16 (asn1_constants.h)
diff --git a/openair2/LAYER2/RLC/rlc_mac.c b/openair2/LAYER2/RLC/rlc_mac.c
index cb7357b5e7..d59b187dc7 100644
--- a/openair2/LAYER2/RLC/rlc_mac.c
+++ b/openair2/LAYER2/RLC/rlc_mac.c
@@ -129,7 +129,6 @@ tbs_size_t mac_rlc_data_req(
{
//-----------------------------------------------------------------------------
struct mac_data_req data_request;
- rb_id_t rb_id = 0;
rlc_mode_t rlc_mode = RLC_MODE_NONE;
rlc_mbms_id_t *mbms_id_p = NULL;
rlc_union_t *rlc_union_p = NULL;
@@ -172,13 +171,7 @@ tbs_size_t mac_rlc_data_req(
return (tbs_size_t)0;
}
} else {
- if (channel_idP > 2) {
- rb_id = channel_idP - 2;
- } else {
- rb_id = channel_idP;
- }
-
- key = RLC_COLL_KEY_VALUE(module_idP, rntiP, enb_flagP, rb_id, srb_flag);
+ key = RLC_COLL_KEY_LCID_VALUE(module_idP, rntiP, enb_flagP, channel_idP, srb_flag);
}
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
@@ -187,7 +180,7 @@ tbs_size_t mac_rlc_data_req(
rlc_mode = rlc_union_p->mode;
} else {
rlc_mode = RLC_MODE_NONE;
- AssertFatal (0 , "RLC not configured rb id %u lcid %u RNTI %x!\n", rb_id, channel_idP, rntiP);
+ AssertFatal (0 , "RLC not configured lcid %u RNTI %x!\n", channel_idP, rntiP);
}
switch (rlc_mode) {
@@ -237,7 +230,6 @@ void mac_rlc_data_ind (
crc_t *crcs_pP)
{
//-----------------------------------------------------------------------------
- rb_id_t rb_id = 0;
rlc_mode_t rlc_mode = RLC_MODE_NONE;
rlc_mbms_id_t *mbms_id_p = NULL;
rlc_union_t *rlc_union_p = NULL;
@@ -287,13 +279,7 @@ void mac_rlc_data_ind (
return;
}
} else {
- if (channel_idP > 2) {
- rb_id = channel_idP - 2;
- } else {
- rb_id = channel_idP;
- }
-
- key = RLC_COLL_KEY_VALUE(module_idP, rntiP, enb_flagP, rb_id, srb_flag);
+ key = RLC_COLL_KEY_LCID_VALUE(module_idP, rntiP, enb_flagP, channel_idP, srb_flag);
}
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
@@ -343,7 +329,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
mac_rlc_status_resp_t mac_rlc_status_resp;
struct mac_status_ind tx_status;
struct mac_status_resp status_resp;
- rb_id_t rb_id = 0;
rlc_mode_t rlc_mode = RLC_MODE_NONE;
rlc_mbms_id_t *mbms_id_p = NULL;
rlc_union_t *rlc_union_p = NULL;
@@ -392,13 +377,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
key = RLC_COLL_KEY_MBMS_VALUE(module_idP, rntiP, enb_flagP, mbms_id_p->service_id, mbms_id_p->session_id);
} else {
- if (channel_idP > 2) {
- rb_id = channel_idP - 2;
- } else {
- rb_id = channel_idP;
- }
-
- key = RLC_COLL_KEY_VALUE(module_idP, rntiP, enb_flagP, rb_id, srb_flag);
+ key = RLC_COLL_KEY_LCID_VALUE(module_idP, rntiP, enb_flagP, channel_idP, srb_flag);
}
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
@@ -427,7 +406,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
break;
case RLC_MODE_UM:
- status_resp = rlc_um_mac_status_indication(&ctxt, &rlc_union_p->rlc.um, tb_sizeP, tx_status);
+ status_resp = rlc_um_mac_status_indication(&ctxt, &rlc_union_p->rlc.um, tb_sizeP, tx_status, enb_flagP);
mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes;
mac_rlc_status_resp.pdus_in_buffer = status_resp.buffer_occupancy_in_pdus;
mac_rlc_status_resp.head_sdu_creation_time = status_resp.head_sdu_creation_time;
diff --git a/openair2/LAYER2/RLC/rlc_rrc.c b/openair2/LAYER2/RLC/rlc_rrc.c
index c78a3fa144..9ef8bd8700 100644
--- a/openair2/LAYER2/RLC/rlc_rrc.c
+++ b/openair2/LAYER2/RLC/rlc_rrc.c
@@ -97,7 +97,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
if (srb2add_listP != NULL) {
for (cnt=0; cntlist.count; cnt++) {
rb_id = srb2add_listP->list.array[cnt]->srb_Identity;
- lc_id = rb_id + 2;
+ lc_id = rb_id;
LOG_D(RLC, "Adding SRB %d, rb_id %d\n",srb2add_listP->list.array[cnt]->srb_Identity,rb_id);
srb_toaddmod_p = srb2add_listP->list.array[cnt];
@@ -118,7 +118,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
ctxt_pP,
SRB_FLAG_YES,
&srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.am,
- rb_id);
+ rb_id, lc_id);
} else {
LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -137,7 +137,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
UNUSED_PARAM_MBMS_SERVICE_ID,
&srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Bi_Directional.ul_UM_RLC,
&srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Bi_Directional.dl_UM_RLC,
- rb_id);
+ rb_id, lc_id);
} else {
LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -156,7 +156,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
UNUSED_PARAM_MBMS_SERVICE_ID,
&srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Uni_Directional_UL.ul_UM_RLC,
NULL,
- rb_id);
+ rb_id, lc_id);
} else {
LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -175,7 +175,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
UNUSED_PARAM_MBMS_SERVICE_ID,
NULL,
&srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Uni_Directional_DL.dl_UM_RLC,
- rb_id);
+ rb_id, lc_id);
} else {
LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -209,7 +209,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
ctxt_pP,
SRB_FLAG_YES,
&srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.am,
- rb_id);
+ rb_id,lc_id);
} else {
LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -225,7 +225,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
UNUSED_PARAM_MBMS_SERVICE_ID,
NULL, // TO DO DEFAULT CONFIG
NULL, // TO DO DEFAULT CONFIG
- rb_id);
+ rb_id, lc_id);
} else {
LOG_D(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -247,9 +247,19 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
drb_toaddmod_p = drb2add_listP->list.array[cnt];
drb_id = drb_toaddmod_p->drb_Identity;
- lc_id = drb_id + 2;
+ if (drb_toaddmod_p->logicalChannelIdentity) {
+ lc_id = *drb_toaddmod_p->logicalChannelIdentity;
+ } else {
+ LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity is missing from drb-ToAddMod information element!\n", PROTOCOL_CTXT_ARGS(ctxt_pP));
+ continue;
+ }
- LOG_I(RLC, "Adding DRB %d, lc_id %d\n",drb_id,lc_id);
+ if (lc_id == 1 || lc_id == 2) {
+ LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity = %d is invalid in RRC message when adding DRB!\n", PROTOCOL_CTXT_ARGS(ctxt_pP), lc_id);
+ continue;
+ }
+
+ LOG_D(RLC, "Adding DRB %d, lc_id %d\n",drb_id,lc_id);
if (drb_toaddmod_p->rlc_Config) {
@@ -264,7 +274,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
ctxt_pP,
SRB_FLAG_NO,
&drb_toaddmod_p->rlc_Config->choice.am,
- drb_id);
+ drb_id, lc_id);
}
break;
@@ -279,7 +289,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
UNUSED_PARAM_MBMS_SERVICE_ID,
&drb_toaddmod_p->rlc_Config->choice.um_Bi_Directional.ul_UM_RLC,
&drb_toaddmod_p->rlc_Config->choice.um_Bi_Directional.dl_UM_RLC,
- drb_id);
+ drb_id, lc_id);
}
break;
@@ -294,7 +304,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
UNUSED_PARAM_MBMS_SERVICE_ID,
&drb_toaddmod_p->rlc_Config->choice.um_Uni_Directional_UL.ul_UM_RLC,
NULL,
- drb_id);
+ drb_id, lc_id);
}
break;
@@ -309,7 +319,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
UNUSED_PARAM_MBMS_SERVICE_ID,
NULL,
&drb_toaddmod_p->rlc_Config->choice.um_Uni_Directional_DL.dl_UM_RLC,
- drb_id);
+ drb_id, lc_id);
}
break;
@@ -393,7 +403,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
mbms_service_id,
NULL,
&dl_um_rlc,
- rb_id);
+ rb_id, lc_id);
}
}
}
@@ -474,6 +484,8 @@ rlc_op_status_t rrc_rlc_remove_rlc (
logical_chan_id_t lcid = 0;
hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
hashtable_rc_t h_rc;
+ hash_key_t key_lcid = HASHTABLE_NOT_A_KEY_VALUE;
+ hashtable_rc_t h_lcid_rc;
rlc_union_t *rlc_union_p = NULL;
#ifdef Rel10
rlc_mbms_id_t *mbms_id_p = NULL;
@@ -517,23 +529,49 @@ rlc_op_status_t rrc_rlc_remove_rlc (
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
if (h_rc == HASH_TABLE_OK) {
- h_rc = hashtable_remove(rlc_coll_p, key);
- LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u] RELEASED %s\n",
- PROTOCOL_CTXT_ARGS(ctxt_pP),
- (srb_flagP) ? "SRB" : "DRB",
- rb_idP,
- (srb_flagP) ? "SRB" : "DRB");
- } else if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) {
- LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u] RELEASE : RLC NOT FOUND %s\n",
- PROTOCOL_CTXT_ARGS(ctxt_pP),
- (srb_flagP) ? "SRB" : "DRB",
- rb_idP,
- (srb_flagP) ? "SRB" : "DRB");
+ // also remove the hash-key created by LC-id
+ switch (rlc_union_p->mode) {
+ case RLC_MODE_AM:
+ lcid = rlc_union_p->rlc.am.channel_id;
+ break;
+ case RLC_MODE_UM:
+ lcid = rlc_union_p->rlc.um.channel_id;
+ break;
+ case RLC_MODE_TM:
+ lcid = rlc_union_p->rlc.tm.channel_id;
+ break;
+ default:
+ LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] RLC mode is unknown!\n",
+ PROTOCOL_CTXT_ARGS(ctxt_pP),
+ (srb_flagP) ? "SRB" : "DRB",
+ rb_idP);
+ }
+ key_lcid = RLC_COLL_KEY_LCID_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, lcid, srb_flagP);
+ h_lcid_rc = hashtable_get(rlc_coll_p, key_lcid, (void**)&rlc_union_p);
} else {
- LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] RELEASE : INTERNAL ERROR %s\n",
+ h_lcid_rc = HASH_TABLE_KEY_NOT_EXISTS;
+ }
+
+ if ((h_rc == HASH_TABLE_OK) && (h_lcid_rc == HASH_TABLE_OK)) {
+ h_lcid_rc = hashtable_remove(rlc_coll_p, key_lcid);
+ h_rc = hashtable_remove(rlc_coll_p, key);
+ LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u LCID %d] RELEASED %s\n",
PROTOCOL_CTXT_ARGS(ctxt_pP),
(srb_flagP) ? "SRB" : "DRB",
- rb_idP,
+ rb_idP, lcid,
+ (srb_flagP) ? "SRB" : "DRB");
+ } else if ((h_rc == HASH_TABLE_KEY_NOT_EXISTS) || (h_lcid_rc == HASH_TABLE_KEY_NOT_EXISTS)) {
+ LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u LCID %d] RELEASE : RLC NOT FOUND %s, by RB-ID=%d, by LC-ID=%d\n",
+ PROTOCOL_CTXT_ARGS(ctxt_pP),
+ (srb_flagP) ? "SRB" : "DRB",
+ rb_idP, lcid,
+ (srb_flagP) ? "SRB" : "DRB",
+ h_rc, h_lcid_rc);
+ } else {
+ LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u LCID %d] RELEASE : INTERNAL ERROR %s\n",
+ PROTOCOL_CTXT_ARGS(ctxt_pP),
+ (srb_flagP) ? "SRB" : "DRB",
+ rb_idP, lcid,
(srb_flagP) ? "SRB" : "DRB");
}
@@ -551,6 +589,8 @@ rlc_union_t* rrc_rlc_add_rlc (
//-----------------------------------------------------------------------------
hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
hashtable_rc_t h_rc;
+ hash_key_t key_lcid = HASHTABLE_NOT_A_KEY_VALUE;
+ hashtable_rc_t h_lcid_rc;
rlc_union_t *rlc_union_p = NULL;
#ifdef Rel10
rlc_mbms_id_t *mbms_id_p = NULL;
@@ -591,6 +631,7 @@ rlc_union_t* rrc_rlc_add_rlc (
#endif
{
key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
+ key_lcid = RLC_COLL_KEY_LCID_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, chan_idP, srb_flagP);
}
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
@@ -606,8 +647,9 @@ rlc_union_t* rrc_rlc_add_rlc (
} else if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) {
rlc_union_p = calloc(1, sizeof(rlc_union_t));
h_rc = hashtable_insert(rlc_coll_p, key, rlc_union_p);
+ h_lcid_rc = hashtable_insert(rlc_coll_p, key_lcid, rlc_union_p);
- if (h_rc == HASH_TABLE_OK) {
+ if ((h_rc == HASH_TABLE_OK) && (h_lcid_rc == HASH_TABLE_OK)) {
#ifdef Rel10
if (MBMS_flagP == TRUE) {
@@ -628,11 +670,12 @@ rlc_union_t* rrc_rlc_add_rlc (
rlc_union_p->mode = rlc_modeP;
return rlc_union_p;
} else {
- LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_add_rlc FAILED %s\n",
+ LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_add_rlc FAILED %s (add by RB_id=%d; add by LC_id=%d)\n",
PROTOCOL_CTXT_ARGS(ctxt_pP),
(srb_flagP) ? "SRB" : "DRB",
rb_idP,
- (srb_flagP) ? "SRB" : "DRB");
+ (srb_flagP) ? "SRB" : "DRB",
+ h_rc, h_lcid_rc);
free(rlc_union_p);
rlc_union_p = NULL;
return NULL;
@@ -689,7 +732,7 @@ rlc_op_status_t rrc_rlc_config_req (
ctxt_pP,
srb_flagP,
&rlc_infoP.rlc.rlc_am_info,
- rb_idP);
+ rb_idP, rb_idP);
break;
case RLC_MODE_UM:
@@ -700,7 +743,7 @@ rlc_op_status_t rrc_rlc_config_req (
ctxt_pP,
srb_flagP,
&rlc_infoP.rlc.rlc_um_info,
- rb_idP);
+ rb_idP, rb_idP);
break;
case RLC_MODE_TM:
@@ -711,7 +754,7 @@ rlc_op_status_t rrc_rlc_config_req (
ctxt_pP,
srb_flagP,
&rlc_infoP.rlc.rlc_tm_info,
- rb_idP);
+ rb_idP, rb_idP);
break;
default:
diff --git a/openair2/LAYER2/openair2_proc.c b/openair2/LAYER2/openair2_proc.c
index 702ddde45b..677d49bb65 100644
--- a/openair2/LAYER2/openair2_proc.c
+++ b/openair2/LAYER2/openair2_proc.c
@@ -115,11 +115,13 @@ int dump_eNB_l2_stats(char *buffer, int length)
for (CC_id=0 ; CC_id < MAX_NUM_CCs; CC_id++) {
eNB->eNB_stats[CC_id].dlsch_bitrate= 0;
- len += sprintf(&buffer[len],"eNB %d CC %d Frame %d: Active UEs %d, Available PRBs %d, nCCE %d \n",
+ len += sprintf(&buffer[len],"eNB %d CC %d Frame %d: Active UEs %d, Available PRBs %d, nCCE %d, Scheduling decisions %d, Missed Deadlines %d \n",
eNB_id, CC_id, eNB->frame,
eNB->eNB_stats[CC_id].num_dlactive_UEs,
eNB->eNB_stats[CC_id].available_prbs,
- eNB->eNB_stats[CC_id].available_ncces);
+ eNB->eNB_stats[CC_id].available_ncces,
+ eNB->eNB_stats[CC_id].sched_decisions,
+ eNB->eNB_stats[CC_id].missed_deadlines);
len += sprintf(&buffer[len],"BCCH , NB_TX_MAC = %d, transmitted bytes (TTI %d, total %d) MCS (TTI %d)\n",
eNB->eNB_stats[CC_id].total_num_bcch_pdu,
diff --git a/openair2/NETWORK_DRIVER/UE_IP/common.c b/openair2/NETWORK_DRIVER/UE_IP/common.c
index 6bef269de8..8696801597 100644
--- a/openair2/NETWORK_DRIVER/UE_IP/common.c
+++ b/openair2/NETWORK_DRIVER/UE_IP/common.c
@@ -99,7 +99,8 @@ ue_ip_common_class_wireless2ip(
hard_header_len = ue_ip_dev[instP]->hard_header_len;
skb_set_mac_header(skb_p, 0);
-
+ skb_set_network_header(skb_p, hard_header_len);
+skb_p->mark = rb_idP;
//printk("[NAC_COMMIN_RECEIVE]: Packet Type %d (%d,%d)",skb_p->pkt_type,PACKET_HOST,PACKET_BROADCAST);
skb_p->pkt_type = PACKET_HOST;
@@ -344,7 +345,7 @@ void ue_ip_common_wireless2ip(struct nlmsghdr *nlh_pP)
ue_ip_common_class_wireless2ip(pdcph_p->data_size,
(unsigned char *)NLMSG_DATA(nlh_pP) + UE_IP_PDCPH_SIZE,
- pdcph_p->inst,
+ 1, //pdcph_p->inst,
pdcph_p->rb_id);
}
diff --git a/openair2/PHY_INTERFACE/defs.h b/openair2/PHY_INTERFACE/defs.h
index 8c711e971d..156b9091b7 100644
--- a/openair2/PHY_INTERFACE/defs.h
+++ b/openair2/PHY_INTERFACE/defs.h
@@ -170,7 +170,7 @@ typedef struct {
PRACH_RESOURCES_t* (*ue_get_rach)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t Msg3_flag,sub_frame_t subframe);
/// Process Random-Access Response
- uint16_t (*ue_process_rar)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t *dlsch_buffer,uint16_t *t_crnti,uint8_t preamble_index);
+ uint16_t (*ue_process_rar)(module_id_t Mod_id,int CC_id,frame_t frameP, uint16_t ra_rnti, uint8_t *dlsch_buffer, uint16_t *t_crnti,uint8_t preamble_index);
/// Get SR payload (0,1) from UE MAC
uint32_t (*ue_get_SR)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t eNB_id,rnti_t rnti,sub_frame_t subframe);
@@ -179,12 +179,15 @@ typedef struct {
void (*dl_phy_sync_success) (module_id_t Mod_id,frame_t frameP, uint8_t CH_index,uint8_t first_sync);
/// Only calls the PDCP for now
- UE_L2_STATE_t (*ue_scheduler)(module_id_t Mod_id, frame_t frameP,sub_frame_t subframe, lte_subframe_t direction, uint8_t eNB_id, int CC_id);
+ UE_L2_STATE_t (*ue_scheduler)(module_id_t Mod_id, frame_t rxFrameP,sub_frame_t rxSubframe, frame_t txFrameP,sub_frame_t txSubframe, lte_subframe_t direction, uint8_t eNB_id, int CC_id);
/// PHY-Config-Dedicated UE
void (*phy_config_dedicated_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index,
struct PhysicalConfigDedicated *physicalConfigDedicated);
+ /// PHY-Config-harq UE
+ void (*phy_config_harq_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index,
+ uint16_t max_harq_tx);
/// Configure Common PHY parameters from SIB1
void (*phy_config_sib1_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index,
TDD_Config_t *tdd_config,
diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.c b/openair2/RRC/LITE/MESSAGES/asn1_msg.c
index 51136dee19..5f9a8e0e2a 100644
--- a/openair2/RRC/LITE/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.c
@@ -99,7 +99,7 @@ int errno;
# endif
#endif
-//#define XER_PRINT
+#define XER_PRINT
extern Enb_properties_array_t enb_properties;
typedef struct xer_sprint_string_s {
@@ -109,6 +109,7 @@ typedef struct xer_sprint_string_s {
} xer_sprint_string_t;
extern unsigned char NB_eNB_INST;
+extern uint8_t usim_test;
uint16_t two_tier_hexagonal_cellIds[7] = {0,1,2,4,5,7,8};
uint16_t two_tier_hexagonal_adjacent_cellIds[7][6] = {{1,2,4,5,7,8}, // CellId 0
@@ -1260,7 +1261,10 @@ uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uin
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension=CALLOC(1,
sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension));
- rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity=2;
+ if(usim_test == 0)
+ rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= 2;
+ else
+ rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= 1;
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME =
NULL;//calloc(1,sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME));
@@ -1384,6 +1388,7 @@ uint8_t
do_RRCConnectionSetup(
const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP,
+ int CC_id,
uint8_t* const buffer,
const uint8_t transmission_mode,
const uint8_t Transaction_id,
@@ -1488,7 +1493,10 @@ do_RRCConnectionSetup(
physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH = CALLOC(1,sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH));
physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH = CALLOC(1,sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH));
physicalConfigDedicated2->cqi_ReportConfig = CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig));
- physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = NULL;//CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
+ if (enb_properties.properties[ctxt_pP->module_id]->srs_enable[CC_id])
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
+ else
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = NULL;
physicalConfigDedicated2->antennaInfo = CALLOC(1,sizeof(*physicalConfigDedicated2->antennaInfo));
physicalConfigDedicated2->schedulingRequestConfig = CALLOC(1,sizeof(*physicalConfigDedicated2->schedulingRequestConfig));
#ifdef CBA
@@ -1574,19 +1582,19 @@ do_RRCConnectionSetup(
*/
//soundingRS-UL-ConfigDedicated
- /*
- physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->present = SoundingRS_UL_ConfigDedicated_PR_setup;
- assign_enum(&physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth,
- SoundingRS_UL_ConfigDedicated__setup__srs_Bandwidth_bw0);
- assign_enum(&physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth,
- SoundingRS_UL_ConfigDedicated__setup__srs_HoppingBandwidth_hbw0);
- physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition=0;
- physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.duration=1;
- physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex=1;
- physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb=0;
- assign_enum(&physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift,
- SoundingRS_UL_ConfigDedicated__setup__cyclicShift_cs0);
- */
+ if (enb_properties.properties[ctxt_pP->module_id]->srs_enable[CC_id]) {
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->present = SoundingRS_UL_ConfigDedicated_PR_setup;
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth =
+ SoundingRS_UL_ConfigDedicated__setup__srs_Bandwidth_bw0;
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth =
+ SoundingRS_UL_ConfigDedicated__setup__srs_HoppingBandwidth_hbw0;
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition=0;
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.duration=1;
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex=45;
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb=0;
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift=
+ SoundingRS_UL_ConfigDedicated__setup__cyclicShift_cs0;
+ }
//AntennaInfoDedicated
@@ -2661,6 +2669,21 @@ OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer_fname)
// UE_EUTRA_Capability->measParameters.bandListEUTRA.list.count = 0; // no measurements on other bands
// UE_EUTRA_Capability->featureGroupIndicators // null
+
+ // featureGroup is mandatory for CMW tests
+ // featureGroup is filled only for usim-test mode
+ BIT_STRING_t *bit_string;
+ uint32_t featrG;
+ bit_string = CALLOC(1, sizeof(*bit_string));
+ featrG = 0x04000800;
+ if(usim_test == 1)
+ {
+ bit_string->buf = &featrG;
+ bit_string->size = 4;
+ bit_string->bits_unused = 0;
+ UE_EUTRA_Capability->featureGroupIndicators = bit_string;
+ }
+
// UE_EUTRA_Capability->interRAT_Parameters // null
} else {
diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.h b/openair2/RRC/LITE/MESSAGES/asn1_msg.h
index 661914ea6e..881a778030 100644
--- a/openair2/RRC/LITE/MESSAGES/asn1_msg.h
+++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.h
@@ -133,6 +133,7 @@ do_RRCConnectionReconfigurationComplete(
PhysicalConfigDedicated IEs. The latter does not enable periodic CQI reporting (PUCCH format 2/2a/2b) or SRS.
@param ctxt_pP Running context
@param ue_context_pP UE context
+@param CC_id Component Carrier ID
@param buffer Pointer to PER-encoded ASN.1 description of DL-CCCH-Message PDU
@param transmission_mode Transmission mode for UE (1-9)
@param UE_id UE index for this message
@@ -144,6 +145,7 @@ uint8_t
do_RRCConnectionSetup(
const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP,
+ int CC_id,
uint8_t* const buffer,
const uint8_t transmission_mode,
const uint8_t Transaction_id,
diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h
index f99b07e893..0b0fd6b73f 100644
--- a/openair2/RRC/LITE/defs.h
+++ b/openair2/RRC/LITE/defs.h
@@ -173,7 +173,7 @@ typedef enum HO_STATE_e {
#define PAYLOAD_SIZE_MAX 1024
#define RRC_BUF_SIZE 255
#define UNDEF_SECURITY_MODE 0xff
-#define NO_SECURITY_MODE 0x33
+#define NO_SECURITY_MODE 0x20
#define CBA_OFFSET 0xfff4
// #define NUM_MAX_CBA_GROUP 4 // in the platform_constants
@@ -498,6 +498,7 @@ typedef struct UE_RRC_INST_s {
struct SRB_ToAddMod *SRB1_config[NB_CNX_UE];
struct SRB_ToAddMod *SRB2_config[NB_CNX_UE];
struct DRB_ToAddMod *DRB_config[NB_CNX_UE][8];
+ rb_id_t *defaultDRB; // remember the ID of the default DRB
MeasObjectToAddMod_t *MeasObj[NB_CNX_UE][MAX_MEAS_OBJ];
struct ReportConfigToAddMod *ReportConfig[NB_CNX_UE][MAX_MEAS_CONFIG];
struct QuantityConfig *QuantityConfig[NB_CNX_UE];
diff --git a/openair2/RRC/LITE/rrc_UE.c b/openair2/RRC/LITE/rrc_UE.c
index 5d40872172..38d7121860 100644
--- a/openair2/RRC/LITE/rrc_UE.c
+++ b/openair2/RRC/LITE/rrc_UE.c
@@ -32,6 +32,7 @@
#define RRC_UE_C
#include "assertions.h"
+#include "hashtable.h"
#include "asn1_conversions.h"
#include "defs.h"
#include "PHY/TOOLS/dB_routines.h"
@@ -97,10 +98,19 @@ extern UE_MAC_INST *UE_mac_inst;
extern void *bigphys_malloc(int);
#endif
-//#define XER_PRINT
+#define XER_PRINT
extern int8_t dB_fixed2(uint32_t x,uint32_t y);
+extern void pdcp_config_set_security(
+ const protocol_ctxt_t* const ctxt_pP,
+ pdcp_t * const pdcp_pP,
+ const rb_id_t rb_idP,
+ const uint16_t lc_idP,
+ const uint8_t security_modeP,
+ uint8_t * const kRRCenc,
+ uint8_t * const kRRCint,
+ uint8_t * const kUPenc);
// internal prototypes
@@ -807,6 +817,7 @@ rrc_ue_process_measConfig(
}
}
+ LOG_I(RRC,"call rrc_mac_config_req \n");
rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index,
(RadioResourceConfigCommonSIB_t *)NULL,
(struct PhysicalConfigDedicated *)NULL,
@@ -953,6 +964,199 @@ rrc_ue_process_measConfig(
}
}
+
+void
+rrc_ue_update_radioResourceConfigDedicated(RadioResourceConfigDedicated_t* radioResourceConfigDedicated,
+ const protocol_ctxt_t* const ctxt_pP,
+ uint8_t eNB_index)
+{
+ PhysicalConfigDedicated_t* physicalConfigDedicated2 = NULL;
+
+ physicalConfigDedicated2 = CALLOC(1,sizeof(*physicalConfigDedicated2));
+ physicalConfigDedicated2->pdsch_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->pdsch_ConfigDedicated));
+ physicalConfigDedicated2->pusch_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->pusch_ConfigDedicated));
+ physicalConfigDedicated2->pucch_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->pucch_ConfigDedicated));
+ physicalConfigDedicated2->cqi_ReportConfig = CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig));
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
+ physicalConfigDedicated2->schedulingRequestConfig = CALLOC(1,sizeof(*physicalConfigDedicated2->schedulingRequestConfig));
+ physicalConfigDedicated2->antennaInfo = CALLOC(1,sizeof(*physicalConfigDedicated2->antennaInfo));
+
+ physicalConfigDedicated2->uplinkPowerControlDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->uplinkPowerControlDedicated));
+ physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH = CALLOC(1,sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH));
+ physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH = CALLOC(1,sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH));
+
+ // Update pdsch_ConfigDedicated
+ if(radioResourceConfigDedicated->physicalConfigDedicated->pdsch_ConfigDedicated != NULL)
+ {
+ LOG_I(RRC,"Update pdsch_ConfigDedicated config \n");
+
+ if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pdsch_ConfigDedicated == NULL)
+ UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pdsch_ConfigDedicated = CALLOC(1,sizeof(PDSCH_ConfigDedicated_t));
+
+ memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pdsch_ConfigDedicated,
+ (char*)radioResourceConfigDedicated->physicalConfigDedicated->pdsch_ConfigDedicated,
+ sizeof(physicalConfigDedicated2->pdsch_ConfigDedicated));
+ }
+ else
+ {
+ LOG_I(RRC,"Keep old config for pdsch_ConfigDedicated\n");
+ }
+
+ // Update pusch_ConfigDedicated
+ if(radioResourceConfigDedicated->physicalConfigDedicated->pusch_ConfigDedicated != NULL)
+ {
+ LOG_I(RRC,"Update pusch_ConfigDedicated config \n");
+
+ if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pusch_ConfigDedicated == NULL)
+ UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pusch_ConfigDedicated = CALLOC(1,sizeof(PUSCH_ConfigDedicated_t));
+
+ memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pusch_ConfigDedicated,
+ (char*)radioResourceConfigDedicated->physicalConfigDedicated->pusch_ConfigDedicated,
+ sizeof(physicalConfigDedicated2->pusch_ConfigDedicated));
+ }
+ else
+ {
+ LOG_I(RRC,"Keep old config for pusch_ConfigDedicated\n");
+ }
+
+ // Update pucch_ConfigDedicated
+ if(radioResourceConfigDedicated->physicalConfigDedicated->pucch_ConfigDedicated != NULL)
+ {
+ LOG_I(RRC,"Update pucch_ConfigDedicated config \n");
+ if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pucch_ConfigDedicated == NULL)
+ UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pucch_ConfigDedicated = CALLOC(1,sizeof(PUCCH_ConfigDedicated_t));
+
+ memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pucch_ConfigDedicated,
+ (char*)radioResourceConfigDedicated->physicalConfigDedicated->pucch_ConfigDedicated,
+ sizeof(physicalConfigDedicated2->pucch_ConfigDedicated));
+ }
+ else
+ {
+ LOG_I(RRC,"Keep old config for pucch_ConfigDedicated\n");
+ }
+
+ // Update cqi_ReportConfig
+ if(radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig != NULL)
+ {
+ LOG_I(RRC,"Update cqi_ReportConfig config \n");
+
+ if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig == NULL)
+ UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig = CALLOC(1,sizeof(CQI_ReportConfig_t));
+
+ memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig,
+ (char*)radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig,
+ sizeof(physicalConfigDedicated2->cqi_ReportConfig));
+ }
+ else
+ {
+ LOG_I(RRC,"Keep old config for cqi_ReportConfig\n");
+ }
+
+ // Update schedulingRequestConfig
+ if(radioResourceConfigDedicated->physicalConfigDedicated->schedulingRequestConfig != NULL)
+ {
+ LOG_I(RRC,"Update schedulingRequestConfig config \n");
+
+ if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->schedulingRequestConfig == NULL)
+ UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->schedulingRequestConfig = CALLOC(1,sizeof(SchedulingRequestConfig_t));
+
+ memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->schedulingRequestConfig,
+ (char*)radioResourceConfigDedicated->physicalConfigDedicated->schedulingRequestConfig,
+ sizeof(physicalConfigDedicated2->schedulingRequestConfig));
+ }
+ else
+ {
+ LOG_I(RRC,"Keep old config for schedulingRequestConfig\n");
+ }
+
+ // Update soundingRS_UL_ConfigDedicated
+ if(radioResourceConfigDedicated->physicalConfigDedicated->soundingRS_UL_ConfigDedicated != NULL)
+ {
+ LOG_I(RRC,"Update soundingRS_UL_ConfigDedicated config \n");
+
+ if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->soundingRS_UL_ConfigDedicated == NULL)
+ UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(SoundingRS_UL_ConfigDedicated_t));
+
+ memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->soundingRS_UL_ConfigDedicated,
+ (char*)radioResourceConfigDedicated->physicalConfigDedicated->soundingRS_UL_ConfigDedicated,
+ sizeof(physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
+ }
+ else
+ {
+ LOG_I(RRC,"Keep old config for soundingRS_UL_ConfigDedicated\n");
+ }
+
+ // Update antennaInfo
+ if(radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo != NULL)
+ {
+ LOG_I(RRC,"Update antennaInfo config \n");
+
+ if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo == NULL)
+ UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo = CALLOC(1,sizeof(struct PhysicalConfigDedicated__antennaInfo));
+
+ memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo,
+ (char*)radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo,
+ sizeof(physicalConfigDedicated2->antennaInfo));
+ }
+ else
+ {
+ LOG_I(RRC,"Keep old config for antennaInfo\n");
+ }
+
+
+ // Update uplinkPowerControlDedicated
+ if(radioResourceConfigDedicated->physicalConfigDedicated->uplinkPowerControlDedicated != NULL)
+ {
+ LOG_I(RRC,"Update uplinkPowerControlDedicated config \n");
+
+ if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->uplinkPowerControlDedicated == NULL)
+ UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->uplinkPowerControlDedicated = CALLOC(1,sizeof(UplinkPowerControlDedicated_t));
+
+ memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->uplinkPowerControlDedicated,
+ (char*)radioResourceConfigDedicated->physicalConfigDedicated->uplinkPowerControlDedicated,
+ sizeof(physicalConfigDedicated2->uplinkPowerControlDedicated));
+ }
+ else
+ {
+ LOG_I(RRC,"Keep old config for uplinkPowerControlDedicated\n");
+ }
+
+ // Update tpc_PDCCH_ConfigPUCCH
+ if(radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUCCH != NULL)
+ {
+ LOG_I(RRC,"Update tpc_PDCCH_ConfigPUCCH config \n");
+
+ if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUCCH == NULL)
+ UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUCCH = CALLOC(1,sizeof(TPC_PDCCH_Config_t));
+
+ memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUCCH,
+ (char*)radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUCCH,
+ sizeof(physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH));
+ }
+ else
+ {
+ LOG_I(RRC,"Keep old config for tpc_PDCCH_ConfigPUCCH\n");
+ }
+
+ // Update tpc_PDCCH_ConfigPUSCH
+ if(radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUSCH != NULL)
+ {
+ LOG_I(RRC,"Update tpc_PDCCH_ConfigPUSCH config \n");
+
+ if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUSCH == NULL)
+ UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUSCH = CALLOC(1,sizeof(TPC_PDCCH_Config_t));
+
+ memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUSCH,
+ (char*)radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUSCH,
+ sizeof(physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH));
+
+ }
+ else
+ {
+ LOG_I(RRC,"Keep old config for tpc_PDCCH_ConfigPUSCH\n");
+ }
+
+}
//-----------------------------------------------------------------------------
void
rrc_ue_process_radioResourceConfigDedicated(
@@ -973,11 +1177,17 @@ rrc_ue_process_radioResourceConfigDedicated(
// Save physicalConfigDedicated if present
if (radioResourceConfigDedicated->physicalConfigDedicated) {
+ LOG_I(RRC,"Save physicalConfigDedicated if present \n");
+
if (UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]) {
+#if 1
+ rrc_ue_update_radioResourceConfigDedicated(radioResourceConfigDedicated, ctxt_pP, eNB_index);
+#else
memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index],(char*)radioResourceConfigDedicated->physicalConfigDedicated,
sizeof(struct PhysicalConfigDedicated));
-
+#endif
} else {
+ LOG_I(RRC,"Init physicalConfigDedicated UE_rrc_inst to radioResourceConfigDedicated->physicalConfigDedicated\n");
UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index] = radioResourceConfigDedicated->physicalConfigDedicated;
}
}
@@ -1054,7 +1264,7 @@ rrc_ue_process_radioResourceConfigDedicated(
#ifdef Rel10
,(PMCH_InfoList_r9_t *)NULL
#endif
- );
+ ,NULL);
// Refresh SRBs
rrc_rlc_config_asn1_req(ctxt_pP,
@@ -1095,7 +1305,7 @@ rrc_ue_process_radioResourceConfigDedicated(
SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
}
- LOG_D(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (SRB1 eNB %d) --->][MAC_UE][MOD %02d][]\n",
+ LOG_I(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (SRB1 eNB %d) --->][MAC_UE][MOD %02d][]\n",
ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index,
(RadioResourceConfigCommonSIB_t *)NULL,
@@ -1150,7 +1360,7 @@ rrc_ue_process_radioResourceConfigDedicated(
SRB2_logicalChannelConfig = &SRB2_logicalChannelConfig_defaultValue;
}
- LOG_D(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (SRB2 eNB %d) --->][MAC_UE][MOD %02d][]\n",
+ LOG_I(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (SRB2 eNB %d) --->][MAC_UE][MOD %02d][]\n",
ctxt_pP->frame,
ctxt_pP->module_id,
eNB_index,
@@ -1194,6 +1404,15 @@ rrc_ue_process_radioResourceConfigDedicated(
// Establish DRBs if present
if (radioResourceConfigDedicated->drb_ToAddModList) {
+
+ if ( (UE_rrc_inst[ctxt_pP->module_id].defaultDRB == NULL) &&
+ (radioResourceConfigDedicated->drb_ToAddModList->list.count >= 1) ) {
+ // configure the first DRB ID as the default DRB ID
+ UE_rrc_inst[ctxt_pP->module_id].defaultDRB = malloc(sizeof(rb_id_t));
+ *UE_rrc_inst[ctxt_pP->module_id].defaultDRB = radioResourceConfigDedicated->drb_ToAddModList->list.array[0]->drb_Identity;
+ LOG_I(RRC,"[UE %d] default DRB = %d\n",ctxt_pP->module_id, *UE_rrc_inst[ctxt_pP->module_id].defaultDRB);
+ }
+
uint8_t *kUPenc = NULL;
#if defined(ENABLE_SECURITY)
@@ -1225,7 +1444,7 @@ rrc_ue_process_radioResourceConfigDedicated(
#ifdef Rel10
,(PMCH_InfoList_r9_t *)NULL
#endif
- );
+ , UE_rrc_inst[ctxt_pP->module_id].defaultDRB);
// Refresh DRBs
rrc_rlc_config_asn1_req(ctxt_pP,
@@ -1248,7 +1467,7 @@ rrc_ue_process_radioResourceConfigDedicated(
UE_rrc_inst[ctxt_pP->module_id].DRB_config[eNB_index][DRB_id] = radioResourceConfigDedicated->drb_ToAddModList->list.array[i];
rrc_ue_establish_drb(ctxt_pP->module_id,ctxt_pP->frame,eNB_index,radioResourceConfigDedicated->drb_ToAddModList->list.array[i]);
// MAC/PHY Configuration
- LOG_D(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (DRB %d eNB %d) --->][MAC_UE][MOD %02d][]\n",
+ LOG_I(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (DRB %d eNB %d) --->][MAC_UE][MOD %02d][]\n",
ctxt_pP->frame, ctxt_pP->module_id,
radioResourceConfigDedicated->drb_ToAddModList->list.array[i]->drb_Identity,
eNB_index,
@@ -1386,6 +1605,62 @@ rrc_ue_process_securityModeCommand(
ul_dcch_msg.message.choice.c1.present = UL_DCCH_MessageType__c1_PR_securityModeFailure;
}
+
+#if defined(ENABLE_SECURITY)
+ uint8_t *kRRCenc = NULL;
+ uint8_t *kUPenc = NULL;
+ uint8_t *kRRCint = NULL;
+ pdcp_t *pdcp_p = NULL;
+ hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
+ hashtable_rc_t h_rc;
+
+ key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti,
+ ctxt_pP->enb_flag, DCCH, SRB_FLAG_YES);
+ h_rc = hashtable_get(pdcp_coll_p, key, (void**) &pdcp_p);
+
+ if (h_rc == HASH_TABLE_OK) {
+ LOG_D(RRC, "PDCP_COLL_KEY_VALUE() returns valid key = %d\n", key);
+
+ LOG_D(RRC, "driving kRRCenc, kRRCint and kUPenc from KeNB="
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x\n",
+ UE_rrc_inst[ctxt_pP->module_id].kenb[0], UE_rrc_inst[ctxt_pP->module_id].kenb[1], UE_rrc_inst[ctxt_pP->module_id].kenb[2], UE_rrc_inst[ctxt_pP->module_id].kenb[3],
+ UE_rrc_inst[ctxt_pP->module_id].kenb[4], UE_rrc_inst[ctxt_pP->module_id].kenb[5], UE_rrc_inst[ctxt_pP->module_id].kenb[6], UE_rrc_inst[ctxt_pP->module_id].kenb[7],
+ UE_rrc_inst[ctxt_pP->module_id].kenb[8], UE_rrc_inst[ctxt_pP->module_id].kenb[9], UE_rrc_inst[ctxt_pP->module_id].kenb[10], UE_rrc_inst[ctxt_pP->module_id].kenb[11],
+ UE_rrc_inst[ctxt_pP->module_id].kenb[12], UE_rrc_inst[ctxt_pP->module_id].kenb[13], UE_rrc_inst[ctxt_pP->module_id].kenb[14], UE_rrc_inst[ctxt_pP->module_id].kenb[15],
+ UE_rrc_inst[ctxt_pP->module_id].kenb[16], UE_rrc_inst[ctxt_pP->module_id].kenb[17], UE_rrc_inst[ctxt_pP->module_id].kenb[18], UE_rrc_inst[ctxt_pP->module_id].kenb[19],
+ UE_rrc_inst[ctxt_pP->module_id].kenb[20], UE_rrc_inst[ctxt_pP->module_id].kenb[21], UE_rrc_inst[ctxt_pP->module_id].kenb[22], UE_rrc_inst[ctxt_pP->module_id].kenb[23],
+ UE_rrc_inst[ctxt_pP->module_id].kenb[24], UE_rrc_inst[ctxt_pP->module_id].kenb[25], UE_rrc_inst[ctxt_pP->module_id].kenb[26], UE_rrc_inst[ctxt_pP->module_id].kenb[27],
+ UE_rrc_inst[ctxt_pP->module_id].kenb[28], UE_rrc_inst[ctxt_pP->module_id].kenb[29], UE_rrc_inst[ctxt_pP->module_id].kenb[30], UE_rrc_inst[ctxt_pP->module_id].kenb[31]);
+
+ derive_key_rrc_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
+ UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCenc);
+ derive_key_rrc_int(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
+ UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCint);
+ derive_key_up_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
+ UE_rrc_inst[ctxt_pP->module_id].kenb, &kUPenc);
+
+ if (securityMode != 0xff) {
+ pdcp_config_set_security(ctxt_pP, pdcp_p, 0, 0,
+ UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm
+ | (UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm << 4),
+ kRRCenc, kRRCint, kUPenc);
+ } else {
+ LOG_W(RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x",
+ securityMode);
+ }
+ } else {
+ LOG_W(RRC, "Could not get PDCP instance where key=0x%\n", key);
+ }
+
+#endif //#if defined(ENABLE_SECURITY)
+
if (securityModeCommand->criticalExtensions.present == SecurityModeCommand__criticalExtensions_PR_c1) {
if (securityModeCommand->criticalExtensions.choice.c1.present == SecurityModeCommand__criticalExtensions__c1_PR_securityModeCommand_r8) {
@@ -1719,7 +1994,7 @@ rrc_ue_process_mobilityControlInfo(
#ifdef Rel10
,NULL
#endif
- );
+ ,NULL);
rrc_rlc_config_asn1_req(NB_eNB_INST+ue_mod_idP, frameP,0,eNB_index,
NULL,// SRB_ToAddModList
@@ -1728,7 +2003,7 @@ rrc_ue_process_mobilityControlInfo(
#ifdef Rel10
,NULL
#endif
- );
+ ,NULL);
*/
@@ -1750,7 +2025,7 @@ rrc_ue_process_mobilityControlInfo(
UE_rrc_inst[ue_mod_idP].DRB_config[eNB_index][0] = NULL;
*/
//Synchronisation to DL of target cell
- LOG_D(RRC,
+ LOG_I(RRC,
"HO: Reset PDCP and RLC for configured RBs.. \n[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (SRB2 eNB %d) --->][MAC_UE][MOD %02d][]\n",
ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
@@ -2610,7 +2885,7 @@ static int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_
UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIperiod = siPeriod_int[sib1->schedulingInfoList.list.array[0]->si_Periodicity];
UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIwindowsize = siWindowLength_int[sib1->si_WindowLength];
- LOG_D( RRC, "[FRAME unknown][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB1 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
+ LOG_I( RRC, "[FRAME unknown][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB1 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
ctxt_pP->module_id, eNB_index, ctxt_pP->module_id );
rrc_mac_config_req(ctxt_pP->module_id, 0, ENB_FLAG_NO, 0, eNB_index,
@@ -3424,7 +3699,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB13 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
dump_sib13( UE_rrc_inst[ctxt_pP->module_id].sib13[eNB_index] );
// adding here function to store necessary parameters for using in decode_MCCH_Message + maybe transfer to PHY layer
- LOG_D( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB13 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
+ LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB13 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index,
(RadioResourceConfigCommonSIB_t *)NULL,
@@ -3881,7 +4156,7 @@ static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_i
{
protocol_ctxt_t ctxt;
- LOG_D(RRC,"[UE %d] Frame %d : Number of MCH(s) in the MBSFN Sync Area %d is %d\n",
+ LOG_I(RRC,"[UE %d] Frame %d : Number of MCH(s) in the MBSFN Sync Area %d is %d\n",
ue_mod_idP, frameP, mbsfn_sync_area, UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9.list.count);
// store to MAC/PHY necessary parameters for receiving MTCHs
rrc_mac_config_req(ue_mod_idP,0,ENB_FLAG_NO,0,eNB_index,
@@ -3933,7 +4208,7 @@ static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_i
#ifdef Rel10
,&(UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9)
#endif
- );
+ ,NULL);
rrc_rlc_config_asn1_req(&ctxt,
NULL,// SRB_ToAddModList
@@ -4090,6 +4365,30 @@ void *rrc_ue_task( void *args_p )
# if defined(ENABLE_USE_MME)
+ case NAS_KENB_REFRESH_REQ:
+ memcpy((void*)UE_rrc_inst[ue_mod_id].kenb, (void*)NAS_KENB_REFRESH_REQ(msg_p).kenb, sizeof(UE_rrc_inst[ue_mod_id].kenb));
+
+ LOG_D(RRC, "[UE %d] Received %s: refreshed RRC::KeNB = "
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x"
+ "%02x%02x%02x%02x\n",
+ ue_mod_id, msg_name,
+ UE_rrc_inst[ue_mod_id].kenb[0], UE_rrc_inst[ue_mod_id].kenb[1], UE_rrc_inst[ue_mod_id].kenb[2], UE_rrc_inst[ue_mod_id].kenb[3],
+ UE_rrc_inst[ue_mod_id].kenb[4], UE_rrc_inst[ue_mod_id].kenb[5], UE_rrc_inst[ue_mod_id].kenb[6], UE_rrc_inst[ue_mod_id].kenb[7],
+ UE_rrc_inst[ue_mod_id].kenb[8], UE_rrc_inst[ue_mod_id].kenb[9], UE_rrc_inst[ue_mod_id].kenb[10], UE_rrc_inst[ue_mod_id].kenb[11],
+ UE_rrc_inst[ue_mod_id].kenb[12], UE_rrc_inst[ue_mod_id].kenb[13], UE_rrc_inst[ue_mod_id].kenb[14], UE_rrc_inst[ue_mod_id].kenb[15],
+ UE_rrc_inst[ue_mod_id].kenb[16], UE_rrc_inst[ue_mod_id].kenb[17], UE_rrc_inst[ue_mod_id].kenb[18], UE_rrc_inst[ue_mod_id].kenb[19],
+ UE_rrc_inst[ue_mod_id].kenb[20], UE_rrc_inst[ue_mod_id].kenb[21], UE_rrc_inst[ue_mod_id].kenb[22], UE_rrc_inst[ue_mod_id].kenb[23],
+ UE_rrc_inst[ue_mod_id].kenb[24], UE_rrc_inst[ue_mod_id].kenb[25], UE_rrc_inst[ue_mod_id].kenb[26], UE_rrc_inst[ue_mod_id].kenb[27],
+ UE_rrc_inst[ue_mod_id].kenb[28], UE_rrc_inst[ue_mod_id].kenb[29], UE_rrc_inst[ue_mod_id].kenb[30], UE_rrc_inst[ue_mod_id].kenb[31]);
+
+ break;
+
/* NAS messages */
case NAS_CELL_SELECTION_REQ:
ue_mod_id = 0; /* TODO force ue_mod_id to first UE, NAS UE not virtualized yet */
@@ -4202,12 +4501,26 @@ void *rrc_ue_task( void *args_p )
/* Transfer data to PDCP */
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, UE_rrc_inst[ue_mod_id].Info[0].rnti, 0, 0,0);
- rrc_data_req (&ctxt,
- DCCH,
- rrc_mui++,
- SDU_CONFIRM_NO,
- length, buffer,
- PDCP_TRANSMISSION_MODE_CONTROL);
+
+ // check if SRB2 is created, if yes request data_req on DCCH1 (SRB2)
+ if(UE_rrc_inst[ue_mod_id].SRB2_config[0] == NULL)
+ {
+ rrc_data_req (&ctxt,
+ DCCH,
+ rrc_mui++,
+ SDU_CONFIRM_NO,
+ length, buffer,
+ PDCP_TRANSMISSION_MODE_CONTROL);
+ }
+ else
+ {
+ rrc_data_req (&ctxt,
+ DCCH1,
+ rrc_mui++,
+ SDU_CONFIRM_NO,
+ length, buffer,
+ PDCP_TRANSMISSION_MODE_CONTROL);
+ }
break;
}
diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c
index 284c5fd215..d279764528 100644
--- a/openair2/RRC/LITE/rrc_eNB.c
+++ b/openair2/RRC/LITE/rrc_eNB.c
@@ -93,6 +93,9 @@
#include "SIMULATION/TOOLS/defs.h" // for taus
+#if defined(FLEXRAN_AGENT_SB_IF)
+#include "flexran_agent_extern.h"
+#endif
#define XER_PRINT
#ifdef PHY_EMUL
@@ -473,7 +476,7 @@ static void init_MBMS(
# ifdef Rel10
, &(eNB_rrc_inst[enb_mod_idP].carrier[CC_id].mcch_message->pmch_InfoList_r9)
# endif
- );
+ ,NULL);
rrc_rlc_config_asn1_req(&ctxt,
NULL, // SRB_ToAddModList
@@ -644,6 +647,9 @@ void rrc_eNB_emulation_notify_ue_module_id(
// find enb_module_id
for (enb_module_id = 0; enb_module_id < NUMBER_OF_eNB_MAX; enb_module_id++) {
+ if(enb_module_id>0){ /*FIX LATER*/
+ return;
+ }
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
if (eNB_rrc_inst[enb_module_id].carrier[CC_id].sib1 != NULL) {
if (
@@ -652,7 +658,6 @@ void rrc_eNB_emulation_notify_ue_module_id(
(eNB_rrc_inst[enb_module_id].carrier[CC_id].sib1->cellAccessRelatedInfo.cellIdentity.buf[2] == cell_identity_byte2P) &&
(eNB_rrc_inst[enb_module_id].carrier[CC_id].sib1->cellAccessRelatedInfo.cellIdentity.buf[3] == cell_identity_byte3P)
) {
- oai_emulation.info.eNB_ue_module_id_to_rnti[enb_module_id][ue_module_idP] = rntiP;
ue_context_p = rrc_eNB_get_ue_context(
&eNB_rrc_inst[enb_module_id],
rntiP
@@ -662,10 +667,11 @@ void rrc_eNB_emulation_notify_ue_module_id(
oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[enb_module_id][ue_context_p->local_uid] = ue_module_idP;
}
- return;
+ //return;
}
}
}
+ oai_emulation.info.eNB_ue_module_id_to_rnti[enb_module_id][ue_module_idP] = rntiP;
}
AssertFatal(enb_module_id == NUMBER_OF_eNB_MAX,
@@ -2613,7 +2619,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH =
CALLOC(1, sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH));
physicalConfigDedicated2->cqi_ReportConfig = NULL; //CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig));
- physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = NULL; //CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
+ physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
physicalConfigDedicated2->antennaInfo = CALLOC(1, sizeof(*physicalConfigDedicated2->antennaInfo));
physicalConfigDedicated2->schedulingRequestConfig =
CALLOC(1, sizeof(*physicalConfigDedicated2->schedulingRequestConfig));
@@ -3275,7 +3281,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
#ifdef Rel10
, (PMCH_InfoList_r9_t *) NULL
#endif
- );
+ ,NULL);
rrc_rlc_config_asn1_req(&ctxt,
ue_context_pP->ue_context.SRB_configList,
@@ -3517,7 +3523,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
#ifdef Rel10
, (PMCH_InfoList_r9_t *) NULL
#endif
- );
+ ,NULL);
// Refresh SRBs/DRBs
rrc_rlc_config_asn1_req(
ctxt_pP,
@@ -3737,8 +3743,9 @@ rrc_eNB_generate_RRCConnectionSetup(
eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size =
do_RRCConnectionSetup(ctxt_pP,
ue_context_pP,
+ CC_id,
(uint8_t*) eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload,
- (fp->nb_antennas_tx_eNB==2)?2:1, //at this point we do not have the UE capability information, so it can only be TM1 or TM2
+ (fp->nb_antenna_ports_eNB==2)?2:1, //at this point we do not have the UE capability information, so it can only be TM1 or TM2
rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id),
fp,
SRB_configList,
@@ -4342,7 +4349,7 @@ rrc_eNB_decode_ccch(
# ifdef Rel10
, (PMCH_InfoList_r9_t *) NULL
# endif
- );
+ ,NULL);
rrc_rlc_config_asn1_req(ctxt_pP,
ue_context_p->ue_context.SRB_configList,
@@ -4535,7 +4542,16 @@ rrc_eNB_decode_dcch(
rrc_eNB_process_RRCConnectionReconfigurationComplete(
ctxt_pP,
ue_context_p,
- ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
+ ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
+
+#if defined(FLEXRAN_AGENT_SB_IF)
+ //WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
+ if (mac_agent_registered[ctxt_pP->module_id]) {
+ agent_mac_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
+ ue_context_p->ue_id_rnti,
+ PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED);
+ }
+#endif
}
#if defined(ENABLE_ITTI)
# if defined(ENABLE_USE_MME)
@@ -4631,6 +4647,15 @@ rrc_eNB_decode_dcch(
ue_context_p->ue_context.Status = RRC_CONNECTED;
LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_CONNECTED \n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
+
+#if defined(FLEXRAN_AGENT_SB_IF)
+ //WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
+ if (mac_agent_registered[ctxt_pP->module_id]) {
+ agent_mac_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
+ ue_context_p->ue_id_rnti,
+ PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED);
+ }
+#endif
}
}
diff --git a/openair2/UTIL/ASYNC_IF/link_manager.c b/openair2/UTIL/ASYNC_IF/link_manager.c
new file mode 100644
index 0000000000..1c9fb72bfe
--- /dev/null
+++ b/openair2/UTIL/ASYNC_IF/link_manager.c
@@ -0,0 +1,254 @@
+/*
+ * 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.0 (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 link_manager.c
+ * \brief this is the implementation of a link manager
+ * \author Cedric Roux
+ * \date November 2015
+ * \version 1.0
+ * \email: cedric.roux@eurecom.fr
+ * @ingroup _mac
+ */
+
+#include "link_manager.h"
+#include "log.h"
+
+#include
+#include
+#include
+
+/* that thread reads messages in the queue and sends them to the link */
+static void *link_manager_sender_thread(void *_manager)
+{
+ link_manager_t *manager = _manager;
+ void *data;
+ int size;
+ int priority;
+
+ LOG_D(MAC, "starting link manager sender thread\n");
+
+ while (manager->run) {
+ while (message_get(manager->send_queue, &data, &size, &priority) == 0) {
+ link_send_packet(manager->socket_link, data, size);
+ free(data);
+ }
+ // if (message_get(manager->send_queue, &data, &size, &priority))
+ // goto error;
+ //if (link_send_packet(manager->socket_link, data, size))
+ // goto error;
+ //free(data);
+ }
+
+ LOG_D(MAC, "link manager sender thread quits\n");
+
+ return NULL;
+
+error:
+ LOG_E(MAC, "%s: error\n", __FUNCTION__);
+ return NULL;
+}
+
+/* that thread receives messages from the link and puts them in the queue */
+static void *link_manager_receiver_thread(void *_manager)
+{
+ link_manager_t *manager = _manager;
+ void *data;
+ int size;
+
+ LOG_D(MAC, "starting link manager receiver thread\n");
+
+ while (manager->run) {
+ if (link_receive_packet(manager->socket_link, &data, &size))
+ goto error;
+ /* todo: priority */
+ if (message_put(manager->receive_queue, data, size, 0))
+ goto error;
+ }
+
+ LOG_D(MAC, "link manager receiver thread quits\n");
+
+ return NULL;
+
+error:
+ LOG_E(MAC, "%s: error\n", __FUNCTION__);
+ return NULL;
+}
+
+link_manager_t *create_link_manager(
+ message_queue_t *send_queue,
+ message_queue_t *receive_queue,
+ socket_link_t *link)
+{
+ link_manager_t *ret = NULL;
+ pthread_attr_t attr;
+ pthread_t t;
+
+ LOG_D(MAC, "create new link manager\n");
+
+ ret = calloc(1, sizeof(link_manager_t));
+ if (ret == NULL)
+ goto error;
+
+ ret->send_queue = send_queue;
+ ret->receive_queue = receive_queue;
+ ret->socket_link = link;
+ ret->run = 1;
+
+ if (pthread_attr_init(&attr))
+ goto error;
+
+ // Make the async interface threads real-time
+ //#ifndef LOWLATENCY
+ struct sched_param sched_param_recv_thread;
+ struct sched_param sched_param_send_thread;
+
+ sched_param_recv_thread.sched_priority = sched_get_priority_max(SCHED_RR) - 1;
+ pthread_attr_setschedparam(&attr, &sched_param_recv_thread);
+ pthread_attr_setschedpolicy(&attr, SCHED_RR);
+ //#endif
+
+ if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
+ goto error;
+
+ if (pthread_create(&t, &attr, link_manager_sender_thread, ret))
+ goto error;
+ ret->sender = t;
+
+ if (pthread_create(&t, &attr, link_manager_receiver_thread, ret))
+ /* we should destroy the other thread here */
+ goto error;
+ ret->receiver = t;
+
+ if (pthread_attr_destroy(&attr))
+ /* to be clean we should destroy the threads at this point,
+ * even if in practice we never reach it */
+ goto error;
+
+ return ret;
+
+error:
+ LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ free(ret);
+ return NULL;
+}
+
+void destroy_link_manager(link_manager_t *manager)
+{
+ LOG_D(MAC, "destroying link manager\n");
+ manager->run = 0;
+ /* todo: force threads to stop (using a dummy message?) */
+}
+
+#ifdef SERVER_TEST
+
+#include