diff --git a/CMakeLists.txt b/CMakeLists.txt index e3741d1f9b..e6147ce3fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1569,6 +1569,10 @@ set(libnas_emm_msg_OBJS ${NAS_SRC}COMMON/EMM/MSG/UplinkNasTransport.c ) +set(libnas_fgs_msg_OBJS + ${NAS_SRC}COMMON/EMM/MSG/fgs_service_request.c +) + set(libnas_esm_msg_OBJS ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextAccept.c ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextReject.c @@ -1682,7 +1686,6 @@ set (libnas_utils_OBJS ${NAS_SRC}COMMON/UTIL/nas_timer.c ${NAS_SRC}COMMON/UTIL/socket.c ${NAS_SRC}COMMON/UTIL/stty.c - ${NAS_SRC}COMMON/UTIL/TLVEncoder.c ${NAS_SRC}COMMON/UTIL/TLVDecoder.c ${NAS_SRC}COMMON/UTIL/OctetString.c ) @@ -1793,6 +1796,7 @@ add_library(LIB_NAS_SIMUE ${libnas_api_OBJS} ${libnas_ue_api_OBJS} ${libnas_emm_msg_OBJS} + ${libnas_fgs_msg_OBJS} ${libnas_esm_msg_OBJS} ${libnas_ies_OBJS} ${libnas_utils_OBJS} @@ -1839,6 +1843,7 @@ include_directories(${NAS_SRC}UE) include_directories(${NAS_SRC}UE/API/USER) include_directories(${NAS_SRC}UE/API/USIM) include_directories(${NAS_SRC}UE/EMM) +include_directories(${NAS_SRC}UE/EMM/MSG) include_directories(${NAS_SRC}UE/EMM/SAP) include_directories(${NAS_SRC}UE/ESM) include_directories(${NAS_SRC}UE/ESM/SAP) @@ -1905,12 +1910,6 @@ add_executable(measurement_display ${OPENAIR_DIR}/common/utils/threadPool/measurement_display.c) target_link_libraries (measurement_display minimal_lib) -add_executable(test5Gnas - ${OPENAIR_DIR}/openair3/TEST/test5Gnas.c -) -target_link_libraries (test5Gnas LIB_5GNAS_GNB minimal_lib ) - - # lte-softmodem is both eNB and UE implementation ################################################### diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index a9c4b5be08..b1c5120097 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -145,10 +145,6 @@ def AnalyzeBuildLogs(buildRoot, images, globalStatus): collectInfo[image] = files return collectInfo -def GetContainerName(ssh, svcName, file): - ret = ssh.run(f"docker compose -f {file} config --format json {svcName} | jq -r '.services.\"{svcName}\".container_name'", silent=True) - return ret.stdout - def GetImageName(ssh, svcName, file): ret = ssh.run(f"docker compose -f {file} config --format json {svcName} | jq -r '.services.\"{svcName}\".image'", silent=True) if ret.returncode != 0: @@ -156,17 +152,18 @@ def GetImageName(ssh, svcName, file): else: return ret.stdout.strip() -def GetContainerHealth(ssh, containerName): - if containerName is None: - return False - if 'db_init' in containerName or 'db-init' in containerName: # exits with 0, there cannot be healthy - return True +def GetServiceHealth(ssh, svcName, file): + if svcName is None: + return False, f"Service {svcName} not found in {file}" + image = GetImageName(ssh, svcName, file) + if 'db_init' in svcName or 'db-init' in svcName: # exits with 0, there cannot be healthy + return True, f"Service {svcName} healthy, image {image}" for _ in range(8): - result = ssh.run(f'docker inspect --format="{{{{.State.Health.Status}}}}" {containerName}', silent=True) + result = ssh.run(f"docker compose -f {file} ps --format json {svcName} | jq -r 'if type==\"array\" then .[0].Health else .Health end'", silent=True) if result.stdout == 'healthy': - return True + return True, f"Service {svcName} healthy, image {image}" time.sleep(5) - return False + return False, f"Failed to deploy: service {svcName}" def ExistEnvFilePrint(ssh, wd, prompt='env vars in existing'): ret = ssh.run(f'cat {wd}/.env', silent=True, reportNonZero=False) @@ -218,9 +215,9 @@ def GetServices(ssh, requested, file): else: return requested -def CopyinContainerLog(ssh, lSourcePath, yaml, containerName, filename): +def CopyinServiceLog(ssh, lSourcePath, yaml, svcName, wd_yaml, filename): remote_filename = f"{lSourcePath}/cmake_targets/log/{filename}" - ssh.run(f'docker logs {containerName} &> {remote_filename}') + ssh.run(f'docker compose -f {wd_yaml} logs {svcName} --no-log-prefix &> {remote_filename}') local_dir = f"{os.getcwd()}/../cmake_targets/log/{yaml}" local_filename = f"{local_dir}/{filename}" return ssh.copyin(remote_filename, local_filename) @@ -336,6 +333,7 @@ class Containerize(): self.imageToCopy = '' #checkers from xml self.ran_checkers={} + self.num_attempts = 1 self.flexricTag = '' @@ -843,50 +841,55 @@ class Containerize(): def DeployObject(self, HTML): svr = self.eNB_serverId[self.eNB_instance] + num_attempts = self.num_attempts lIpAddr, lSourcePath = self.GetCredentials(svr) - logging.debug('\u001B[1m Deploying OAI Object on server: ' + lIpAddr + '\u001B[0m') + logging.debug(f'Deploying OAI Object on server: {lIpAddr}') yaml = self.yamlPath[self.eNB_instance].strip('/') # creating the log folder by default local_dir = f"{os.getcwd()}/../cmake_targets/log/{yaml.split('/')[-1]}" os.system(f'mkdir -p {local_dir}') wd = f'{lSourcePath}/{yaml}' - + wd_yaml = f'{wd}/docker-compose.y*ml' + yaml_dir = yaml.split('/')[-1] with cls_cmd.getConnection(lIpAddr) as ssh: - services = GetServices(ssh, self.services[self.eNB_instance], f"{wd}/docker-compose.y*ml") + services = GetServices(ssh, self.services[self.eNB_instance], wd_yaml) if services == [] or services == ' ' or services == None: - msg = "Cannot determine services to start" + msg = 'Cannot determine services to start' logging.error(msg) HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg]) return False - ExistEnvFilePrint(ssh, wd) WriteEnvFile(ssh, services, wd, self.deploymentTag, self.flexricTag) - - logging.info(f"will start services {services}") - status = ssh.run(f'docker compose -f {wd}/docker-compose.y*ml up -d -- {services}') - if status.returncode != 0: - msg = f"cannot deploy services {services}: {status.stdout}" - logging.error(msg) - HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg]) - return False - - imagesInfo = [] - fstatus = True - for svc in services.split(): - containerName = GetContainerName(ssh, svc, f"{wd}/docker-compose.y*ml") - healthy = GetContainerHealth(ssh, containerName) - if not healthy: - imagesInfo += [f"Failed to deploy: service {svc}"] - fstatus = False - else: - image = GetImageName(ssh, svc, f"{wd}/docker-compose.y*ml") - logging.info(f"service {svc} healthy, container {containerName}, image {image}") - imagesInfo += [f"service {svc} healthy, image {image}"] - if fstatus: + if num_attempts <= 0: + raise ValueError(f'Invalid value for num_attempts: {num_attempts}, must be greater than 0') + for attempt in range(num_attempts): + imagesInfo = [] + healthInfo = [] + logging.info(f'will start services {services}') + status = ssh.run(f'docker compose -f {wd_yaml} up -d -- {services}') + if status.returncode != 0: + msg = f'cannot deploy services {services}: {status.stdout}' + logging.error(msg) + HTML.CreateHtmlTestRowQueue('N/A', 'NOK', [msg]) + return False + for svc in services.split(): + health, msg = GetServiceHealth(ssh, svc, f'{wd_yaml}') + logging.info(msg) + imagesInfo.append(msg) + healthInfo.append(health) + deployed = all(healthInfo) + if deployed: + break + elif (attempt < num_attempts - 1): + logging.warning(f'Failed to deploy on attempt {attempt}, restart services {services}') + for svc in services.split(): + CopyinServiceLog(ssh, lSourcePath, yaml_dir, svc, wd_yaml, f'{svc}-{HTML.testCase_id}-attempt{attempt}.log') + ssh.run(f'docker compose -f {wd_yaml} down -- {services}') + if deployed: HTML.CreateHtmlTestRowQueue('N/A', 'OK', ['\n'.join(imagesInfo)]) else: HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['\n'.join(imagesInfo)]) - return fstatus + return deployed def UndeployObject(self, HTML, RAN): svr = self.eNB_serverId[self.eNB_instance] @@ -902,7 +905,7 @@ class Containerize(): if services is not None: all_serv = " ".join([s for s, _ in services]) ssh.run(f'docker compose -f {wd}/docker-compose.y*ml stop -- {all_serv}') - copyin_res = all(CopyinContainerLog(ssh, lSourcePath, yaml_dir, c, f'{s}-{HTML.testCase_id}.log') for s, c in services) + copyin_res = all(CopyinServiceLog(ssh, lSourcePath, yaml_dir, s, f"{wd}/docker-compose.y*ml", f'{s}-{HTML.testCase_id}.log') for s, c in services) else: logging.warning('could not identify services to stop => no log file') ssh.run(f'docker compose -f {wd}/docker-compose.y*ml down -v') diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf index cd3842ed5b..ee651b344d 100644 --- a/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf +++ b/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf @@ -230,7 +230,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 75; eNB_instances = [0]; - sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.80.250"; + sdr_addrs = "addr=192.168.80.250"; } ); diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf index a2dfde11c3..321a57657a 100644 --- a/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf +++ b/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf @@ -230,7 +230,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 75; eNB_instances = [0]; - sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.80.250"; + sdr_addrs = "addr=192.168.80.250"; } ); diff --git a/ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf b/ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf index a3f3b2a64c..20460557c4 100644 --- a/ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf +++ b/ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf @@ -230,7 +230,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 75; eNB_instances = [0]; - sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.80.250"; + sdr_addrs = "addr=192.168.80.250"; } ); diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf index b9c569b625..c9e51c352b 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf @@ -263,11 +263,6 @@ fhi_72 = { ru_addr = ("98:ae:71:01:c5:eb", "98:ae:71:01:c5:eb"); mtu = 9600; fh_config = ({ - Tadv_cp_dl = 125; - T2a_cp_dl = (285, 429); - T2a_cp_ul = (285, 429); - T2a_up = (125, 428); - Ta3 = (130, 170); T1a_cp_dl = (285, 470); T1a_cp_ul = (285, 429); T1a_up = (125, 350); diff --git a/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf b/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf index de2a610371..acb000e7c3 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf @@ -271,11 +271,6 @@ fhi_72 = { ru_addr = ("70:b3:d5:e1:5b:81", "70:b3:d5:e1:5b:81"); mtu = 9600; fh_config = ({ - Tadv_cp_dl = 125; - T2a_cp_dl = (259, 500); - T2a_cp_ul = (25, 500); - T2a_up = (134, 375); - Ta3 = (152, 160); T1a_cp_dl = (419, 470); T1a_cp_ul = (285, 336); T1a_up = (294, 345); diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index 44ae5fbb08..3e665f1f0b 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -11,10 +11,10 @@ Ref : feptx_prec : 13.0 feptx_ofdm : 33.0 feptx_total : 55.0 - L1 Tx processing : 220.0 - DLSCH encoding : 130.0 - L1 Rx processing : 387.0 - PUSCH inner-receiver : 150.0 + L1 Tx processing : 200.0 + DLSCH encoding : 100.0 + L1 Rx processing : 330.0 + PUSCH inner-receiver : 120.0 Schedule Response : 3.0 DL & UL scheduling timing : 6.0 UL Indication : 3.0 diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 9bf196338c..bba0f3f57f 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -349,6 +349,7 @@ def ExecuteActionWithParam(action): string_field = test.findtext('services') if string_field is not None: CONTAINERS.services[CONTAINERS.eNB_instance] = string_field + CONTAINERS.num_attempts = int(test.findtext('num_attempts') or 1) CONTAINERS.deploymentTag = cls_containerize.CreateTag(CONTAINERS.ranCommitID, CONTAINERS.ranBranch, CONTAINERS.ranAllowMerge) if action == 'Deploy_Object': success = CONTAINERS.DeployObject(HTML) diff --git a/ci-scripts/tests/deployment.py b/ci-scripts/tests/deployment.py index 47e459d6a4..a7337f6e52 100644 --- a/ci-scripts/tests/deployment.py +++ b/ci-scripts/tests/deployment.py @@ -47,6 +47,7 @@ class TestDeploymentMethods(unittest.TestCase): self.cont.eNBUserName = None self.cont.eNBPassword = None self.cont.eNBSourceCodePath = os.getcwd() + self.cont.num_attempts = 3 def test_deploy(self): self.cont.yamlPath[0] = 'tests/simple-dep/' @@ -65,6 +66,15 @@ class TestDeploymentMethods(unittest.TestCase): self.assertFalse(deploy) self.cont.yamlPath = old + def test_deployfails_2svc(self): + # fails reliably + old = self.cont.yamlPath + self.cont.yamlPath[0] = 'tests/simple-fail-2svc/' + deploy = self.cont.DeployObject(self.html) + self.cont.UndeployObject(self.html, self.ran) + self.assertFalse(deploy) + self.cont.yamlPath = old + def test_deploy_ran(self): self.cont.yamlPath[0] = 'yaml_files/5g_rfsimulator_tdd_dora' self.cont.services[0] = "oai-gnb" diff --git a/ci-scripts/tests/simple-fail-2svc/docker-compose.yml b/ci-scripts/tests/simple-fail-2svc/docker-compose.yml new file mode 100644 index 0000000000..8b30c4aa08 --- /dev/null +++ b/ci-scripts/tests/simple-fail-2svc/docker-compose.yml @@ -0,0 +1,23 @@ +services: + test1: + image: ubuntu:jammy + container_name: test_container1 + cap_drop: + - ALL + entrypoint: /bin/bash -c "false" + healthcheck: + test: /bin/bash -c "true" + interval: 1s + timeout: 1s + retries: 1 + test2: + image: ubuntu:jammy + container_name: test_container2 + cap_drop: + - ALL + entrypoint: /bin/bash -c "sleep infinity" + healthcheck: + test: /bin/bash -c "true" + interval: 1s + timeout: 1s + retries: 1 diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 54d2b221b2..3f3fc5aa3d 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -39,6 +39,12 @@ 040002 030021 030022 + 040021 + 000030 + 040022 + 040023 + 020022 + 040024 100021 222222 @@ -74,6 +80,12 @@ 0 + + IdleSleep + Sleep + 5 + + Attach_UE Attach OAI UE (Wait for IP) @@ -149,9 +161,9 @@ Custom_Command - Simulate a disruption of DL radio channel (ploss 55)(5 sec) + Simulate a disruption of DL radio channel (ploss 55) cacofonix - echo channelmod modify 0 ploss 55 | nc 192.168.71.181 8091 && sleep 5 + echo channelmod modify 0 ploss 55 | nc 192.168.71.181 8091 yes @@ -165,9 +177,9 @@ Custom_Command - Restoration of the original DL channel conditions (ploss 0)(5 sec) + Restoration of the original DL channel conditions (ploss 20) cacofonix - echo channelmod modify 0 ploss 0 | nc 192.168.71.181 8091 && sleep 5 + echo channelmod modify 0 ploss 20 | nc 192.168.71.181 8091 yes @@ -175,7 +187,7 @@ Custom_Command Get UE sync state (UE ID 0) cacofonix - echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_CONNECTED && sleep 10 + echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_CONNECTED yes @@ -184,8 +196,8 @@ true Undeploy all OAI 5G stack ci-scripts/yaml_files/5g_f1_rfsimulator - 30,30,100,100 - 30,30,100,100 + 30,100,100,100 + 30,100,100,100 0 0 diff --git a/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml index 3fd9c83522..15a9ad4065 100644 --- a/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml @@ -89,6 +89,7 @@ ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz 0 0 + 3 diff --git a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml index d4d7568ec4..52b05df661 100644 --- a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml @@ -89,6 +89,7 @@ ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz 0 0 + 3 diff --git a/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml index b89891f496..e9833887df 100644 --- a/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml @@ -89,6 +89,7 @@ ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz 0 0 + 3 diff --git a/ci-scripts/xml_files/container_sa_n310_nrue.xml b/ci-scripts/xml_files/container_sa_n310_nrue.xml index e1e79ccec9..e6b1ba1643 100644 --- a/ci-scripts/xml_files/container_sa_n310_nrue.xml +++ b/ci-scripts/xml_files/container_sa_n310_nrue.xml @@ -80,6 +80,7 @@ ci-scripts/yaml_files/5g_sa_n310_gnb 0 0 + 3 Create_Workspace @@ -93,6 +94,7 @@ ci-scripts/yaml_files/5g_sa_n310_nrue 1 1 + 3 diff --git a/cmake_targets/at_commands/CMakeLists.txt b/cmake_targets/at_commands/CMakeLists.txt index 13067562fe..146b63028c 100755 --- a/cmake_targets/at_commands/CMakeLists.txt +++ b/cmake_targets/at_commands/CMakeLists.txt @@ -145,7 +145,6 @@ set(util_SRC ${OPENAIR_NAS_DIR}/COMMON/UTIL/OctetString.c ${OPENAIR_NAS_DIR}/COMMON/UTIL/parser.c ${OPENAIR_NAS_DIR}/COMMON/UTIL/TLVDecoder.c - ${OPENAIR_NAS_DIR}/COMMON/UTIL/TLVEncoder.c ${OPENAIR_NAS_DIR}/COMMON/UTIL/socket.c ${OPENAIR_NAS_DIR}/COMMON/UTIL/stty.c ) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index e2aa1384d6..5e1ad1467e 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -48,6 +48,7 @@ CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_CMD="$CMAKE" OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 websrv oai_iqplayer imscope" TARGET_LIST="" +BUILD_TOOL_OPT="-j$(nproc)" function print_help() { echo_info " @@ -56,6 +57,8 @@ for a number of distributions (Ubuntu 22-24, Fedora, RHEL9). Options: --arch-native Passes -march=native to the compiler. +--build-tool-opt + Pass options to build tool (ninja/make), e.g. -k (\"keep going\") -c | --clean Erase all files to make a rebuild from start -C | --clean-all @@ -160,6 +163,9 @@ function main() { --arch-native) echo_fatal "Error: specify --arch-native on the command line to cmake directly: ./build_oai --cmake-opt \"-DCMAKE_C_FLAGS=-march=native -DCMAKE_CXX_FLAGS=-march=native\"" shift;; + --build-tool-opt) + BUILD_TOOL_OPT+=" $2" + shift 2;; -c | --clean) CLEAN=1 shift;; @@ -490,7 +496,7 @@ function main() { CMAKE_CMD="$CMAKE_CMD ../../.." echo_info "Running \"$CMAKE_CMD\"" eval $CMAKE_CMD - compilations $BUILD_DIR all.txt $TARGET_LIST + compilations $BUILD_DIR all.txt "$TARGET_LIST" "${BUILD_TOOL_OPT}" ################### # Doxygen Support # ################### @@ -513,9 +519,9 @@ function main() { cd $DIR/nas_sim_tools/build ${CMAKE_CMD% *} .. - compilations nas_sim_tools usim.txt usim - compilations nas_sim_tools nvram.txt nvram - compilations nas_sim_tools conf2uedata.txt conf2uedata + compilations nas_sim_tools usim.txt "usim" "${BUILD_TOOL_OPT}" + compilations nas_sim_tools nvram.txt "nvram" "${BUILD_TOOL_OPT}" + compilations nas_sim_tools conf2uedata.txt "conf2uedata" "${BUILD_TOOL_OPT}" # generate USIM data if [ -f conf2uedata ]; then diff --git a/cmake_targets/nas_sim_tools/CMakeLists.txt b/cmake_targets/nas_sim_tools/CMakeLists.txt index 4f0be81064..98b0772582 100755 --- a/cmake_targets/nas_sim_tools/CMakeLists.txt +++ b/cmake_targets/nas_sim_tools/CMakeLists.txt @@ -31,7 +31,6 @@ set(CONF2UEDATA_LIB_SRC ${OPENAIR_DIR}/openair3/NAS/UE/API/USIM/aka_functions.c ${OPENAIR_DIR}/common/utils/mem/memory.c ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/OctetString.c - ${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/TLVEncoder.c ${OPENAIR_DIR}/common/utils/utils.c ) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index dfb0b5a95e..13c8e4efde 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -208,20 +208,20 @@ check_errors() { } compilations() { - [[ $# -gt 2 ]] || echo_fatal "compilations needs more than three arguments" + [[ $# -eq 4 ]] || echo_fatal "compilations " local dir=$1 - shift 1 - local logfile=$1 - shift 1 - local targets=$@ + local logfile=$2 + local targets=$3 + local build_tool_opt=$4 local verbose=$([ "$VERBOSE_COMPILE" == "1" ] && echo "-v" || echo "") echo cd $OPENAIR_DIR/cmake_targets/$dir/build cd $OPENAIR_DIR/cmake_targets/$dir/build - echo_info "Running \"$CMAKE --build . $verbose --target $targets -- -j$(nproc)\"" $green + cmd="$CMAKE --build . ${verbose} --target ${targets} -- ${build_tool_opt}" + echo_info "Running \"${cmd}\"" $green echo "Log file for compilation is being written to: $dlog/$logfile" set +e { - $CMAKE --build . $verbose --target $targets -- -j$(nproc) + eval ${cmd} ret=$? } > $dlog/$logfile 2>&1 # Print the errors and warnings for CI purposes diff --git a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch new file mode 100644 index 0000000000..8ab8da6aad --- /dev/null +++ b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch @@ -0,0 +1,493 @@ +diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h +index ac5f471..bbd39fe 100644 +--- a/fhi_lib/app/src/common.h ++++ b/fhi_lib/app/src/common.h +@@ -28,7 +28,7 @@ + #include + #include + +-#define VERSIONX "oran_f_release_v1.0" ++#define VERSIONX "oran_f_release_v1.1" + + #define APP_O_DU 0 + #define APP_O_RU 1 +diff --git a/fhi_lib/lib/Makefile b/fhi_lib/lib/Makefile +index eccc4ae..8ddb22e 100644 +--- a/fhi_lib/lib/Makefile ++++ b/fhi_lib/lib/Makefile +@@ -23,12 +23,18 @@ MYCUSTOMSPACE1='------------------------------------------------------------' + ############################################################## + # Tools configuration + ############################################################## +-ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc) +-CC := icc +-CPP := icpc +-AS := as +-AR := ar +-LD := icc ++ifeq ($(WIRELESS_SDK_TOOLCHAIN),gcc) ++ CC := gcc ++ CPP := g++ ++ AS := as ++ AR := ar ++ LD := gcc ++else ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc) ++ CC := icc ++ CPP := icpc ++ AS := as ++ AR := ar ++ LD := icc + else ifeq ($(WIRELESS_SDK_TOOLCHAIN),icx) + CC := icx + CPP := icpx +@@ -72,7 +78,7 @@ ifeq ($(RTE_SDK),) + endif + + RTE_TARGET ?= x86_64-native-linux-icc +-RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) ++RTE_INC := $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH):/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) + + API_DIR := $(PROJECT_DIR)/api + SRC_DIR := $(PROJECT_DIR)/src +@@ -110,8 +116,7 @@ CPP_SRC = $(SRC_DIR)/xran_compression.cpp \ + $(SRC_DIR)/xran_bfp_cplane32.cpp \ + $(SRC_DIR)/xran_bfp_cplane64.cpp \ + $(SRC_DIR)/xran_bfp_uplane_9b16rb.cpp \ +- $(SRC_DIR)/xran_bfp_uplane.cpp \ +- $(SRC_DIR)/xran_mod_compression.cpp ++ $(SRC_DIR)/xran_bfp_uplane.cpp + + CPP_SRC_SNC = $(SRC_DIR)/xran_compression_snc.cpp \ + $(SRC_DIR)/xran_bfp_cplane8_snc.cpp \ +@@ -127,7 +132,7 @@ CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ + -fPIC \ + -Wall \ + -Wimplicit-function-declaration \ +- -g -O3 -mcmodel=large ++ -g -O -mavx512bw -march=skylake-avx512 -mtune=skylake-avx512#--wd1786 -mcmodel=large + + ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc) + CC_FLAGS += -wd1786 -restrict +@@ -138,8 +143,9 @@ CC_FLAGS += -march=icelake-server -mintrinsic-promote -Wno-unused-function -Wno- + endif + + CPP_FLAGS := -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D_GNU_SOURCE -D_REENTRANT -pipe \ +- -falign-functions=16 \ +- -Werror -Wno-unused-variable -std=c++14 -mcmodel=large -fPIC ++ -fPIC \ ++ -falign-functions=16 \ ++ -Werror -Wno-unused-variable -std=c++14 -mcmodel=large -mavx512bw -march=skylake-avx512 -mtune=skylake-avx512 + + ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc) + CPP_FLAGS += -fp-model fast=2 -no-prec-div -no-prec-sqrt -fast-transcendentals -restrict +@@ -186,8 +192,8 @@ CPP_SNC_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(CPP_OBJS_SNC)) + + AS_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(AS_OBJS)) + #-qopt-report=5 -qopt-matmul -qopt-report-phase=all +-CPP_COMP := -O3 -DNDEBUG -xcore-avx512 -fPIE -fasm-blocks +-CPP_COMP_SNC := -O3 -DNDEBUG -march=icelake-server -fPIE -fasm-blocks ++CPP_COMP := -O3 -DNDEBUG -fPIE ++CPP_COMP_SNC := -O3 -DNDEBUG -march=icelake-server -fPIE + CC_FLAGS_FULL := $(CC_FLAGS) $(INC) $(DEF) + CPP_FLAGS_FULL := $(CPP_FLAGS) $(CPP_COMP) $(INC) $(DEF) + CPP_FLAGS_FULL_SNC := $(CPP_FLAGS) $(CPP_COMP_SNC) $(INC) $(DEF) +diff --git a/fhi_lib/lib/api/xran_fh_o_du.h b/fhi_lib/lib/api/xran_fh_o_du.h +index bacf597..90a42a2 100644 +--- a/fhi_lib/lib/api/xran_fh_o_du.h ++++ b/fhi_lib/lib/api/xran_fh_o_du.h +@@ -1193,6 +1193,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb, + */ + int32_t xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond); + ++/** ++ * @ingroup xran ++ * ++ * Function returns Frame, Subframe, Slot Number based on rx_tti ++ * ++ * @param tti ++ * tti for which to compute Frame, Subframe, Slot ++ * ++ * @param nFrameIdx ++ * Pointer to Frame number [0-99] ++ * ++ * @param nSubframeIdx ++ * Pointer to Subframe number [0-10] ++ * ++ * @param nSlotIdx ++ * Pointer to Slot number [0-7] ++ * ++ * @param nSecond ++ * Pointer to current UTC second ++ * ++ * @return ++ * current TTI number [0-7999] ++ */ ++int32_t xran_get_slot_idx_from_tti(uint32_t tti, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond); ++ + /** + * @ingroup xran + * +diff --git a/fhi_lib/lib/api/xran_up_api.h b/fhi_lib/lib/api/xran_up_api.h +index 46e0e1d..409ef4b 100644 +--- a/fhi_lib/lib/api/xran_up_api.h ++++ b/fhi_lib/lib/api/xran_up_api.h +@@ -80,6 +80,7 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf, + uint8_t *subframe_id, + uint8_t *slot_id, + uint8_t *symb_id, ++ uint8_t *filter_id, + union ecpri_seq_id *seq_id, + uint16_t *num_prbu, + uint16_t *start_prbu, +@@ -89,7 +90,8 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf, + int8_t expect_comp, + enum xran_comp_hdr_type staticComp, + uint8_t *compMeth, +- uint8_t *iqWidth); ++ uint8_t *iqWidth, ++ uint8_t *is_prach); + + int xran_prepare_iq_symbol_portion( + struct rte_mbuf *mbuf, +diff --git a/fhi_lib/lib/ethernet/ethdi.c b/fhi_lib/lib/ethernet/ethdi.c +index f5b2fd6..e949fe7 100644 +--- a/fhi_lib/lib/ethernet/ethdi.c ++++ b/fhi_lib/lib/ethernet/ethdi.c +@@ -325,8 +325,8 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, + char bbdev_wdev[32] = ""; + char bbdev_vdev[32] = ""; + char iova_mode[32] = "--iova-mode=pa"; +- char socket_mem[32] = "--socket-mem=8192"; +- char socket_limit[32] = "--socket-limit=8192"; ++ char socket_mem[32] = "--socket-mem=0"; ++ char socket_limit[32] = "--socket-limit=0"; + char ring_name[32] = ""; + int32_t xran_port = -1; + queueid_t qi = 0; +@@ -336,7 +336,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, + cpu = sched_getcpu(); + node = numa_node_of_cpu(cpu); + +- char *argv[] = { name, core_mask, "-n2", iova_mode, socket_mem, socket_limit, "--proc-type=auto", ++ char *argv[] = { name, core_mask, "-n2", iova_mode, socket_mem, socket_limit, "--proc-type=auto", "--no-telemetry", + "--file-prefix", name, "-a0000:00:00.0", bbdev_wdev, bbdev_vdev}; + + if (io_cfg == NULL) +@@ -481,11 +481,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, + ctx->tx_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING_TRX, + rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ); + PANIC_ON(ctx->tx_ring[i] == NULL, "failed to allocate rx ring"); ++ printf("Created ring %s on core %d\n",ring_name,*lcore_id); + for(qi = 0; qi < io_cfg->num_rxq; qi++) { + snprintf(ring_name, RTE_DIM(ring_name), "%s_%d_%d", "rx_ring_cp", i, qi); + ctx->rx_ring[i][qi] = rte_ring_create(ring_name, NUM_MBUFS_RING_TRX, + rte_lcore_to_socket_id(*lcore_id), RING_F_SP_ENQ); + PANIC_ON(ctx->rx_ring[i][qi] == NULL, "failed to allocate rx ring"); ++ printf("Created ring %s on core %d\n",ring_name,*lcore_id); + } + } + } else { +@@ -555,7 +557,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, + ctx->up_dl_pkt_gen_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING, + rte_lcore_to_socket_id(*lcore_id), /*RING_F_SC_DEQ*/0); + PANIC_ON(ctx->up_dl_pkt_gen_ring[i] == NULL, "failed to allocate dl gen ring"); +- printf("created %s\n", ring_name); ++ printf("created %s on core %d\n", ring_name, *lcore_id); + } + + return 1; +diff --git a/fhi_lib/lib/src/xran_bfp_ref.cpp b/fhi_lib/lib/src/xran_bfp_ref.cpp +index e6d3067..8e0abee 100644 +--- a/fhi_lib/lib/src/xran_bfp_ref.cpp ++++ b/fhi_lib/lib/src/xran_bfp_ref.cpp +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + static int16_t saturateAbs(int16_t inVal) + { +diff --git a/fhi_lib/lib/src/xran_bfp_uplane.cpp b/fhi_lib/lib/src/xran_bfp_uplane.cpp +index 59b6850..322d238 100644 +--- a/fhi_lib/lib/src/xran_bfp_uplane.cpp ++++ b/fhi_lib/lib/src/xran_bfp_uplane.cpp +@@ -90,7 +90,7 @@ namespace BFP_UPlane + { + const __m512i* rawData = reinterpret_cast(dataIn.dataExpanded); + /// Abs +- const auto rawDataAbs = _mm512_abs_epi16(rawData[0]); ++ const auto rawDataAbs = _mm512_abs_epi16(_mm512_loadu_epi16(rawData)); + /// No need to do a full horizontal max operation here, just do a max IQ step, + /// compute the exponents and then use a reduce max over all exponent values. This + /// is the fastest way to handle a single RB. +@@ -116,7 +116,7 @@ namespace BFP_UPlane + /// Get AVX512 pointer aligned to desired RB + const __m512i* rawDataIn = reinterpret_cast(dataIn.dataExpanded + numREOffset); + /// Apply the exponent shift +- const auto compData = _mm512_srai_epi16(*rawDataIn, thisExp); ++ const auto compData = _mm512_srai_epi16(_mm512_loadu_epi16(rawDataIn), thisExp); + /// Pack compressed data network byte order + const auto compDataBytePacked = networkBytePack(compData); + /// Store exponent first +@@ -201,7 +201,7 @@ namespace BFP_UPlane + /// Get AVX512 pointer aligned to desired RB + const __m512i* rawDataIn = reinterpret_cast(dataIn.dataExpanded + numREOffset); + /// Apply the exponent shift +- const auto compData = _mm512_srai_epi16(*rawDataIn, thisExp); ++ const auto compData = _mm512_srai_epi16(_mm512_loadu_epi16(rawDataIn), thisExp); + /// Store exponent first + dataOut->dataCompressed[thisRBExpAddr] = thisExp; + /// Now have 1 RB worth of bytes separated into 3 chunks (1 per lane) +@@ -432,4 +432,4 @@ BlockFloatCompander::BFPExpandUserPlaneAvx512(const CompressedData& dataIn, Expa + BFP_UPlane::expandByAllocN(dataIn, dataOut, k_totNumBytesPerRB12, k_maxExpShift12); + break; + } +-} +\ No newline at end of file ++} +diff --git a/fhi_lib/lib/src/xran_common.c b/fhi_lib/lib/src/xran_common.c +index dc40ad9..4ac1fbf 100644 +--- a/fhi_lib/lib/src/xran_common.c ++++ b/fhi_lib/lib/src/xran_common.c +@@ -714,11 +714,14 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) + uint8_t compMeth = 0; + uint8_t iqWidth = 0; + ++ uint8_t is_prach = 0; ++ + int ret = MBUF_FREE; + uint32_t mb_free = 0; + int32_t valid_res = 0; + int expect_comp = (p_dev_ctx->fh_cfg.ru_conf.compMeth != XRAN_COMPMETHOD_NONE); + enum xran_comp_hdr_type staticComp = p_dev_ctx->fh_cfg.ru_conf.xranCompHdrType; ++ uint8_t filter_id; + + if(first_call == 0) + return ret; +@@ -733,9 +736,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) + return MBUF_FREE; + + num_bytes = xran_extract_iq_samples(pkt, &iq_samp_buf, +- &CC_ID, &Ant_ID, &frame_id, &subframe_id, &slot_id, &symb_id, &seq, ++ &CC_ID, &Ant_ID, &frame_id, &subframe_id, &slot_id, &symb_id, &filter_id, &seq, + &num_prbu, &start_prbu, &sym_inc, &rb, §_id, +- expect_comp, staticComp, &compMeth, &iqWidth); ++ expect_comp, staticComp, &compMeth, &iqWidth, &is_prach); + if (num_bytes <= 0) + { + print_err("num_bytes is wrong [%d]\n", num_bytes); +@@ -781,10 +784,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) + + else + { +- valid_res = xran_pkt_validate(p_dev_ctx, +- pkt, iq_samp_buf, num_bytes, +- CC_ID, Ant_ID, frame_id, subframe_id, slot_id, symb_id, +- &seq, num_prbu, start_prbu, sym_inc, rb, sect_id); ++ pCnt->rx_counter++; ++ pCnt->Rx_on_time++; ++ pCnt->Total_msgs_rcvd++; + #ifndef FCN_ADAPT + if(valid_res != 0) + { +@@ -807,8 +809,7 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) + PrachCfg = &(p_dev_ctx->PrachCPConfig); + } + +- if (Ant_ID >= PrachCfg->eAxC_offset && p_dev_ctx->fh_cfg.prachEnable) +- { ++ if (/*Ant_ID >= PrachCfg->eAxC_offset &&*/p_dev_ctx->fh_cfg.prachEnable && is_prach) { + /* PRACH packet has ruportid = num_eAxc + ant_id */ + Ant_ID -= PrachCfg->eAxC_offset; + symbol_total_bytes[p_dev_ctx->xran_port_id][CC_ID][Ant_ID] += num_bytes; +@@ -1412,7 +1413,7 @@ int generate_cpmsg_prach(void *pHandle, struct xran_cp_gen_params *params, struc + if(XRAN_FILTERINDEX_PRACH_ABC == pPrachCPConfig->filterIdx) + { + timeOffset = timeOffset >> nNumerology; //original number is Tc, convert to Ts based on mu +- if ((slot_id == 0) || (slot_id == (SLOTNUM_PER_SUBFRAME(pxran_lib_ctx->interval_us_local) >> 1))) ++ if (startSymId > 0 && ((slot_id == 0) || (slot_id == (SLOTNUM_PER_SUBFRAME(pxran_lib_ctx->interval_us_local) >> 1)))) + timeOffset += 16; + } + else +@@ -1547,8 +1548,7 @@ int32_t ring_processing_func(void* args) + + for (i = 0; i < ctx->io_cfg.num_vfs && i < XRAN_VF_MAX; i++){ + for(qi = 0; qi < ctx->rxq_per_port[i]; qi++) { +- if (process_ring(ctx->rx_ring[i][qi], i, qi)) +- return 0; ++ process_ring(ctx->rx_ring[i][qi],i,qi); + } + } + +diff --git a/fhi_lib/lib/src/xran_compression.cpp b/fhi_lib/lib/src/xran_compression.cpp +index 112caae..7c74342 100644 +--- a/fhi_lib/lib/src/xran_compression.cpp ++++ b/fhi_lib/lib/src/xran_compression.cpp +@@ -62,7 +62,7 @@ xranlib_compress(const struct xranlib_compress_request *request, + return xranlib_5gnr_mod_compression(&mod_request, &mod_response); + } + else{ +- if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) { ++ if(false) { + return xranlib_compress_avxsnc(request,response); + } else { + return xranlib_compress_avx512(request,response); +@@ -89,7 +89,7 @@ xranlib_decompress(const struct xranlib_decompress_request *request, + return xranlib_5gnr_mod_decompression(&mod_request, &mod_response); + } + else{ +- if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) { ++ if(false) { + return xranlib_decompress_avxsnc(request,response); + } else { + return xranlib_decompress_avx512(request,response); +@@ -101,7 +101,7 @@ int32_t + xranlib_compress_bfw(const struct xranlib_compress_request *request, + struct xranlib_compress_response *response) + { +- if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) { ++ if(false) { + return xranlib_compress_avxsnc_bfw(request,response); + } else { + return xranlib_compress_avx512_bfw(request,response); +@@ -112,7 +112,7 @@ int32_t + xranlib_decompress_bfw(const struct xranlib_decompress_request *request, + struct xranlib_decompress_response *response) + { +- if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) { ++ if(false) { + return xranlib_decompress_avxsnc_bfw(request,response); + } else { + return xranlib_decompress_avx512_bfw(request,response); +diff --git a/fhi_lib/lib/src/xran_main.c b/fhi_lib/lib/src/xran_main.c +index 7c472d7..7bab6a8 100644 +--- a/fhi_lib/lib/src/xran_main.c ++++ b/fhi_lib/lib/src/xran_main.c +@@ -306,7 +306,7 @@ xran_init_prach(struct xran_fh_config* pConf, struct xran_device_ctx * p_xran_de + printf("PRACH start symbol %u lastsymbol %u\n", p_xran_dev_ctx->prach_start_symbol[0], p_xran_dev_ctx->prach_last_symbol[0]); + } + +- pPrachCPConfig->eAxC_offset = xran_get_num_eAxc(p_xran_dev_ctx); ++ pPrachCPConfig->eAxC_offset = pPRACHConfig->eAxC_offset; + print_dbg("PRACH eAxC_offset %d\n", pPrachCPConfig->eAxC_offset); + + /* Save some configs for app */ +@@ -1570,6 +1570,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru + { + case ECPRI_IQ_DATA: + pkt_data[num_data++] = pkt; ++ uint8_t *pkt_bytes=rte_pktmbuf_mtod(pkt,uint8_t*); + break; + // For RU emulation + case ECPRI_RT_CONTROL_DATA: +@@ -1587,7 +1588,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru + break; + default: + if (p_dev_ctx->fh_init.io_cfg.id == O_DU) { +- print_err("Invalid eCPRI message type - %d", ecpri_hdr->cmnhdr.bits.ecpri_mesg_type); ++ rte_pktmbuf_free(pkt); + } + break; + } +@@ -2347,8 +2348,7 @@ ring_processing_func_per_port(void* args) + for (i = 0; i < ctx->io_cfg.num_vfs && i < XRAN_VF_MAX; i = i+1) { + if (ctx->vf2xran_port[i] == port_id) { + for(qi = 0; qi < ctx->rxq_per_port[port_id]; qi++){ +- if (process_ring(ctx->rx_ring[i][qi], i, qi)) +- return 0; ++ process_ring(ctx->rx_ring[i][qi],i,qi); + } + } + } +@@ -2414,9 +2414,6 @@ xran_spawn_workers(void) + nWorkerCore = nWorkerCore << 1; + } + +- extern int _may_i_use_cpu_feature(unsigned __int64); +- icx_cpu = _may_i_use_cpu_feature(_FEATURE_AVX512IFMA52); +- + printf("O-XU %d\n", eth_ctx->io_cfg.id); + printf("HW %d\n", icx_cpu); + printf("Num cores %d\n", total_num_cores); +@@ -4034,6 +4031,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, + return tti; + } + ++int32_t ++xran_get_slot_idx_from_tti(uint32_t tti, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond) ++{ ++ struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx_by_id(0); ++ if (!p_xran_dev_ctx) ++ { ++ print_err("Null xRAN context on port id %u!!\n", 0); ++ return 0; ++ } ++ ++ *nSlotIdx = (uint32_t)XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local)); ++ *nSubframeIdx = (uint32_t)XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local), SUBFRAMES_PER_SYSTEMFRAME); ++ *nFrameIdx = (uint32_t)XranGetFrameNum(tti,0/*xran_getSfnSecStart()*/,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local)); ++ *nSecond = timing_get_current_second(); ++ ++ return tti; ++} ++ + int32_t + xran_set_debug_stop(int32_t value, int32_t count) + { +diff --git a/fhi_lib/lib/src/xran_mod_compression.cpp b/fhi_lib/lib/src/xran_mod_compression.cpp +index 7d4a5d0..b9b44ac 100644 +--- a/fhi_lib/lib/src/xran_mod_compression.cpp ++++ b/fhi_lib/lib/src/xran_mod_compression.cpp +@@ -747,9 +747,9 @@ int xranlib_5gnr_mod_compression(const struct xranlib_5gnr_mod_compression_reque + #ifdef C_Module_Used + return (xranlib_5gnr_mod_compression_c(request, response)); + #else +- if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) ++ if (false) { + return (xranlib_5gnr_mod_compression_snc(request, response)); +- else ++ } else { + return (xranlib_5gnr_mod_compression_avx512(request, response)); + #endif + } +diff --git a/fhi_lib/lib/src/xran_up_api.c b/fhi_lib/lib/src/xran_up_api.c +index fe22a1f..f6c4830 100644 +--- a/fhi_lib/lib/src/xran_up_api.c ++++ b/fhi_lib/lib/src/xran_up_api.c +@@ -336,6 +336,7 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf, + uint8_t *subframe_id, + uint8_t *slot_id, + uint8_t *symb_id, ++ uint8_t *filter_id, + union ecpri_seq_id *seq_id, + uint16_t *num_prbu, + uint16_t *start_prbu, +@@ -345,7 +346,8 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf, + int8_t expect_comp, + enum xran_comp_hdr_type staticComp, + uint8_t *compMeth, +- uint8_t *iqWidth) ++ uint8_t *iqWidth, ++ uint8_t *is_prach) + { + #if XRAN_MLOG_VAR + uint32_t mlogVar[10]; +@@ -381,6 +383,7 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf, + return 0; /* packet too short */ + + radio_hdr->sf_slot_sym.value = rte_be_to_cpu_16(radio_hdr->sf_slot_sym.value); ++ *is_prach = (radio_hdr->data_feature.filter_id > 0); + + if (frame_id) + *frame_id = radio_hdr->frame_id; +@@ -394,6 +397,9 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf, + if (symb_id) + *symb_id = radio_hdr->sf_slot_sym.symb_id; + ++ if (filter_id) ++ *filter_id = radio_hdr->data_feature.filter_id; ++ + /* Process data section hdr */ + struct data_section_hdr *data_hdr = + (void *)rte_pktmbuf_adj(mbuf, sizeof(*radio_hdr)); diff --git a/common/config/yaml/config_yaml.cpp b/common/config/yaml/config_yaml.cpp index c2af51e2db..eb510c94f5 100644 --- a/common/config/yaml/config_yaml.cpp +++ b/common/config/yaml/config_yaml.cpp @@ -265,7 +265,7 @@ extern "C" int config_yaml_get(configmodule_interface_t *cfg, paramdef_t *cfgopt } } config_yaml::GetParams(cfg, node, cfgoptions, numoptions); - return 0; + return numoptions; } extern "C" int config_yaml_getlist(configmodule_interface_t *cfg, @@ -286,10 +286,10 @@ extern "C" int config_yaml_getlist(configmodule_interface_t *cfg, return -1; } + ParamList->numelt = node.size(); if (!node.IsSequence()) { return -1; } - ParamList->numelt = node.size(); if (ParamList->numelt > 0 && params != NULL) { ParamList->paramarray = static_cast(config_allocate_new(cfg, ParamList->numelt * sizeof(paramdef_t *), true)); diff --git a/common/config/yaml/tests/CMakeLists.txt b/common/config/yaml/tests/CMakeLists.txt index b28bb8d47f..6290f2fc15 100644 --- a/common/config/yaml/tests/CMakeLists.txt +++ b/common/config/yaml/tests/CMakeLists.txt @@ -9,3 +9,4 @@ configure_file(test_list.yaml test_list.yaml COPYONLY) configure_file(test_string.yaml test_string.yaml COPYONLY) configure_file(test_list_of_mappings.yml test_list_of_mappings.yml COPYONLY) configure_file(test_int_array.yaml test_int_array.yaml COPYONLY) +configure_file(test_read_mapping_as_list.yaml test_read_mapping_as_list.yaml COPYONLY) diff --git a/common/config/yaml/tests/test_read_mapping_as_list.yaml b/common/config/yaml/tests/test_read_mapping_as_list.yaml new file mode 100644 index 0000000000..2e17dcce36 --- /dev/null +++ b/common/config/yaml/tests/test_read_mapping_as_list.yaml @@ -0,0 +1,4 @@ +fhi_72: + element1: value1 + element2: value2 + element3: value3 diff --git a/common/config/yaml/tests/test_yaml_config.cpp b/common/config/yaml/tests/test_yaml_config.cpp index 921a455dfd..deaa52cd1a 100644 --- a/common/config/yaml/tests/test_yaml_config.cpp +++ b/common/config/yaml/tests/test_yaml_config.cpp @@ -125,7 +125,7 @@ TEST(yaml_config, test_high_recusion) { p.type = TYPE_UINT16; p.u16ptr = &value; char prefix[] = "test.test1.test2.test3.test4"; - EXPECT_EQ(config_yaml_get(cfg, &p, 1, prefix), 0); + EXPECT_EQ(config_yaml_get(cfg, &p, 1, prefix), 1); EXPECT_EQ(value, i); } @@ -175,7 +175,7 @@ TEST(yaml_config, test_string_auto_alloc) { // Test automatic allocation of strings char prefix[] = "test"; - EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 0); + EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 1); EXPECT_NE(param.strptr, nullptr); EXPECT_EQ(strcmp(*param.strptr, "testvalue"), 0); EXPECT_EQ(cfg->numptrs, 2); @@ -200,7 +200,7 @@ TEST(yaml_config, test_string_no_realloc) { char prefix[] = "test"; char* non_null_pointer_to_pointer = nullptr; param.strptr = &non_null_pointer_to_pointer; - EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 0); + EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 1); EXPECT_EQ(param.strptr, &non_null_pointer_to_pointer); EXPECT_EQ(strcmp(*param.strptr, "testvalue"), 0); EXPECT_EQ(cfg->numptrs, 1); @@ -225,7 +225,7 @@ TEST(yaml_config, test_string_pointer_available) { char prefix[] = "test"; char *container = (char *)malloc(sizeof(char) * 30); param.strptr = &container; - EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 0); + EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 1); EXPECT_EQ(param.strptr, &container); EXPECT_EQ(strcmp(*param.strptr, "testvalue"), 0); EXPECT_EQ(cfg->numptrs, 0); @@ -253,7 +253,7 @@ TEST(yaml_config, test_string_default_value) { param.defstrval = default_value; param.strptr = nullptr; sprintf(param.optname, "%s", "stringvalue_missing"); - EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 0); + EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 1); EXPECT_NE(param.strptr, nullptr); EXPECT_EQ(strcmp(*param.strptr, "default"), 0); EXPECT_EQ(cfg->numptrs, 2) << " 2 pointers required, 1 for the string, one for the pointer-to string"; @@ -276,7 +276,7 @@ TEST(yaml_config, test_stringlist) { // Test automatic allocation of string lists char prefix[] = "test"; - EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 0); + EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 1); EXPECT_NE(param.strptr, nullptr); for (auto i = 0; i < param.numelt; i++) { std::cout << (param.strlistptr)[i] << std::endl; @@ -302,7 +302,7 @@ TEST(yaml_config, test_list_of_mappings) { // Test automatic allocation of string lists char prefix1[] = "test.list.[0]"; - EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix1), 0); + EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix1), 1); EXPECT_NE(param.strptr, nullptr); EXPECT_STREQ("value1", param.strlistptr[0]); EXPECT_STREQ("value2", param.strlistptr[1]); @@ -310,7 +310,7 @@ TEST(yaml_config, test_list_of_mappings) { char prefix2[] = "test.list.[1]"; param.strlistptr = nullptr; - EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix2), 0); + EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix2), 1); EXPECT_NE(param.strptr, nullptr); EXPECT_STREQ("value4", param.strlistptr[0]); EXPECT_STREQ("value5", param.strlistptr[1]); @@ -334,7 +334,7 @@ TEST(yaml_config, test_int_array) { // Test automatic allocation of int arrays char prefix[] = "test"; - EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 0); + EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 1); EXPECT_NE(param.iptr, nullptr); ASSERT_EQ(param.numelt, 4); EXPECT_EQ(1, param.iptr[0]); @@ -345,7 +345,7 @@ TEST(yaml_config, test_int_array) { param.uptr = nullptr; param.numelt = 0; sprintf(param.optname, "%s", "array2"); - EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 0); + EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 1); EXPECT_NE(param.uptr, nullptr); ASSERT_EQ(param.numelt, 3); EXPECT_EQ(1U, param.uptr[0]); @@ -355,7 +355,7 @@ TEST(yaml_config, test_int_array) { param.uptr = nullptr; param.numelt = 0; sprintf(param.optname, "%s", "non-existent-array"); - EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 0); + EXPECT_EQ(config_yaml_get(cfg, ¶m, 1, prefix), 1); EXPECT_EQ(param.uptr, nullptr); ASSERT_EQ(param.numelt, 0); @@ -364,6 +364,33 @@ TEST(yaml_config, test_int_array) { end_configmodule(cfg); } +TEST(yaml_config, test_read_mapping_as_list) { + configmodule_interface_t *cfg = static_cast(calloc(1, sizeof(*cfg))); + cfg->cfgP[0] = strdup("test_read_mapping_as_list.yaml"); + EXPECT_EQ(config_yaml_init(cfg), 0); + char cfgstring[] = "fhi_72"; + + paramlist_def_t pl = {0}; + strncpy(pl.listname, cfgstring, sizeof(pl.listname) - 1); + config_yaml_getlist(cfg, &pl, NULL, 0, /* prefix */ NULL); + EXPECT_NE(pl.numelt, 0); + EXPECT_EQ(pl.numelt, 3); + + paramdef_t params[4] = {0}; + for (auto i = 0U; i < sizeofArray(params); i++) { + sprintf(params[i].optname, "%s%d", "element_", i+1); + params[i].type = TYPE_STRING; + params[i].paramflags = PARAMFLAG_MANDATORY; + } + params[sizeofArray(params) - 1].paramflags = 0; + int ret = config_yaml_get(cfg, params, sizeofArray(params), cfgstring); + EXPECT_EQ(ret, 4); + + config_yaml_end(cfg); + free(cfg->cfgP[0]); + end_configmodule(cfg); +} + int main(int argc, char** argv) { logInit(); diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c index 62230d9ba3..80244c0912 100644 --- a/common/utils/LOG/log.c +++ b/common/utils/LOG/log.c @@ -69,13 +69,13 @@ typedef struct { static log_mem_cnt_t log_mem_d[2]; static int log_mem_flag = 0; -volatile int log_mem_side=0; +static volatile int log_mem_side = 0; static pthread_mutex_t log_mem_lock; static pthread_cond_t log_mem_notify; static pthread_t log_mem_thread; static int log_mem_file_cnt=0; -volatile int log_mem_write_flag=0; -volatile int log_mem_write_side=0; +static volatile int log_mem_write_flag = 0; +static volatile int log_mem_write_side = 0; static char * log_mem_filename; static mapping log_level_names[] = {{"error", OAILOG_ERR}, diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index dc9080b158..0f306501f0 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -87,6 +87,10 @@ ID = ENB_PHY_INITIATE_RA_PROCEDURE DESC = eNodeB initiates a random access procedure after detecting enough energy for one of the preambles GROUP = ALL:PHY:ENB:WIRESHARK FORMAT = int,eNB_ID : int,frame : int,subframe : int,preamble : int,energy : int,delay +ID = UE_PHY_INITIATE_RA_PROCEDURE + DESC = UE initiates a random access procedure with a given preamble (can be used for both LTE and NR) + GROUP = ALL:PHY:UE:WIRESHARK + FORMAT = int,frame : int,subframe_or_slot : int,preamble : int,power ID = GNB_PHY_DL_TICK DESC = gNodeB downlink tick - one tick per ms at start of downlink processing GROUP = ALL:PHY:GRAPHIC:GNB @@ -99,6 +103,10 @@ ID = GNB_PHY_MIB DESC = NR MIB data GROUP = ALL:PHY:GNB:WIRESHARK FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data +ID = NRUE_PHY_MIB + DESC = NR MIB data as received by an UE + GROUP = ALL:PHY:UE:WIRESHARK + FORMAT = int,frame : int,slot : int,ssb_index : buffer,data ID = GNB_PHY_PUCCH_PUSCH_IQ DESC = gNodeB input data in the frequency domain for a slot where some PUCCH or PUSCH detection was done GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB @@ -181,6 +189,18 @@ ID = GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA DESC = NR MAC downlink retransmitted PDU for an UE GROUP = ALL:MAC:GNB:WIRESHARK FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : int,round : buffer,data +ID = NRUE_MAC_DL_PDU_WITH_DATA + DESC = NR MAC downlink PDU for an UE + GROUP = ALL:MAC:UE:WIRESHARK + FORMAT = int,rnti : int,frame : int,slot : int,harq_pid : buffer,data +ID = NRUE_MAC_UL_PDU_WITH_DATA + DESC = NR MAC uplink PDU for an UE + GROUP = ALL:MAC:UE:WIRESHARK + FORMAT = int,rnti : int,frame : int,slot : int,harq_pid : buffer,data +ID = NRUE_MAC_DL_RAR_PDU_WITH_DATA + DESC = NR MAC downlink PDU for RAR + GROUP = ALL:MAC:UE:WIRESHARK + FORMAT = int,rnti : int,frame : int,slot : buffer,data #RLC logs ID = ENB_RLC_DL diff --git a/common/utils/T/tracer/macpdu2wireshark.c b/common/utils/T/tracer/macpdu2wireshark.c index d7c4b23b51..607023db6a 100644 --- a/common/utils/T/tracer/macpdu2wireshark.c +++ b/common/utils/T/tracer/macpdu2wireshark.c @@ -44,6 +44,10 @@ typedef struct { int preamble_frame; int preamble_subframe; int preamble_preamble; + /* UE RA preamble */ + int ue_preamble_frame; + int ue_preamble_subframe; + int ue_preamble_preamble; /* RAR */ int rar_rnti; int rar_frame; @@ -82,6 +86,27 @@ typedef struct { int nr_rar_frame; int nr_rar_slot; int nr_rar_data; + /* NR UE mib */ + int nr_ue_mib_frame; + int nr_ue_mib_slot; + int nr_ue_mib_data; + /* NR UE ul */ + int nr_ue_ul_rnti; + int nr_ue_ul_frame; + int nr_ue_ul_slot; + int nr_ue_ul_harq_pid; + int nr_ue_ul_data; + /* NR UE dl */ + int nr_ue_dl_rnti; + int nr_ue_dl_frame; + int nr_ue_dl_slot; + int nr_ue_dl_harq_pid; + int nr_ue_dl_data; + /* NR UE RAR */ + int nr_ue_rar_rnti; + int nr_ue_rar_frame; + int nr_ue_rar_slot; + int nr_ue_rar_data; /* config */ int no_mib; @@ -235,6 +260,15 @@ void preamble(void *_d, event e) e.e[d->preamble_preamble].i, NO_SR_RNTI); } +void ue_preamble(void *_d, event e) +{ + ev_data *d = _d; + trace_lte(d, DIRECTION_UPLINK, NO_RNTI, 0, + e.e[d->ue_preamble_frame].i, e.e[d->ue_preamble_subframe].i, + NULL, 0, + e.e[d->ue_preamble_preamble].i, NO_SR_RNTI); +} + void rar(void *_d, event e) { ev_data *d = _d; @@ -347,7 +381,7 @@ void nr_dl(void *_d, event e) { ev_data *d = _d; - if (e.e[d->dl_rnti].i == 0xffff) { + if (e.e[d->nr_dl_rnti].i == 0xffff) { if (d->no_sib) return; if (d->max_sib && d->cur_sib == d->max_sib) return; @@ -356,7 +390,7 @@ void nr_dl(void *_d, event e) } trace_nr(d, NR_DIRECTION_DOWNLINK, - e.e[d->dl_rnti].i != 0xffff ? NR_C_RNTI : NR_SI_RNTI, + e.e[d->nr_dl_rnti].i != 0xffff ? NR_C_RNTI : NR_SI_RNTI, e.e[d->nr_dl_rnti].i, e.e[d->nr_dl_frame].i, e.e[d->nr_dl_slot].i, e.e[d->nr_dl_harq_pid].i, e.e[d->nr_dl_data].b, e.e[d->nr_dl_data].bsize, NO_PREAMBLE); @@ -387,6 +421,21 @@ void nr_mib(void *_d, event e) e.e[d->nr_mib_data].b, e.e[d->nr_mib_data].bsize, NO_PREAMBLE); } +void nr_ue_mib(void *_d, event e) +{ + ev_data *d = _d; + + if (d->no_mib) return; + + if (d->max_mib && d->cur_mib == d->max_mib) return; + + d->cur_mib++; + + trace_nr(d, NR_DIRECTION_DOWNLINK, NR_NO_RNTI, 0, + e.e[d->nr_ue_mib_frame].i, e.e[d->nr_ue_mib_slot].i, 0 /* harq pid */, + e.e[d->nr_ue_mib_data].b, e.e[d->nr_ue_mib_data].bsize, NO_PREAMBLE); +} + void nr_rar(void *_d, event e) { ev_data *d = _d; @@ -396,61 +445,120 @@ void nr_rar(void *_d, event e) e.e[d->nr_rar_data].b, e.e[d->nr_rar_data].bsize, NO_PREAMBLE); } +void nr_ue_ul(void *_d, event e) +{ + ev_data *d = _d; + + trace_nr(d, NR_DIRECTION_UPLINK, NR_C_RNTI, e.e[d->nr_ue_ul_rnti].i, + e.e[d->nr_ue_ul_frame].i, e.e[d->nr_ue_ul_slot].i, + e.e[d->nr_ue_ul_harq_pid].i, e.e[d->nr_ue_ul_data].b, + e.e[d->nr_ue_ul_data].bsize, NO_PREAMBLE); +} + +void nr_ue_dl(void *_d, event e) +{ + ev_data *d = _d; + + if (e.e[d->nr_ue_dl_rnti].i == 0xffff) { + if (d->no_sib) return; + + if (d->max_sib && d->cur_sib == d->max_sib) return; + + d->cur_sib++; + } + + trace_nr(d, NR_DIRECTION_DOWNLINK, + e.e[d->nr_ue_dl_rnti].i != 0xffff ? NR_C_RNTI : NR_SI_RNTI, + e.e[d->nr_ue_dl_rnti].i, e.e[d->nr_ue_dl_frame].i, + e.e[d->nr_ue_dl_slot].i, e.e[d->nr_ue_dl_harq_pid].i, + e.e[d->nr_ue_dl_data].b, e.e[d->nr_ue_dl_data].bsize, NO_PREAMBLE); +} + +void nr_ue_rar(void *_d, event e) +{ + ev_data *d = _d; + trace_nr(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->nr_ue_rar_rnti].i, + e.e[d->nr_ue_rar_frame].i, e.e[d->nr_ue_rar_slot].i, 0, + e.e[d->nr_ue_rar_data].b, e.e[d->nr_ue_rar_data].bsize, + NO_PREAMBLE); +} + /****************************************************************************/ /****************************************************************************/ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id, - int preamble_id, int rar_id, int sr_id, + int preamble_id, int ue_preamble_id, int rar_id, int sr_id, int nr_ul_id, int nr_dl_id, int nr_dl_retx_id, int nr_mib_id, - int nr_rar_id) + int nr_rar_id, int nr_ue_mib_id, int nr_ue_ul_id, + int nr_ue_dl_id, int nr_ue_rar_id) { database_event_format f; int i; - d->ul_rnti = -1; - d->ul_frame = -1; - d->ul_subframe = -1; - d->ul_data = -1; - d->dl_rnti = -1; - d->dl_frame = -1; - d->dl_subframe = -1; - d->dl_data = -1; - d->mib_frame = -1; - d->mib_subframe = -1; - d->mib_data = -1; - d->preamble_frame = -1; - d->preamble_subframe = -1; - d->preamble_preamble = -1; - d->rar_rnti = -1; - d->rar_frame = -1; - d->rar_subframe = -1; - d->rar_data = -1; - d->sr_rnti = -1; - d->sr_frame = -1; - d->sr_subframe = -1; + d->ul_rnti = -1; + d->ul_frame = -1; + d->ul_subframe = -1; + d->ul_data = -1; + d->dl_rnti = -1; + d->dl_frame = -1; + d->dl_subframe = -1; + d->dl_data = -1; + d->mib_frame = -1; + d->mib_subframe = -1; + d->mib_data = -1; + d->preamble_frame = -1; + d->preamble_subframe = -1; + d->preamble_preamble = -1; + d->ue_preamble_frame = -1; + d->ue_preamble_subframe = -1; + d->ue_preamble_preamble = -1; + d->rar_rnti = -1; + d->rar_frame = -1; + d->rar_subframe = -1; + d->rar_data = -1; + d->sr_rnti = -1; + d->sr_frame = -1; + d->sr_subframe = -1; - d->nr_ul_rnti = -1; - d->nr_ul_frame = -1; - d->nr_ul_slot = -1; - d->nr_ul_harq_pid = -1; - d->nr_ul_data = -1; - d->nr_dl_rnti = -1; - d->nr_dl_frame = -1; - d->nr_dl_slot = -1; - d->nr_dl_harq_pid = -1; - d->nr_dl_data = -1; - d->nr_dl_retx_rnti = -1; - d->nr_dl_retx_frame = -1; - d->nr_dl_retx_slot = -1; - d->nr_dl_retx_harq_pid = -1; - d->nr_dl_retx_data = -1; - d->nr_mib_frame = -1; - d->nr_mib_slot = -1; - d->nr_mib_data = -1; - d->nr_rar_rnti = -1; - d->nr_rar_frame = -1; - d->nr_rar_slot = -1; - d->nr_rar_data = -1; + d->nr_ul_rnti = -1; + d->nr_ul_frame = -1; + d->nr_ul_slot = -1; + d->nr_ul_harq_pid = -1; + d->nr_ul_data = -1; + d->nr_dl_rnti = -1; + d->nr_dl_frame = -1; + d->nr_dl_slot = -1; + d->nr_dl_harq_pid = -1; + d->nr_dl_data = -1; + d->nr_dl_retx_rnti = -1; + d->nr_dl_retx_frame = -1; + d->nr_dl_retx_slot = -1; + d->nr_dl_retx_harq_pid = -1; + d->nr_dl_retx_data = -1; + d->nr_mib_frame = -1; + d->nr_mib_slot = -1; + d->nr_mib_data = -1; + d->nr_rar_rnti = -1; + d->nr_rar_frame = -1; + d->nr_rar_slot = -1; + d->nr_rar_data = -1; + d->nr_ue_mib_frame = -1; + d->nr_ue_mib_slot = -1; + d->nr_ue_mib_data = -1; + d->nr_ue_ul_rnti = -1; + d->nr_ue_ul_frame = -1; + d->nr_ue_ul_slot = -1; + d->nr_ue_ul_harq_pid = -1; + d->nr_ue_ul_data = -1; + d->nr_ue_dl_rnti = -1; + d->nr_ue_dl_frame = -1; + d->nr_ue_dl_slot = -1; + d->nr_ue_dl_harq_pid = -1; + d->nr_ue_dl_data = -1; + d->nr_ue_rar_rnti = -1; + d->nr_ue_rar_frame = -1; + d->nr_ue_rar_slot = -1; + d->nr_ue_rar_data = -1; #define G(var_name, var_type, var) \ if (!strcmp(f.name[i], var_name)) { \ @@ -508,6 +616,18 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id, if (d->preamble_frame == -1 || d->preamble_subframe == -1 || d->preamble_preamble == -1) goto error; + /* ue preamble: frame, subframe, preamble */ + f = get_format(database, ue_preamble_id); + + for (i = 0; i < f.count; i++) { + G("frame", "int", d->ue_preamble_frame); + G("subframe_or_slot", "int", d->ue_preamble_subframe); + G("preamble", "int", d->ue_preamble_preamble); + } + + if (d->ue_preamble_frame == -1 || d->ue_preamble_subframe == -1 || + d->ue_preamble_preamble == -1) goto error; + /* rar: rnti, frame, subframe, data */ f = get_format(database, rar_id); @@ -605,6 +725,64 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id, d->nr_rar_data == -1) goto error; + /* NR UE MIB: frame, slot, data */ + f = get_format(database, nr_ue_mib_id); + + for (i = 0; i < f.count; i++) { + G("frame", "int", d->nr_ue_mib_frame); + G("slot", "int", d->nr_ue_mib_slot); + G("data", "buffer", d->nr_ue_mib_data); + } + + if (d->nr_ue_mib_frame == -1 || d->nr_ue_mib_slot== -1 || + d->nr_ue_mib_data == -1) + goto error; + + /* NR UE ul: rnti, frame, slot, harq_pid, data */ + f = get_format(database, nr_ue_ul_id); + + for (i = 0; i < f.count; i++) { + G("rnti", "int", d->nr_ue_ul_rnti); + G("frame", "int", d->nr_ue_ul_frame); + G("slot", "int", d->nr_ue_ul_slot); + G("harq_pid", "int", d->nr_ue_ul_harq_pid); + G("data", "buffer", d->nr_ue_ul_data); + } + + if (d->nr_ue_ul_rnti == -1 || d->nr_ue_ul_frame == -1 || + d->nr_ue_ul_slot == -1 || d->nr_ue_ul_harq_pid == -1 || + d->nr_ue_ul_data == -1) + goto error; + + /* NR UE dl: rnti, frame, slot, harq_pid, data */ + f = get_format(database, nr_ue_dl_id); + + for (i = 0; i < f.count; i++) { + G("rnti", "int", d->nr_ue_dl_rnti); + G("frame", "int", d->nr_ue_dl_frame); + G("slot", "int", d->nr_ue_dl_slot); + G("harq_pid", "int", d->nr_ue_dl_harq_pid); + G("data", "buffer", d->nr_ue_dl_data); + } + + if (d->nr_ue_dl_rnti == -1 || d->nr_ue_dl_frame == -1 || + d->nr_ue_dl_slot == -1 || d->nr_ue_dl_harq_pid == -1 || + d->nr_ue_dl_data == -1) + goto error; + + /* NR UE rar: rnti, frame, slot, data */ + f = get_format(database, nr_ue_rar_id); + + for (i = 0; i < f.count; i++) { + G("rnti", "int", d->nr_ue_rar_rnti); + G("frame", "int", d->nr_ue_rar_frame); + G("slot", "int", d->nr_ue_rar_slot); + G("data", "buffer", d->nr_ue_rar_data); + } + + if (d->nr_ue_rar_rnti == -1 || d->nr_ue_rar_frame == -1 || + d->nr_ue_rar_slot == -1 || d->nr_ue_rar_data == -1) goto error; + #undef G return; error: @@ -672,8 +850,9 @@ int main(int n, char **v) event_handler *h; int in; int i; - int ul_id, dl_id, mib_id, preamble_id, rar_id; + int ul_id, dl_id, mib_id, preamble_id, ue_preamble_id, rar_id; int nr_ul_id, nr_dl_id, nr_dl_retx_id, nr_mib_id, nr_rar_id; + int nr_ue_mib_id, nr_ue_ul_id, nr_ue_dl_id, nr_ue_rar_id; int sr_id; ev_data d; char *ip = DEFAULT_IP; @@ -748,6 +927,7 @@ int main(int n, char **v) on_off(database, "ENB_MAC_UE_DL_PDU_WITH_DATA", is_on, 1); on_off(database, "ENB_PHY_MIB", is_on, 1); on_off(database, "ENB_PHY_INITIATE_RA_PROCEDURE", is_on, 1); + on_off(database, "UE_PHY_INITIATE_RA_PROCEDURE", is_on, 1); on_off(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA", is_on, 1); on_off(database, "ENB_MAC_SCHEDULING_REQUEST", is_on, 1); @@ -756,6 +936,10 @@ int main(int n, char **v) on_off(database, "GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA", is_on, 1); on_off(database, "GNB_PHY_MIB", is_on, 1); on_off(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA", is_on, 1); + on_off(database, "NRUE_PHY_MIB", is_on, 1); + on_off(database, "NRUE_MAC_UL_PDU_WITH_DATA", is_on, 1); + on_off(database, "NRUE_MAC_DL_PDU_WITH_DATA", is_on, 1); + on_off(database, "NRUE_MAC_DL_RAR_PDU_WITH_DATA", is_on, 1); /* activate selected traces */ if (socket_send(in, &mt, 1) == -1 || @@ -772,6 +956,7 @@ int main(int n, char **v) dl_id = event_id_from_name(database, "ENB_MAC_UE_DL_PDU_WITH_DATA"); mib_id = event_id_from_name(database, "ENB_PHY_MIB"); preamble_id = event_id_from_name(database, "ENB_PHY_INITIATE_RA_PROCEDURE"); + ue_preamble_id = event_id_from_name(database, "UE_PHY_INITIATE_RA_PROCEDURE"); rar_id = event_id_from_name(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA"); sr_id = event_id_from_name(database, "ENB_MAC_SCHEDULING_REQUEST"); @@ -780,14 +965,20 @@ int main(int n, char **v) nr_dl_retx_id = event_id_from_name(database, "GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA"); nr_mib_id = event_id_from_name(database, "GNB_PHY_MIB"); nr_rar_id = event_id_from_name(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA"); + nr_ue_mib_id = event_id_from_name(database, "NRUE_PHY_MIB"); + nr_ue_ul_id = event_id_from_name(database, "NRUE_MAC_UL_PDU_WITH_DATA"); + nr_ue_dl_id = event_id_from_name(database, "NRUE_MAC_DL_PDU_WITH_DATA"); + nr_ue_rar_id = event_id_from_name(database, "NRUE_MAC_DL_RAR_PDU_WITH_DATA"); - setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id, sr_id, - nr_ul_id, nr_dl_id, nr_dl_retx_id, nr_mib_id, nr_rar_id); + setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, ue_preamble_id, + rar_id, sr_id, nr_ul_id, nr_dl_id, nr_dl_retx_id, nr_mib_id, + nr_rar_id, nr_ue_mib_id, nr_ue_ul_id, nr_ue_dl_id, nr_ue_rar_id); register_handler_function(h, ul_id, ul, &d); register_handler_function(h, dl_id, dl, &d); register_handler_function(h, mib_id, mib, &d); register_handler_function(h, preamble_id, preamble, &d); + register_handler_function(h, ue_preamble_id, ue_preamble, &d); register_handler_function(h, rar_id, rar, &d); register_handler_function(h, sr_id, sr, &d); @@ -796,6 +987,10 @@ int main(int n, char **v) register_handler_function(h, nr_dl_retx_id, nr_dl_retx, &d); register_handler_function(h, nr_mib_id, nr_mib, &d); register_handler_function(h, nr_rar_id, nr_rar, &d); + register_handler_function(h, nr_ue_mib_id, nr_ue_mib, &d); + register_handler_function(h, nr_ue_ul_id, nr_ue_ul, &d); + register_handler_function(h, nr_ue_dl_id, nr_ue_dl, &d); + register_handler_function(h, nr_ue_rar_id, nr_ue_rar, &d); d.socket = socket(AF_INET, SOCK_DGRAM, 0); @@ -817,11 +1012,15 @@ int main(int n, char **v) if (e.type == -1) break; - if (!(e.type == ul_id || e.type == dl_id || e.type == mib_id || - e.type == preamble_id || e.type == rar_id || e.type == sr_id || + if (!(e.type == ul_id || e.type == dl_id || + e.type == mib_id || + e.type == preamble_id || e.type == ue_preamble_id || + e.type == rar_id || e.type == sr_id || e.type == nr_ul_id || e.type == nr_dl_id || e.type == nr_dl_retx_id || e.type == nr_mib_id || - e.type == nr_rar_id)) continue; + e.type == nr_rar_id || e.type == nr_ue_mib_id || + e.type == nr_ue_ul_id || e.type == nr_ue_dl_id || + e.type == nr_ue_rar_id)) continue; handle_event(h, e); } diff --git a/common/utils/actor/actor.h b/common/utils/actor/actor.h index 753ba8d00a..474554c667 100644 --- a/common/utils/actor/actor.h +++ b/common/utils/actor/actor.h @@ -21,7 +21,7 @@ #ifndef ACTOR_H #define ACTOR_H -#include "thread-pool.h" +#include "notified_fifo.h" #define INIT_ACTOR(ptr, name, core_affinity) init_actor((Actor_t *)ptr, name, core_affinity); diff --git a/common/utils/load_module_shlib.c b/common/utils/load_module_shlib.c index 04d3080b5b..825012ce6a 100644 --- a/common/utils/load_module_shlib.c +++ b/common/utils/load_module_shlib.c @@ -43,6 +43,8 @@ #include "common/config/config_userapi.h" #include "load_module_shlib.h" +loader_data_t loader_data; + void loader_init(void) { paramdef_t LoaderParams[] = LOADER_PARAMS_DESC; diff --git a/common/utils/load_module_shlib.h b/common/utils/load_module_shlib.h index 1609ef9ec5..ac99778474 100644 --- a/common/utils/load_module_shlib.h +++ b/common/utils/load_module_shlib.h @@ -32,9 +32,6 @@ #ifndef LOAD_SHLIB_H #define LOAD_SHLIB_H - - - typedef struct { char *fname; int (*fptr)(void); @@ -68,11 +65,10 @@ typedef int(*checkverfunc_t)(char * mainexec_version, char ** shlib_version); /* the function array when calling load_module_shlib (farray param NULL) */ typedef int(*getfarrayfunc_t)(loader_shlibfunc_t **funcarray); -#ifdef LOAD_MODULE_SHLIB_MAIN #define LOADER_CONFIG_PREFIX "loader" #define DEFAULT_PATH "" #define DEFAULT_MAXSHLIBS 10 -loader_data_t loader_data; +extern loader_data_t loader_data; /*----------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* LOADER parameters */ @@ -85,13 +81,8 @@ loader_data_t loader_data; } // clang-format on -/*-------------------------------------------------------------------------------------------------------------*/ -#else /* LOAD_MODULE_SHLIB_MAIN */ - -extern int load_module_version_shlib(char *modname, char *version, loader_shlibfunc_t *farray, int numf, void *initfunc_arg); -extern void * get_shlibmodule_fptr(char *modname, char *fname); -extern loader_data_t loader_data; -#endif /* LOAD_MODULE_SHLIB_MAIN */ +int load_module_version_shlib(char *modname, char *version, loader_shlibfunc_t *farray, int numf, void *initfunc_arg); +void *get_shlibmodule_fptr(char *modname, char *fname); #define load_module_shlib(M, F, N, I) load_module_version_shlib(M, NULL, F, N, I) void loader_reset(); #endif diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index b59de2e0fc..faf510712b 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -434,7 +434,7 @@ typedef struct timer_elm_s { void itti_send_terminate_message(task_id_t task_id) { } - sem_t itti_sem_block; + static sem_t itti_sem_block; void itti_wait_tasks_unblock() { int rc = sem_post(&itti_sem_block); diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c index 9e708efc38..3da25380dd 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -53,7 +53,6 @@ #include #include "common/utils/load_module_shlib.h" #include "common/config/config_userapi.h" -#include "common/utils/threadPool/thread-pool.h" #include "executables/softmodem-common.h" #include #include "common/oai_version.h" diff --git a/common/utils/threadPool/CMakeLists.txt b/common/utils/threadPool/CMakeLists.txt index eb48e39a94..8e27a6b7f6 100644 --- a/common/utils/threadPool/CMakeLists.txt +++ b/common/utils/threadPool/CMakeLists.txt @@ -1,6 +1,6 @@ if (ENABLE_TESTS) add_subdirectory(test) endif() -add_library(thread-pool thread-pool.c) +add_library(thread-pool thread-pool.c task_ans.c) target_link_libraries(thread-pool PRIVATE utils) target_include_directories(thread-pool PUBLIC .) diff --git a/common/utils/threadPool/bounded_notified_fifo.h b/common/utils/threadPool/bounded_notified_fifo.h new file mode 100644 index 0000000000..db9f4f6153 --- /dev/null +++ b/common/utils/threadPool/bounded_notified_fifo.h @@ -0,0 +1,245 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef BOUNDED_NOTIFIED_FIFO_H +#define BOUNDED_NOTIFIED_FIFO_H + +#include "assertions.h" +#include +#include +#include "task.h" +#include +#include "pthread_utils.h" + +// For working correctly, maintain the default elements to a 2^N e.g., 2^5=32 +#define DEFAULT_ELM 256 + +typedef struct seq_ring_buf_s { + task_t* array; + size_t cap; + uint32_t head; + uint32_t tail; + _Atomic uint64_t sz; +} seq_ring_task_t; + + +static size_t size_seq_ring_task(seq_ring_task_t* r) +{ + DevAssert(r != NULL); + + return r->head - r->tail; +} + +static uint32_t mask(uint32_t cap, uint32_t val) +{ + return val & (cap - 1); +} + +static bool full(seq_ring_task_t* r) +{ + return size_seq_ring_task(r) == r->cap - 1; +} + +static void enlarge_buffer(seq_ring_task_t* r) +{ + DevAssert(r != NULL); + DevAssert(full(r)); + + const uint32_t factor = 2; + task_t* tmp_buffer = calloc(r->cap * factor, sizeof(task_t)); + DevAssert(tmp_buffer != NULL); + + const uint32_t head_pos = mask(r->cap, r->head); + const uint32_t tail_pos = mask(r->cap, r->tail); + + if (head_pos > tail_pos) { + memcpy(tmp_buffer, r->array + tail_pos, (head_pos - tail_pos) * sizeof(task_t)); + } else { + memcpy(tmp_buffer, r->array + tail_pos, (r->cap - tail_pos) * sizeof(task_t)); + memcpy(tmp_buffer + (r->cap - tail_pos), r->array, head_pos * sizeof(task_t)); + } + r->cap *= factor; + free(r->array); + r->array = tmp_buffer; + r->tail = 0; + r->head = r->cap / 2 - 1; +} + +static void init_seq_ring_task(seq_ring_task_t* r) +{ + DevAssert(r != NULL); + task_t* tmp_buffer = calloc(DEFAULT_ELM, sizeof(task_t)); + DevAssert(tmp_buffer != NULL); + seq_ring_task_t tmp = {.array = tmp_buffer, .head = 0, .tail = 0, .cap = DEFAULT_ELM}; + memcpy(r, &tmp, sizeof(seq_ring_task_t)); + r->sz = 0; +} + +static void free_seq_ring_task(seq_ring_task_t* r) +{ + DevAssert(r != NULL); + free(r->array); +} + +static void push_back_seq_ring_task(seq_ring_task_t* r, task_t t) +{ + DevAssert(r != NULL); + + if (full(r)) + enlarge_buffer(r); + + const uint32_t pos = mask(r->cap, r->head); + r->array[pos] = t; + r->head += 1; + r->sz += 1; +} + +static task_t pop_seq_ring_task(seq_ring_task_t* r) +{ + DevAssert(r != NULL); + DevAssert(size_seq_ring_task(r) > 0); + + const uint32_t pos = mask(r->cap, r->tail); + task_t t = r->array[pos]; + r->tail += 1; + r->sz -= 1; + return t; +} + +#undef DEFAULT_ELM + +typedef struct { + pthread_mutex_t mtx; + pthread_cond_t cv; + seq_ring_task_t r; + size_t idx; +} not_q_t; + +typedef struct { + task_t t; + bool success; +} ret_try_t; + +static void init_not_q(not_q_t* q, size_t idx) +{ + DevAssert(q != NULL); + + q->idx = idx; + + init_seq_ring_task(&q->r); + + mutexinit(q->mtx); + condinit(q->cv); +} + +static void free_not_q(not_q_t* q) +{ + DevAssert(q != NULL); + + free_seq_ring_task(&q->r); + + mutexdestroy(q->mtx); + conddestroy(q->cv); +} + +static bool try_push_not_q(not_q_t* q, task_t t) +{ + DevAssert(q != NULL); + + + if (mutextrylock(q->mtx) != 0) + return false; + + push_back_seq_ring_task(&q->r, t); + + const size_t sz = size_seq_ring_task(&q->r); + DevAssert(sz > 0); + + mutexunlock(q->mtx); + + condsignal(q->cv); + + return true; +} + +static void push_not_q(not_q_t* q, task_t t) +{ + DevAssert(q != NULL); + DevAssert(t.func != NULL); + + mutexlock(q->mtx); + + push_back_seq_ring_task(&q->r, t); + + DevAssert(size_seq_ring_task(&q->r) > 0); + + mutexunlock(q->mtx); + + condsignal(q->cv); +} + +static ret_try_t try_pop_not_q(not_q_t* q) +{ + DevAssert(q != NULL); + + ret_try_t ret = {.success = false}; + + int rc = mutextrylock(q->mtx); + DevAssert(rc == 0 || rc == EBUSY); + + if (rc == EBUSY) + return ret; + + size_t sz = size_seq_ring_task(&q->r); + if (sz == 0) { + mutexunlock(q->mtx); + + return ret; + } + + DevAssert(sz > 0); + ret.t = pop_seq_ring_task(&q->r); + + mutexunlock(q->mtx); + ret.success = true; + + return ret; +} + +static bool pop_not_q(not_q_t* q, ret_try_t* out) +{ + DevAssert(q != NULL); + DevAssert(out != NULL); + + mutexlock(q->mtx); + + while (size_seq_ring_task(&q->r) == 0) { + condwait(q->cv, q->mtx); + } + + out->t = pop_seq_ring_task(&q->r); + + mutexunlock(q->mtx); + + return true; +} + +#endif diff --git a/common/utils/threadPool/notified_fifo.h b/common/utils/threadPool/notified_fifo.h new file mode 100644 index 0000000000..c845c40b56 --- /dev/null +++ b/common/utils/threadPool/notified_fifo.h @@ -0,0 +1,223 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef NOTIFIED_FIFO_H +#define NOTIFIED_FIFO_H +#include "pthread_utils.h" +#include +#include +#include "time_meas.h" +#include +#include +#include "assertions.h" + +/// @brief Element on the notifiedFifo_t +/// next: internal FIFO chain, do not set it +/// key: a long int that the client can use to identify a job or a group of messages +/// ResponseFifo: if the client defines a response FIFO, the job will be posted back after processing +/// processingFunc: any function (of type void processingFunc(void *)) that a worker will process +/// msgData: the data passed to `processingFunc`. It can be added automatically, or you can set it to a buffer you are managing +/// malloced: a boolean that enables internal free in the case of no return FIFO or abort feature +typedef struct notifiedFIFO_elt_s { + struct notifiedFIFO_elt_s *next; + uint64_t key; // To filter out elements + struct notifiedFIFO_s *reponseFifo; + void (*processingFunc)(void *); + bool malloced; + oai_cputime_t creationTime; + oai_cputime_t startProcessingTime; + oai_cputime_t endProcessingTime; + oai_cputime_t returnTime; + // use alignas(32) to align msgData to 32b + // user data behind it will be aligned to 32b as well + // important! this needs to be the last member in the struct + alignas(32) void *msgData; +} notifiedFIFO_elt_t; + +typedef struct notifiedFIFO_s { + notifiedFIFO_elt_t *outF; + notifiedFIFO_elt_t *inF; + pthread_mutex_t lockF; + pthread_cond_t notifF; + bool abortFIFO; // if set, the FIFO always returns NULL -> abort condition +} notifiedFIFO_t; + +/// @brief Creates a new job. +/// @param size The data part of the job will have this size +/// @param key the job can be identified +/// @param reponseFifo response fifo +/// @param processingFunc function to call +/// @return new notifiedFIFO_elt_t element with extra memory allocated at the end equal to size. +static inline notifiedFIFO_elt_t *newNotifiedFIFO_elt(int size, + uint64_t key, + notifiedFIFO_t *reponseFifo, + void (*processingFunc)(void *)) +{ + notifiedFIFO_elt_t *ret = (notifiedFIFO_elt_t *)memalign(32, sizeof(notifiedFIFO_elt_t) + size); + AssertFatal(NULL != ret, "out of memory\n"); + ret->next = NULL; + ret->key = key; + ret->reponseFifo = reponseFifo; + ret->processingFunc = processingFunc; + // We set user data piece aligend 32 bytes to be able to process it with SIMD + // msgData is aligned to 32bytes, so everything after will be as well + ret->msgData = ((uint8_t *)ret) + sizeof(notifiedFIFO_elt_t); + ret->malloced = true; + return ret; +} + +/// @brief Get pointer to the data carried by notifiedFIFO_elt_t +/// @param elt +/// @return void pointer to the data allocated with the message +static inline void *NotifiedFifoData(notifiedFIFO_elt_t *elt) +{ + return elt->msgData; +} + +/// @brief Delete a notifiedFIFO_elt_t if its allocated +/// @param elt +static inline void delNotifiedFIFO_elt(notifiedFIFO_elt_t *elt) +{ + if (elt->malloced) { + elt->malloced = false; + free(elt); + } +} + +static inline void initNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf) +{ + nf->inF = NULL; + nf->outF = NULL; + nf->abortFIFO = false; +} +static inline void initNotifiedFIFO(notifiedFIFO_t *nf) +{ + mutexinit(nf->lockF); + condinit(nf->notifF); + initNotifiedFIFO_nothreadSafe(nf); + // No delete function: the creator has only to free the memory +} + +static inline void pushNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) +{ + msg->next = NULL; + + if (nf->outF == NULL) + nf->outF = msg; + + if (nf->inF != NULL) + nf->inF->next = msg; + + nf->inF = msg; +} + +static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) +{ + mutexlock(nf->lockF); + if (!nf->abortFIFO) { + pushNotifiedFIFO_nothreadSafe(nf, msg); + condsignal(nf->notifF); + } + mutexunlock(nf->lockF); +} + +static inline notifiedFIFO_elt_t *pullNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf) +{ + if (nf->outF == NULL) + return NULL; + if (nf->abortFIFO) + return NULL; + + notifiedFIFO_elt_t *ret = nf->outF; + + AssertFatal(nf->outF != nf->outF->next, "Circular list in thread pool: push several times the same buffer is forbidden\n"); + + nf->outF = nf->outF->next; + + if (nf->outF == NULL) + nf->inF = NULL; + + return ret; +} + +static inline notifiedFIFO_elt_t *pullNotifiedFIFO(notifiedFIFO_t *nf) +{ + mutexlock(nf->lockF); + notifiedFIFO_elt_t *ret = NULL; + + while ((ret = pullNotifiedFIFO_nothreadSafe(nf)) == NULL && !nf->abortFIFO) + condwait(nf->notifF, nf->lockF); + + mutexunlock(nf->lockF); + return ret; +} + +static inline notifiedFIFO_elt_t *pollNotifiedFIFO(notifiedFIFO_t *nf) +{ + int tmp = mutextrylock(nf->lockF); + + if (tmp != 0) + return NULL; + + if (nf->abortFIFO) { + mutexunlock(nf->lockF); + return NULL; + } + + notifiedFIFO_elt_t *ret = pullNotifiedFIFO_nothreadSafe(nf); + mutexunlock(nf->lockF); + return ret; +} + +static inline time_stats_t exec_time_stats_NotifiedFIFO(const notifiedFIFO_elt_t *elt) +{ + time_stats_t ts = {0}; + if (elt->startProcessingTime == 0 && elt->endProcessingTime == 0) + return ts; /* no measurements done */ + ts.in = elt->startProcessingTime; + ts.diff = elt->endProcessingTime - ts.in; + ts.p_time = ts.diff; + ts.diff_square = ts.diff * ts.diff; + ts.max = ts.diff; + ts.trials = 1; + return ts; +} + +// This functions aborts all messages in the queue, and marks the queue as +// "aborted", such that every call to it will return NULL +static inline void abortNotifiedFIFO(notifiedFIFO_t *nf) +{ + mutexlock(nf->lockF); + nf->abortFIFO = true; + notifiedFIFO_elt_t **elt = &nf->outF; + while (*elt != NULL) { + notifiedFIFO_elt_t *p = *elt; + *elt = (*elt)->next; + delNotifiedFIFO_elt(p); + } + + if (nf->outF == NULL) + nf->inF = NULL; + condbroadcast(nf->notifF); + mutexunlock(nf->lockF); +} + +#endif diff --git a/common/utils/threadPool/pthread_utils.h b/common/utils/threadPool/pthread_utils.h new file mode 100644 index 0000000000..119fc3aeab --- /dev/null +++ b/common/utils/threadPool/pthread_utils.h @@ -0,0 +1,45 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef PTHREAD_UTILS_H +#define PTHREAD_UTILS_H + +#include +#define mutexinit(mutex) {int ret=pthread_mutex_init(&mutex,NULL); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define condinit(signal) {int ret=pthread_cond_init(&signal,NULL); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define mutexlock(mutex) {int ret=pthread_mutex_lock(&mutex); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define mutextrylock(mutex) pthread_mutex_trylock(&mutex) +#define mutexunlock(mutex) {int ret=pthread_mutex_unlock(&mutex); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define condwait(condition, mutex) {int ret=pthread_cond_wait(&condition, &mutex); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define condbroadcast(signal) {int ret=pthread_cond_broadcast(&signal); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define condsignal(signal) {int ret=pthread_cond_signal(&signal); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define mutexdestroy(mutex) { int ret = pthread_mutex_destroy(&mutex);\ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define conddestroy(condition) { int ret = pthread_cond_destroy(&condition);\ + AssertFatal(ret==0,"ret=%d\n",ret);} +#endif diff --git a/openair3/NAS/COMMON/UTIL/TLVEncoder.c b/common/utils/threadPool/task.h similarity index 66% rename from openair3/NAS/COMMON/UTIL/TLVEncoder.c rename to common/utils/threadPool/task.h index 0316c353fa..2b380bc60f 100644 --- a/openair3/NAS/COMMON/UTIL/TLVEncoder.c +++ b/common/utils/threadPool/task.h @@ -19,29 +19,12 @@ * contact@openairinterface.org */ -#include -#include -#include +#ifndef TASK_WORK_STEALING_THREAD_POOL_H +#define TASK_WORK_STEALING_THREAD_POOL_H -#include "TLVEncoder.h" - -int errorCodeEncoder = 0; - -const char *const errorCodeStringEncoder[] = { - "No error", - "Buffer NULL", - "Buffer too short", - "Octet string too long for IEI", - "Wrong message type", - "Protocol not supported", -}; - -void tlv_encode_perror(void) -{ - if (errorCodeEncoder >= 0) - // No error or TLV_DECODE_ERR_OK - return; - - printf("error: (%d, %s)\n", errorCodeEncoder, errorCodeStringEncoder[errorCodeEncoder * -1]); -} +typedef struct { + void* args; + void (*func)(void* args); +} task_t; +#endif diff --git a/common/utils/threadPool/task_ans.c b/common/utils/threadPool/task_ans.c new file mode 100644 index 0000000000..5a1a2c8764 --- /dev/null +++ b/common/utils/threadPool/task_ans.c @@ -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.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "task_ans.h" +#include "assertions.h" +#include +#include +#include +#include +#include + +void completed_task_ans(task_ans_t* task) +{ + DevAssert(task != NULL); + + if (atomic_load_explicit(&task->status, memory_order_acquire) != 0) + AssertFatal(0, "Task already finished?"); + + atomic_store_explicit(&task->status, 1, memory_order_release); +} + +void join_task_ans(task_ans_t* arr, size_t len) +{ + DevAssert(len < INT_MAX); + DevAssert(arr != NULL); + + // Spin lock inspired by: + // The Art of Writing Efficient Programs: + // An advanced programmer's guide to efficient hardware utilization + // and compiler optimizations using C++ examples + const struct timespec ns = {0, 1}; + uint64_t i = 0; + int j = len - 1; + for (; j != -1; i++) { + for (; j != -1; --j) { + int const task_completed = 1; + if (atomic_load_explicit(&arr[j].status, memory_order_acquire) != task_completed) + break; + } + if (i % 8 == 0) { + nanosleep(&ns, NULL); + } + } +} diff --git a/common/utils/threadPool/task_ans.h b/common/utils/threadPool/task_ans.h new file mode 100644 index 0000000000..4d1203555d --- /dev/null +++ b/common/utils/threadPool/task_ans.h @@ -0,0 +1,74 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef TASK_ANSWER_THREAD_POOL_H +#define TASK_ANSWER_THREAD_POOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __cplusplus +#include +#include +#else +#include +#define _Atomic(X) std::atomic +#define _Alignas(X) alignas(X) +#endif + +#include +#include + +#if defined(__i386__) || defined(__x86_64__) +#define LEVEL1_DCACHE_LINESIZE 64 +#elif defined(__aarch64__) +// This is not always true for ARM +// in linux, you can obtain the size at runtime using sysconf (_SC_LEVEL1_DCACHE_LINESIZE) +// or from the bash with the command $ getconf LEVEL1_DCACHE_LINESIZE +// in c++ using std::hardware_destructive_interference_size +#define LEVEL1_DCACHE_LINESIZE 64 +#else +#error Unknown CPU architecture +#endif + +typedef struct { + // Avoid false sharing + _Alignas(LEVEL1_DCACHE_LINESIZE) _Atomic(int) status; +} task_ans_t; + +typedef struct { + uint8_t* buf; + size_t len; + size_t cap; // capacity + task_ans_t* ans; +} thread_info_tm_t; + + +void join_task_ans(task_ans_t* arr, size_t len); + +void completed_task_ans(task_ans_t* task); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/common/utils/threadPool/test/test_thread-pool.c b/common/utils/threadPool/test/test_thread-pool.c index 1af3dc1020..f1e3322ac9 100644 --- a/common/utils/threadPool/test/test_thread-pool.c +++ b/common/utils/threadPool/test/test_thread-pool.c @@ -27,8 +27,10 @@ #include #include #include -#include +#include "thread-pool.h" #include "log.h" +#include "task_ans.h" +#include "notified_fifo.h" void displayList(notifiedFIFO_t *nf) { @@ -47,6 +49,7 @@ struct testData { int id; int sleepTime; char txt[50]; + task_ans_t* task_ans; }; void processing(void *arg) @@ -57,6 +60,7 @@ void processing(void *arg) in->sleepTime = rand() % 1000; usleep(in->sleepTime); // printf("done: %d, %s, in thr %ld\n",in->id, in->txt,pthread_self() ); + completed_task_ans(in->task_ans); } int main() @@ -102,8 +106,6 @@ int main() tpool_t pool; char params[] = "1,2,3,4,5"; initTpool(params, &pool, true); - notifiedFIFO_t worker_back; - initNotifiedFIFO(&worker_back); //sleep(1); int cumulProcessTime = 0; @@ -112,21 +114,22 @@ int main() int nb_jobs = 4; for (int i = 0; i < 1000; i++) { int parall = nb_jobs; + task_ans_t task_ans[parall]; + memset(task_ans, 0, sizeof(task_ans)); + struct testData test_data[parall]; + memset(test_data, 0, sizeof(test_data)); for (int j = 0; j < parall; j++) { - notifiedFIFO_elt_t *work = newNotifiedFIFO_elt(sizeof(struct testData), i, &worker_back, processing); - struct testData *x = (struct testData *)NotifiedFifoData(work); + task_t task = {.args = &test_data[j], .func = processing}; + struct testData *x = (struct testData *)task.args; x->id = i; - pushTpool(&pool, work); + x->task_ans = &task_ans[j]; + pushTpool(&pool, task); } + join_task_ans(task_ans, parall); int sleepmax = 0; - while (parall) { - tmp = pullTpool(&worker_back, &pool); - if (tmp) { - parall--; - struct testData *dd = NotifiedFifoData(tmp); - if (dd->sleepTime > sleepmax) - sleepmax = dd->sleepTime; - delNotifiedFIFO_elt(tmp); + for (int j = 0; j < parall; j++) { + if (test_data[j].sleepTime > sleepmax) { + sleepmax = test_data[j].sleepTime; } } cumulProcessTime += sleepmax; diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index 5b22f2895d..2a31602e6e 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -1,163 +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.1 (the "License"); you may not use this file -* except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.openairinterface.org/?page_id=698 -* -* Author and copyright: Laurent Thomas, open-cells.com -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*------------------------------------------------------------------------------- -* For more information about the OpenAirInterface (OAI) Software Alliance: -* contact@openairinterface.org -*/ - + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ #define _GNU_SOURCE #include #include #include #include -#include +#include "thread-pool.h" +#include "bounded_notified_fifo.h" +#include +typedef struct { + tpool_t* tpool; + int idx; +} task_thread_args_t; -static inline notifiedFIFO_elt_t *pullNotifiedFifoRemember( notifiedFIFO_t *nf, struct one_thread *thr) { - mutexlock(nf->lockF); - - while(!nf->outF && !thr->terminate) - condwait(nf->notifF, nf->lockF); - - if (thr->terminate) { - mutexunlock(nf->lockF); - return NULL; +void pushTpool(tpool_t* tpool, task_t task) +{ + DevAssert(tpool != NULL); + if (tpool->len_thr == 0) { + task.func(task.args); + return; } - notifiedFIFO_elt_t *ret=nf->outF; - nf->outF=nf->outF->next; + size_t const index = tpool->index++; + size_t const len_thr = tpool->len_thr; - if (nf->outF==NULL) - nf->inF=NULL; + not_q_t* q_arr = (not_q_t*)tpool->q_arr; - // For abort feature - thr->runningOnKey=ret->key; - thr->dropJob = false; - mutexunlock(nf->lockF); - return ret; + for (size_t i = 0; i < len_thr; ++i) { + if (try_push_not_q(&q_arr[(i + index) % len_thr], task)) { + return; + } + } + + push_not_q(&q_arr[index % len_thr], task); } -void *one_thread(void *arg) { - struct one_thread *myThread=(struct one_thread *) arg; - struct thread_pool *tp=myThread->pool; +static void* worker_thread(void* arg) +{ + DevAssert(arg != NULL); - // Infinite loop to process requests - do { - notifiedFIFO_elt_t *elt=pullNotifiedFifoRemember(&tp->incomingFifo, myThread); - if (elt == NULL) { - AssertFatal(myThread->terminate, "pullNotifiedFifoRemember() returned NULL although thread not aborted\n"); + task_thread_args_t* args = (task_thread_args_t*)arg; + int const idx = args->idx; + tpool_t* tpool = args->tpool; + + uint32_t const len = tpool->len_thr; + uint32_t const num_it = 2 * (tpool->len_thr + idx); + + not_q_t* q_arr = (not_q_t*)tpool->q_arr; + + init_not_q(&q_arr[idx], idx); + // Synchronize all threads + pthread_barrier_wait(&tpool->barrier); + + for (;;) { + ret_try_t ret = {.success = false}; + + for (uint32_t i = idx; i < num_it; ++i) { + ret = try_pop_not_q(&q_arr[i % len]); + if (ret.success == true) + break; + } + + if (ret.success == false) { + if (pop_not_q(&q_arr[idx], &ret) == false) + break; + } + + if (ret.t.func == NULL && ret.t.args == NULL) { + pushTpool(tpool, (task_t){.args = NULL, .func = NULL}); break; } + ret.t.func(ret.t.args); + } - if (tp->measurePerf) elt->startProcessingTime=rdtsc_oai(); - - elt->processingFunc(NotifiedFifoData(elt)); - - if (tp->measurePerf) elt->endProcessingTime=rdtsc_oai(); - - if (elt->reponseFifo) { - // Check if the job is still alive, else it has been aborted - mutexlock(tp->incomingFifo.lockF); - - if (myThread->dropJob) - delNotifiedFIFO_elt(elt); - else - pushNotifiedFIFO(elt->reponseFifo, elt); - myThread->runningOnKey=-1; - mutexunlock(tp->incomingFifo.lockF); - } - else - delNotifiedFIFO_elt(elt); - } while (!myThread->terminate); + free(args); return NULL; } -void initNamedTpool(char *params,tpool_t *pool, bool performanceMeas, char *name) { - memset(pool,0,sizeof(*pool)); - char *measr=getenv("OAI_THREADPOOLMEASUREMENTS"); - pool->measurePerf=performanceMeas; - // force measurement if the output is defined - pool->measurePerf |= measr!=NULL; +void initNamedTpool(char* params, tpool_t* tpool, bool performanceMeas, char* name) +{ + (void)performanceMeas; - if (measr) { - mkfifo(measr,0666); - AssertFatal(-1 != (pool->dummyKeepReadingTraceFd= - open(measr, O_RDONLY| O_NONBLOCK)),""); - AssertFatal(-1 != (pool->traceFd= - open(measr, O_WRONLY|O_APPEND|O_NOATIME|O_NONBLOCK)),""); - } else - pool->traceFd=-1; + DevAssert(tpool != NULL); + memset(tpool, 0, sizeof(*tpool)); - pool->activated=true; - initNotifiedFIFO(&pool->incomingFifo); - char *saveptr, * curptr; - char *parms_cpy=strdup(params); - pool->nbThreads=0; - curptr=strtok_r(parms_cpy,",",&saveptr); - struct one_thread * ptr; - char *tname = (name == NULL ? "Tpool" : name); - while ( curptr!=NULL ) { - int c=toupper(curptr[0]); + char* tname = (name == NULL ? "Tpool" : name); + char *saveptr, *curptr; + char* parms_cpy = strdup(params); + curptr = strtok_r(parms_cpy, ",", &saveptr); + int core_id[128] = {0}; + int num_workers = 0; + while (curptr != NULL) { + int c = toupper(curptr[0]); switch (c) { - case 'N': - pool->activated=false; break; default: - ptr=pool->allthreads; - pool->allthreads=(struct one_thread *)malloc(sizeof(struct one_thread)); - pool->allthreads->next=ptr; - pool->allthreads->coreID=atoi(curptr); - pool->allthreads->id=pool->nbThreads; - pool->allthreads->pool=pool; - pool->allthreads->dropJob = false; - pool->allthreads->terminate = false; - //Configure the thread scheduler policy for Linux - // set the thread name for debugging - sprintf(pool->allthreads->name,"%s%d_%d",tname,pool->nbThreads,pool->allthreads->coreID); - // we set the maximum priority for thread pool threads (which is close - // but not equal to Linux maximum). See also the corresponding commit - // message; initially introduced for O-RAN 7.2 fronthaul split - threadCreate(&pool->allthreads->threadID, one_thread, (void *)pool->allthreads, - pool->allthreads->name, pool->allthreads->coreID, OAI_PRIORITY_RT_MAX); - pool->nbThreads++; + core_id[num_workers++] = atoi(curptr); } - curptr=strtok_r(NULL,",",&saveptr); + curptr = strtok_r(NULL, ",", &saveptr); } free(parms_cpy); - if (pool->activated && pool->nbThreads==0) { - printf("No servers created in the thread pool, exit\n"); - exit(1); + + if (num_workers) { + tpool->q_arr = calloc(num_workers, sizeof(not_q_t)); + AssertFatal(tpool->q_arr != NULL, "Memory exhausted"); + + tpool->t_arr = calloc(num_workers, sizeof(pthread_t)); + AssertFatal(tpool->t_arr != NULL, "Memory exhausted"); } + tpool->len_thr = num_workers; + + tpool->index = 0; + + const pthread_barrierattr_t* barrier_attr = NULL; + int rc = pthread_barrier_init(&tpool->barrier, barrier_attr, num_workers + 1); + DevAssert(rc == 0); + + for (size_t i = 0; i < num_workers; ++i) { + task_thread_args_t* args = malloc(sizeof(task_thread_args_t)); + AssertFatal(args != NULL, "Memory exhausted"); + args->idx = i; + args->tpool = tpool; + char name[64]; + sprintf(name, "%s%ld_%d", tname, i, core_id[i]); + threadCreate(&tpool->t_arr[i], worker_thread, args, name, core_id[i], OAI_PRIORITY_RT_MAX); + } + + // Syncronize thread pool threads. All the threads started + pthread_barrier_wait(&tpool->barrier); } -void initFloatingCoresTpool(int nbThreads,tpool_t *pool, bool performanceMeas, char *name) { +void initFloatingCoresTpool(int nbThreads, tpool_t* pool, bool performanceMeas, char* name) +{ char threads[1024] = "n"; if (nbThreads) { - strcpy(threads,"-1"); - for (int i=1; i < nbThreads; i++) - strncat(threads,",-1", sizeof(threads)-1); + strcpy(threads, "-1"); + for (int i = 1; i < nbThreads; i++) + strncat(threads, ",-1", sizeof(threads) - 1); } - threads[sizeof(threads)-1]=0; + threads[sizeof(threads) - 1] = 0; initNamedTpool(threads, pool, performanceMeas, name); } + + +void abortTpool(tpool_t* tpool) +{ + if (tpool->len_thr > 0) { + not_q_t* q_arr = (not_q_t*)tpool->q_arr; + + pushTpool(tpool, (task_t){.args = NULL, .func = NULL}); + + for (uint32_t i = 0; i < tpool->len_thr; ++i) { + int rc = pthread_join(tpool->t_arr[i], NULL); + DevAssert(rc == 0); + } + + for (uint32_t i = 0; i < tpool->len_thr; ++i) { + free_not_q(&q_arr[i]); + } + + free(tpool->q_arr); + free(tpool->t_arr); + } + + int rc = pthread_barrier_destroy(&tpool->barrier); + DevAssert(rc == 0); +} diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index 31395d7a9b..8e5d329499 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -1,26 +1,23 @@ /* -* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The OpenAirInterface Software Alliance licenses this file to You under -* the OAI Public License, Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.openairinterface.org/?page_id=698 -* -* Author and copyright: Laurent Thomas, open-cells.com -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*------------------------------------------------------------------------------- -* For more information about the OpenAirInterface (OAI) Software Alliance: -* contact@openairinterface.org -*/ - + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ #ifndef THREAD_POOL_H #define THREAD_POOL_H @@ -35,316 +32,54 @@ #include "assertions.h" #include "common/utils/time_meas.h" #include "common/utils/system.h" +#include "task.h" +#include "pthread_utils.h" #ifdef DEBUG #define THREADINIT PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP #else #define THREADINIT PTHREAD_MUTEX_INITIALIZER #endif -#define mutexinit(mutex) {int ret=pthread_mutex_init(&mutex,NULL); \ - AssertFatal(ret==0,"ret=%d\n",ret);} -#define condinit(signal) {int ret=pthread_cond_init(&signal,NULL); \ - AssertFatal(ret==0,"ret=%d\n",ret);} -#define mutexlock(mutex) {int ret=pthread_mutex_lock(&mutex); \ - AssertFatal(ret==0,"ret=%d\n",ret);} -#define mutextrylock(mutex) pthread_mutex_trylock(&mutex) -#define mutexunlock(mutex) {int ret=pthread_mutex_unlock(&mutex); \ - AssertFatal(ret==0,"ret=%d\n",ret);} -#define condwait(condition, mutex) {int ret=pthread_cond_wait(&condition, &mutex); \ - AssertFatal(ret==0,"ret=%d\n",ret);} -#define condbroadcast(signal) {int ret=pthread_cond_broadcast(&signal); \ - AssertFatal(ret==0,"ret=%d\n",ret);} -#define condsignal(signal) {int ret=pthread_cond_signal(&signal); \ - AssertFatal(ret==0,"ret=%d\n",ret);} -#define tpool_nbthreads(tpool) (tpool.nbThreads) -typedef struct notifiedFIFO_elt_s { - struct notifiedFIFO_elt_s *next; - uint64_t key; //To filter out elements - struct notifiedFIFO_s *reponseFifo; - void (*processingFunc)(void *); - bool malloced; - oai_cputime_t creationTime; - oai_cputime_t startProcessingTime; - oai_cputime_t endProcessingTime; - oai_cputime_t returnTime; - // use alignas(32) to align msgData to 32b - // user data behind it will be aligned to 32b as well - // important! this needs to be the last member in the struct - alignas(32) void *msgData; -} notifiedFIFO_elt_t; -typedef struct notifiedFIFO_s { - notifiedFIFO_elt_t *outF; - notifiedFIFO_elt_t *inF; - pthread_mutex_t lockF; - pthread_cond_t notifF; - bool abortFIFO; // if set, the FIFO always returns NULL -> abort condition -} notifiedFIFO_t; +typedef struct { + pthread_t* t_arr; + size_t len_thr; -// You can use this allocator or use any piece of memory -static inline notifiedFIFO_elt_t *newNotifiedFIFO_elt(int size, - uint64_t key, - notifiedFIFO_t *reponseFifo, - void (*processingFunc)(void *)) { - notifiedFIFO_elt_t *ret = (notifiedFIFO_elt_t *)memalign(32, sizeof(notifiedFIFO_elt_t) + size); - AssertFatal(NULL != ret, "out of memory\n"); - ret->next=NULL; - ret->key=key; - ret->reponseFifo=reponseFifo; - ret->processingFunc=processingFunc; - // We set user data piece aligend 32 bytes to be able to process it with SIMD - // msgData is aligned to 32bytes, so everything after will be as well - ret->msgData = ((uint8_t *)ret) + sizeof(notifiedFIFO_elt_t); - ret->malloced=true; - return ret; -} + _Atomic(uint64_t) index; -static inline void *NotifiedFifoData(notifiedFIFO_elt_t *elt) { - return elt->msgData; -} + void* q_arr; -static inline void delNotifiedFIFO_elt(notifiedFIFO_elt_t *elt) { - if (elt->malloced) { - elt->malloced = false; - free(elt); - } - /* it is allowed to call delNotifiedFIFO_elt when the memory is managed by - * the caller */ -} - -static inline void initNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf) { - nf->inF=NULL; - nf->outF=NULL; - nf->abortFIFO = false; -} -static inline void initNotifiedFIFO(notifiedFIFO_t *nf) { - mutexinit(nf->lockF); - condinit (nf->notifF); - initNotifiedFIFO_nothreadSafe(nf); - // No delete function: the creator has only to free the memory -} - -static inline void pushNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) { - msg->next=NULL; - - if (nf->outF == NULL) - nf->outF = msg; - - if (nf->inF != NULL) - nf->inF->next = msg; - - nf->inF = msg; -} - -static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) { - mutexlock(nf->lockF); - if (!nf->abortFIFO) { - pushNotifiedFIFO_nothreadSafe(nf,msg); - condsignal(nf->notifF); - } - mutexunlock(nf->lockF); -} - -static inline notifiedFIFO_elt_t *pullNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf) { - if (nf->outF == NULL) - return NULL; - if (nf->abortFIFO) - return NULL; - - notifiedFIFO_elt_t *ret=nf->outF; - - AssertFatal(nf->outF != nf->outF->next,"Circular list in thread pool: push several times the same buffer is forbidden\n"); - - nf->outF=nf->outF->next; - - if (nf->outF==NULL) - nf->inF=NULL; - - return ret; -} - -static inline notifiedFIFO_elt_t *pullNotifiedFIFO(notifiedFIFO_t *nf) { - mutexlock(nf->lockF); - notifiedFIFO_elt_t *ret = NULL; - - while((ret=pullNotifiedFIFO_nothreadSafe(nf)) == NULL && !nf->abortFIFO) - condwait(nf->notifF, nf->lockF); - - mutexunlock(nf->lockF); - return ret; -} - -static inline notifiedFIFO_elt_t *pollNotifiedFIFO(notifiedFIFO_t *nf) { - int tmp=mutextrylock(nf->lockF); - - if (tmp != 0 ) - return NULL; - - if (nf->abortFIFO) { - mutexunlock(nf->lockF); - return NULL; - } - - notifiedFIFO_elt_t *ret=pullNotifiedFIFO_nothreadSafe(nf); - mutexunlock(nf->lockF); - return ret; -} - -static inline time_stats_t exec_time_stats_NotifiedFIFO(const notifiedFIFO_elt_t* elt) -{ - time_stats_t ts = {0}; - if (elt->startProcessingTime == 0 && elt->endProcessingTime == 0) - return ts; /* no measurements done */ - ts.in = elt->startProcessingTime; - ts.diff = elt->endProcessingTime - ts.in; - ts.p_time = ts.diff; - ts.diff_square = ts.diff * ts.diff; - ts.max = ts.diff; - ts.trials = 1; - return ts; -} - -// This functions aborts all messages in the queue, and marks the queue as -// "aborted", such that every call to it will return NULL -static inline void abortNotifiedFIFO(notifiedFIFO_t *nf) { - mutexlock(nf->lockF); - nf->abortFIFO = true; - notifiedFIFO_elt_t **elt = &nf->outF; - while(*elt != NULL) { - notifiedFIFO_elt_t *p = *elt; - *elt = (*elt)->next; - delNotifiedFIFO_elt(p); - } - - if (nf->outF == NULL) - nf->inF = NULL; - condbroadcast(nf->notifF); - mutexunlock(nf->lockF); -} - -struct one_thread { - pthread_t threadID; - int id; - int coreID; - char name[256]; - uint64_t runningOnKey; - bool dropJob; - bool terminate; - struct thread_pool *pool; - struct one_thread *next; -}; - -typedef struct thread_pool { - bool activated; - bool measurePerf; - int traceFd; - int dummyKeepReadingTraceFd; - uint64_t cpuCyclesMicroSec; - int nbThreads; - notifiedFIFO_t incomingFifo; - struct one_thread *allthreads; + pthread_barrier_t barrier; } tpool_t; -static inline void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) { - if (t->measurePerf) msg->creationTime=rdtsc_oai(); +/// @brief Push job to threadpool. May run task inline in case there are no worker threads +/// defined for threadpool +/// @param tpool threadpool to use +/// @param task task description +void pushTpool(tpool_t *tpool, task_t task); - if ( t->activated) - pushNotifiedFIFO(&t->incomingFifo, msg); - else { - if (t->measurePerf) - msg->startProcessingTime=rdtsc_oai(); +/// @brief Abort tpool, stop all threads and return +/// @param t +void abortTpool(tpool_t *t); - msg->processingFunc(NotifiedFifoData(msg)); - - if (t->measurePerf) - msg->endProcessingTime=rdtsc_oai(); - - if (msg->reponseFifo) - pushNotifiedFIFO(msg->reponseFifo, msg); - else - delNotifiedFIFO_elt(msg); - } -} - -static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { - notifiedFIFO_elt_t *msg= pullNotifiedFIFO(responseFifo); - if (msg == NULL) - return NULL; - AssertFatal(t->traceFd != 0, "Thread pool used while not initialized"); - if (t->measurePerf) - msg->returnTime=rdtsc_oai(); - - if (t->traceFd > 0) { - ssize_t b = write(t->traceFd, msg, sizeof(*msg)); - AssertFatal(b == sizeof(*msg), "error in write(): %d, %s\n", errno, strerror(errno)); - } - - return msg; -} - -static inline notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { - notifiedFIFO_elt_t *msg= pollNotifiedFIFO(responseFifo); - AssertFatal(t->traceFd != 0, "Thread pool used while not initialized"); - if (msg == NULL) - return NULL; - - if (t->measurePerf) - msg->returnTime=rdtsc_oai(); - - if (t->traceFd > 0) { - ssize_t b = write(t->traceFd, msg, sizeof(*msg)); - AssertFatal(b == sizeof(*msg), "error in write(): %d, %s\n", errno, strerror(errno)); - } - - return msg; -} - -static inline int abortTpool(tpool_t *t) { - int nbRemoved=0; - /* disables threading: if a message comes in now, we cannot have a race below - * as each thread will simply execute the message itself */ - t->activated = false; - notifiedFIFO_t *nf=&t->incomingFifo; - mutexlock(nf->lockF); - nf->abortFIFO = true; - notifiedFIFO_elt_t **start=&nf->outF; - - /* mark threads to abort them */ - struct one_thread *thread = t->allthreads; - while (thread != NULL) { - thread->dropJob = true; - thread->terminate = true; - nbRemoved++; - thread = thread->next; - } - - /* clear FIFOs */ - while(*start!=NULL) { - notifiedFIFO_elt_t **request=start; - *start=(*start)->next; - delNotifiedFIFO_elt(*request); - *request = NULL; - nbRemoved++; - } - - if (t->incomingFifo.outF==NULL) - t->incomingFifo.inF=NULL; - - condbroadcast(t->incomingFifo.notifF); - mutexunlock(nf->lockF); - - /* join threads that are still runing */ - thread = t->allthreads; - while (thread != NULL) { - pthread_cancel(thread->threadID); - struct one_thread *next = thread->next; - free(thread); - thread = next; - } - - return nbRemoved; -} +/// @brief Initialize a threadPool. +/// @param params A string in a form of ",,,...," or "n" +/// if params is "n" threadpool is disabled and all functions are called inline. +/// else if params is a list of comma separated integers, the number of threads +/// is equal to the list length and each thread is pinned to a core indicated by +/// the integer value. If -1 is specified thread is not pinned to any core. +/// @param pool Theadpool +/// @param performanceMeas unused +/// @param name Name of the theadpool, will be used as pthread names for the pool worker threads void initNamedTpool(char *params,tpool_t *pool, bool performanceMeas, char *name); + +/// @brief Initialize a threadpool with floating core worker threads only +/// @param nbThreads number of floating core worker threads +/// @param pool Threadpool +/// @param performanceMeas unused +/// @param name Name of the theadpool, will be used as pthread names for the pool worker threads void initFloatingCoresTpool(int nbThreads,tpool_t *pool, bool performanceMeas, char *name); + +/// Convenience macro #define initTpool(PARAMPTR,TPOOLPTR, MEASURFLAG) initNamedTpool(PARAMPTR,TPOOLPTR, MEASURFLAG, NULL) #endif diff --git a/common/utils/threadPool/thread-pool.md b/common/utils/threadPool/thread-pool.md index 02dd9e0387..7185f2bcc1 100644 --- a/common/utils/threadPool/thread-pool.md +++ b/common/utils/threadPool/thread-pool.md @@ -1,198 +1,7 @@ # Thread pool -The **thread pool** is a working server, made of a set of worker threads that can be mapped on CPU cores. Each thread pool has an **input queue** ("**FIFO**"), from which its workers pick **jobs** (FIFO element) to execute. When a job is done, the worker sends a message to an output queue, if it has been defined. +The **thread pool** is a working server, made of a set of worker threads that can be mapped on CPU cores. All the thread pool functions are thread safe. The functions executed by worker threads are provided by the thread pool client, so the client has to handle the concurrency/parallel execution of his functions. -## license - Author: - Laurent Thomas, Open cells project - The owner share this piece code to Openairsoftware alliance as per OSA license terms - With contributions from Robert Schmidt, OSA - -# Jobs - -A job is a message of type `notifiedFIFO_elt_t`: - -* `next`: internal FIFO chain, do not set it -* `key`: a `long int` that the client can use to identify a job or a group of messages -* `ResponseFifo`: if the client defines a response FIFO, the job will be posted back after processing -* `processingFunc`: any function (of type `void processingFunc(void *)`) that a worker will process -* `msgData`: the data passed to `processingFunc`. It can be added automatically, or you can set it to a buffer you are managing -* `malloced`: a boolean that enables internal free in the case of no return FIFO or abort feature - -The job messages can be created and destroyed with `newNotifiedFIFO_elt()` and `delNotifiedFIFO_elt()`, or managed by the client: - -* `newNotifiedFIFO_elt()`: Creates a job, that will later be used in queues/FIFO -* `delNotifiedFIFO_elt()`: Deletes a job -* `NotifiedFifoData()`: gives a pointer to the beginning of free usage memory in a job (you can put any data there, up to 'size' parameter you passed to `newNotifiedFIFO_elt()`) - -These 3 calls are not mandatory, you can also use your own memory to save the `malloc()`/`free()` that are behind these calls. - -## API details - -### `notifiedFIFO_elt_t *newNotifiedFIFO_elt(int size, uint64_t key, notifiedFIFO_t *reponseFifo, void (*processingFunc)(void *))` - -Creates a new job. The data part of the job will have size `size`, the job can be identified via `key`. `reponseFifo` is a FIFO queue to which the job should be pushed after being processed by a thread pool (see below for details) using function `processingFunc()`. - -The function returns a pointer to an allocated job. - -### `void delNotifiedFIFO_elt(notifiedFIFO_elt_t *elt)` - -Free the memory allocated for a job `elt`. - -### `void *NotifiedFifoData(notifiedFIFO_elt_t *elt)` - -Returns a pointer (`void *`) to the data segment of an allocated job. - -# Queues of jobs (`FIFO`) - -Queues can be used to enqueue messages/jobs, of type `notifiedFIFO_t`. - -* `initNotifiedFIFO()`: Create a queue -* No delete function is required, the creator has only to free the data of type `notifiedFIFO_t` -* `pushNotifiedFIFO()`: Add a job to a queue -* `pullNotifiedFIFO()`: Pull a job from a queue. This call is blocking until a job arrived. -* `pollNotifiedFIFO()`: Pull a job from a queue. This call is not blocking, so it returns always very shortly -* `abortNotifiedFIFO()`: Aborts a FIFO, such that it will always return `NULL` - -Note that in 99.9% of cases, `pull()` is better than `poll()`. - -The above push/pull/poll functions are built on not-thread-safe versions of these functions that are described below. - -## Low level: fast and simple, but not thread-safe - -* `initNotifiedFIFO_nothreadSafe()`: Create a queue -* `pushNotifiedFIFO_nothreadSafe()`: Add a element in a queue -* `pullNotifiedFIFO_nothreadSafe()`: Pull a element from a queue - -As these queues are not thread safe, there is NO blocking mechanism, neither `pull()` versus `poll()` calls - -There is no delete for a message queue: you only have to abandon the memory you allocated to call `initNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf)` - -If you malloced the memory under `nf` parameter, you have to free it. - -## FIFO queue abort - -It is possible to *abort* the FIFO queue. In this case, any pulling/polling of jobs in the queue will return `NULL`. This can be used when stopping a program, to release multiple queues that might depend on each other (a proper design would try to avoid such dependencies, though). - -## API details - -### `void initNotifiedFIFO(notifiedFIFO_t *nf)` -### `void initNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf)` - -Initializes a FIFO queue pointed to by `nf` ("notified FIFO"). - -### `void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg)` -### `void pushNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg)` - -Pushes a job `msg` to the FIFO queue `nf`. - -### `notifiedFIFO_elt_t *pullNotifiedFIFO(notifiedFIFO_t *nf)` - -Pulls a job from a FIFO queue `nf`. The returned pointer points to the job. This call is blocking, i.e., a caller will be blocked until there is a message. - -If the FIFO has been aborted, the returned pointer will be `NULL`. In other words, if the call to this functions returns `NULL`, the FIFO has been deactivated. - -### `notifiedFIFO_elt_t *pollNotifiedFIFO(notifiedFIFO_t *nf)` -### `notifiedFIFO_elt_t *pullNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf)` - -Like `pullNotifiedFIFO()`, but non-blocking: they check if the queue `nf` contains a job, and return it. Otherwise, they return `NULL`. Note the slight difference in naming: the thread-safe function is called *poll*, not *pull*. - -Note that unlike for `pullNotifiedFIFO()`, returning `NULL` does not inform whether the queue has been aborted; the caller should manually check the `abortFIFO` flag of `nf` in this case. - -### `void abortNotifiedFIFO(notifiedFIFO_t *nf)` - -Aborts the entire FIFO queue `nf`: all jobs will be dropped, and the FIFO is marked as aborted, such that a call to `pullNotifiedFIFO()` returns `NULL`. - -Returns the total number of jobs that were waiting or under execution. - -# Thread pools - -## Initialization - -The clients can create one or more thread pools with - -* `initTpool(char *params, tpool_t *pool, bool performanceMeas)` or -* `initNamedTpool(char *params,tpool_t *pool, bool performanceMeas , char *name)` - -The threads are governed by the Linux real time scheduler, and their name is set automatically to `Tpool_` if `initTpool()` is used or to `_` when `initNamedTpool()` is used. - -## Adding jobs - -The client create their jobs messages as a `notifiedFIFO_elt_t`. They then push it with `pushTpool()` which internally calls `push_notifiedFIFO()`. - -If they need a return value (e.g., result of a computation), they have to create response queues with `init_notifiedFIFO()` and set this FIFO pointer in the `notifiedFIFO_elt_t` before pushing the job. This way, multiple result queues can be used in one thread pool. - -## Abort - -`abortTpool()` kills all jobs in the Tpool, and terminates the pool. - -## API details - -Each thread pool (there can be several in the same process) should be initialized once using one of the two API's: - -### `void initNamedTpool(char *params, tpool_t *pool, bool performanceMeas, char *name)` - -### `void initTpool(char *params, tpool_t *pool, bool performanceMeas)` - - -The `params` string describes a list of cores, separated by "," that run a worker thread. If the core exists on the CPU, the thread pool initialization sets the affinity between this thread and the related core. The following options are available: - -* `N`: if an `N` is in the parameter list, no threads are created, and the threadpool will be disabled (jobs will be treated by each calling thread independently). -* A number that represent a valid CPU core on the target CPU, i.e., if there are `M` cores, a number within `[0,M-1]`: A thread is created and pinned to the core (with set affinity) -* `-1`: The thread will not be mapped onto a specific core (a "floating" thread) - -Example: `-1,-1,-1`: the thread pool is made of 3 floating threads. -Be careful with a fixed allocation: it is hard to be more clever than Linux kernel! - -`pool` is a pointer to the thread pool object. - -`performanceMeas` is a flag to enable measurements (see also below). - -`name` is used to build the thread names. - -### `void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg)` - -Adds a job for processing in the thread pool. - -The job data you can set are, inside `msg`: - -* `key`: an arbitrary key to find a job in a response queue. -* `reponseFifo`: if non-`NULL`, the message will be sent back on this queue when the job is done. If `NULL`, the thread pool automatically frees the job when it is done. -* `processingFunc`: the function to execute for this job. - -The `processingFunc` prototype is `void (void *memory)`. The data part of the job (the pointer returned by `NotifiedFifoData(msg)`) is passed to the function. The job data will be updated by `processingFunc`, and the job will be pushed into return queue (the parameter `reponseFifo`). - -### `notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_t *t)` - -Collects a job result in a return queue that has been defined in `msg` when calling `pushTpool()`, and that has been updated by `processingFunc()`. Returns the corresponding job pointer of type `notifiedFIFO_elt_t *`. - -Multiple return queues might be useful. Consider the following example in the eNB: I created one single thread pool (because it depends mainly on CPU hardware), but i use two return queues: one for turbo encode, one for turbo decode. Thus, when performing Turbo encoding/decoding, jobs are pushed into a single thread pool, but will end up in different result queues, such that DL/UL processing can be separated more easily. - -### `notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpool_t *t)` - -The same as `pullTpool()` in a non-blocking fashion (an alternative name would have been `pollTpool()`). - -### `int abortTpool(tpool_t *t)` - -Aborts the complete Tpool: cancel every work in the input queue, marks to drop existing jobs in processing, and terminates all worker threads. It is afterwards still possible to call functions such as `pushTpool()`, but each calling thread will execute the job itself. - -Returns the total number of jobs that were aborted, i.e., waiting for execution or being executed. - -## Performance measurements - -A performance measurement is integrated: the pool will automacillay fill timestamps if you set the environement variable `OAI_THREADPOOLMEASUREMENTS` to a valid file name. The following measurements will be written to Linux pipe on a per-job basis: - -* `creationTime`: time the request is push to the pool; -* `startProcessingTime`: time a worker start to run on the job -* `endProcessingTime`: time the worker finished the job -* `returnTime`: time the client reads the result - -The `measurement_display` tool to read the Linux pipe and display it in ASCII is provided. -In the cmake build directory, type `make/ninja measurement_display`. Use as -follows: -``` -sudo OAI_THREADPOOLMEASUREMENTS=tpool.meas ./nr-softmodem ... -./measurement_display tpool.meas -``` +See header file doxygen comments for detailed description of the API diff --git a/common/utils/time_meas.c b/common/utils/time_meas.c index 31e9cfd6fb..b93c8fc6e4 100644 --- a/common/utils/time_meas.c +++ b/common/utils/time_meas.c @@ -27,7 +27,7 @@ #include "assertions.h" #include #include "common/config/config_userapi.h" -#include +#include "common/utils/threadPool/notified_fifo.h" // global var for openair performance profiler int cpu_meas_enabled = 0; double cpu_freq_GHz __attribute__ ((aligned(32))); diff --git a/common/utils/websrv/CMakeLists.txt b/common/utils/websrv/CMakeLists.txt index 7d7b00b038..25753c458d 100644 --- a/common/utils/websrv/CMakeLists.txt +++ b/common/utils/websrv/CMakeLists.txt @@ -62,7 +62,7 @@ add_library(websrv MODULE websrv_utils.c ../../../openair1/PHY/TOOLS/nr_phy_scope.c ) -target_link_libraries(websrv PRIVATE ulfius jansson asn1_nr_rrc_hdrs) +target_link_libraries(websrv PRIVATE ulfius jansson asn1_nr_rrc_hdrs UTIL) target_compile_definitions(websrv PUBLIC WEBSRVSCOPE) # put websrv into build root and not under build/common/utils/websrv/ set_target_properties(websrv PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../..) diff --git a/doc/Doxyfile b/doc/Doxyfile index bd1661fe60..564c43bb3f 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1332,7 +1332,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/parser.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/device.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/device.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/TLVEncoder.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/OctetString.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/nas_timer.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/TLVDecoder.c \ diff --git a/doc/NR_SA_Tutorial_OAI_multi_UE.md b/doc/NR_SA_Tutorial_OAI_multi_UE.md new file mode 100644 index 0000000000..f596b9cb95 --- /dev/null +++ b/doc/NR_SA_Tutorial_OAI_multi_UE.md @@ -0,0 +1,119 @@ + + + + + + + + + + OAI 5G NR SA tutorial to deploy multiple OAI nrUE + + + + +**Table of Contents** + +[[_TOC_]] + +# Scenario +This tutorial is about how to configure and run multiple OAI nrUE in the same end-to-end OAI 5G setup with RFsimulator. + +# Pre-requisites + +This tutorial is assuming that OAI CN5G and OAI RAN are already deployed. To learn how to deploy and run a basic setup with OAI nrUE, please refer to [NR_SA_Tutorial_OAI_nrUE.md](NR_SA_Tutorial_OAI_nrUE.md). + +Also, it is suggested to get some knowledge on how the channel simulation with OAI RFsimulator works. Please refer to the following documentation to learn about the relevant topics discussed: + +- RFsimulator tutorial [rfsimulator/README.md](../radio/rfsimulator/README.md) +- Channel simulation with OAI [channel_simulation.md](../openair1/SIMULATION/TOOLS/DOC/channel_simulation.md) +- Telnet server usage [telnetusage.md](../common/utils/telnetsrv/DOC/telnetusage.md). + +# Run multiple UEs in RFsimulator + +## Multiple nrUEs with namespaces + +Important notes: + +* This should be run on the same host as the OAI gNB +* Use the script [multi_ue.sh](../tools/scripts/multi-ue.sh) to make namespaces for multiple UEs. +* For each UE, a namespace shall be created, each one has a different address that will be used as rfsim server address +* Each UE shall have a different IMSI, which shall be present in the relevant tables of the MySQL database +* Each UE shall run a telnet server on a different port, with command line option `--telnetsrv.listenport` + +1. For the first UE, create the namespace ue1 (`-c1`), then execute shell inside (`-o1`, "open"): + + ```bash + sudo ./multi-ue.sh -c1 + sudo ./multi-ue.sh -o1 + ``` + +2. After entering the bash environment, run the following command to deploy your first UE + + ```bash + sudo ./nr-uesoftmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --uicc0.imsi 001010000000001 --rfsimulator.options chanmod --rfsimulator.serveraddr 10.201.1.100 --telnetsrv --telnetsrv.listenport 9095 + ``` + +3. For the second UE, create the namespace ue2 (`-c1`), then execute shell inside (`-o1`, "open"): + + ```bash + sudo ./multi-ue.sh -c2 + sudo ./multi-ue.sh -o2 + ``` + +4. After entering the bash environment, run the following command to deploy your second UE: + + ```bash + sudo ./nr-uesoftmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --uicc0.imsi 001010000000002 --rfsimulator.options chanmod --rfsimulator.serveraddr 10.202.1.100 --telnetsrv --telnetsrv.listenport 9096 + ``` + +in the command above, please note that the IMSI and the telnet port changed. + +## Running Multiple UEs with Docker + +1. Make sure OAI nrUE image is pulled: + + ```bash + docker pull oaisoftwarealliance/oai-nr-ue:latest + ``` + +2. Configure your setup by editing the Docker compose file e.g. in [docker-compose.yaml](../ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml). + +3. Deploy the UEs, e.g. for 3 UEs: + + ```bash + docker compose up -d oai-nr-ue{1,2,3} + ``` + +4. Check the logs to ensure each UE has gotten an IP address, e.g.: + + ```bash + docker logs oai-nr-ue1 + ``` + + or + + ```bash + docker exec -it oai-nr-ue1 ip a show oaitun_ue1 + ``` + +5. Test the connectivity of each UE to the core network: + + ```bash + docker exec -it oai-nr-ue1 ping -c1 192.168.70.135 + ``` + +7. After testing, undeploy the UEs to allow them time to deregister, and then bring down the rest of the network: + + ```bash + docker compose stop oai-nr-ue{1,2,3} + docker compose down -v + ``` + +# Further reading + +For more details and scenarios, refer to the following files: + +* [RFSIM deployment in the CI](../ci-scripts/yaml_files/5g_rfsimulator/README.md) +* [E1 deployment in the CI](../ci-scripts/yaml_files/5g_rfsimulator_e1/README.md) +* [Docker documentation](../docker/README.md) diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index d0e66fe68c..199f910b1c 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -78,8 +78,10 @@ Tested libxran releases: | Vendor | |-----------------------------------------| | `oran_e_maintenance_release_v1.0` | +| `oran_f_release_v1.0` | -**Note**: The libxran driver of OAI identifies the above version as "5.1.0" (E is fifth letter, then 1.0). + +**Note**: The libxran driver of OAI identifies the above E release version as "5.1.0" (E is fifth letter, then 1.0), and the above F release as "6.1.0". ## Configure your server @@ -379,19 +381,22 @@ cd ~/openairinterface5g/ ## Build ORAN Fronthaul Interface Library -Download ORAN FHI DU library and checkout the correct version. +Download ORAN FHI DU library, checkout the correct version, and apply the correct patch (available in `oai_folder/cmake_targets/tools/oran_fhi_integration_patches`). +### E release ```bash git clone https://gerrit.o-ran-sc.org/r/o-du/phy.git ~/phy cd ~/phy git checkout oran_e_maintenance_release_v1.0 +git apply ~/openairinterface5g/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch ``` -Apply the patch (available in `oai_folder/cmake_targets/tools/oran_fhi_integration_patches/E`): - +### F release ```bash +git clone https://gerrit.o-ran-sc.org/r/o-du/phy.git ~/phy cd ~/phy -git apply ~/openairinterface5g/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch +git checkout oran_f_release_v1.0 +git apply ~/openairinterface5g/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch ``` Compile the fronthaul interface library by calling `make` and the option @@ -404,7 +409,8 @@ environment variables `RTE_SDK` for the path to the source tree of DPDK, and ```bash cd ~/phy/fhi_lib/lib make clean -RTE_SDK=~/dpdk-stable-20.11.9/ XRAN_DIR=~/phy/fhi_lib make XRAN_LIB_SO=1 +RTE_SDK=~/dpdk-stable-20.11.9/ XRAN_DIR=~/phy/fhi_lib make XRAN_LIB_SO=1 # E release +WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=~/dpdk-stable-20.11.9/ XRAN_DIR=~/phy/fhi_lib make XRAN_LIB_SO=1 # F release ... [AR] build/libxran.so ./build/libxran.so @@ -911,6 +917,7 @@ Edit the sample OAI gNB configuration file and check following parameters: cannot preallocate memory on NUMA nodes other than 0; in this case, set this to 0 (no pre-allocation) and so that DPDK will allocate it on-demand on the right NUMA node. + * `owdm_enable`: used for eCPRI One-Way Delay Measurements; it depends if the RU supports it; if not set to 1 (enabled), default value is 0 (disabled) * `fh_config`: parameters that need to match RU parameters * timing parameters (starting with `T`) depend on the RU: `Tadv_cp_dl` is a single number, the rest pairs of numbers `(x, y)` specifying minimum and @@ -928,7 +935,9 @@ Layer mapping (eAxC offsets) happens as follows: - For PUSCH/PDSCH, the layers are mapped to `[0,1,...,Nrx-1]/[0,1,...,Ntx-1]` where `Nrx/Ntx` is the respective RX/TX number of antennas. - For PRACH, the layers are mapped to `[No,No+1,...No+Nrx-1]` where `No` is the - `fhi_72.fh_config.[0].prach_config.eAxC_offset`. Please be aware that the following equation must be fullfilled: `No >= max(Nrx,Ntx)`. + `fhi_72.fh_config.[0].prach_config.eAxC_offset`. xran assumes PRACH offset `No >= max(Nrx,Ntx)`. + However, we made a workaround that xran supports PRACH eAxC IDs same as PUSCH eAxC IDs. This is achieved with `is_prach` and `filter_id` parameters in the patch. + Please note that this approach only applies to the RUs that support this functionality, e.g. LITEON RU. **Note** diff --git a/doc/README.md b/doc/README.md index 3effd781b6..b703397e3a 100644 --- a/doc/README.md +++ b/doc/README.md @@ -43,6 +43,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https:// * [OAI 5GC](./NR_SA_Tutorial_OAI_CN5G.md) * [OAI gNB with COTS UE](./NR_SA_Tutorial_COTS_UE.md) * [OAI NR-UE](./NR_SA_Tutorial_OAI_nrUE.md) + * [Multiple OAI NR-UE with RFsimulator](./NR_SA_Tutorial_OAI_multi_UE.md) - [RUNMODEM.md](./RUNMODEM.md): Generic information on how to * Run simulators * Run with hardware @@ -64,6 +65,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https:// - [How to setup OAI with Nvidia Aerial and Foxconn](./Aerial_FAPI_Split_Tutorial.md) - [How to setup OAI with AMD T2 Telco card](./LDPC_T2_OFFLOAD_SETUP.md) - [How to do a handover](./handover-tutorial.md) +- [How to setup gNB frequency](./gNB_frequency_setup.md) Legacy unmaintained files: - [`L2NFAPI_NOS1.md`](./L2NFAPI_NOS1.md), [`L2NFAPI_S1.md`](./L2NFAPI_S1.md): diff --git a/doc/gNB_frequency_setup.md b/doc/gNB_frequency_setup.md new file mode 100644 index 0000000000..8ef4a4f083 --- /dev/null +++ b/doc/gNB_frequency_setup.md @@ -0,0 +1,80 @@ +# 5G gNB Frequency Configuration + +Configuring the frequency settings for a 5G gNB involves specifying multiple parameters in the gNB configuration file. This guide outlines the necessary parameters and provides step-by-step instructions for configuration. + +[TOC] + +## Configuration parameters + +To configure the gNB with the required frequency and bandwidth, modify following parameters in the configuration file: + +### `gNBs` Section + +* `absoluteFrequencySSB`: ARFCN (frequency number) of the middle frequency of the SSB. This value must align with the NR frequency raster defined in TS 38.104, Section 5.4.3.1. + * Steps to compute this value are provided below. +* `dl_absoluteFrequencyPointA`: ARFCN (frequency number) for Point A, lowest subcarrier of the reference resource block (Common RB 0). + * Steps to compute this value are provided below. +* `dl_frequencyBand`: downlink NR frequency band number. +* `dl_subcarrierSpacing`: downlink subcarrier spacing. + * *Allowed values:* `0` = 15 kHz, `1` = 30 kHz, `2` = 60 kHz, `3` = 120 kHz +* `dl_carrierBandwidth`: number of PRBs for downlink. +* `initialDLBWPlocationAndBandwidth`: resource indicator value (RIV) of the initial BWP. + * Steps to compute this value are provided below. +* `initialDLBWPsubcarrierSpacing`: initial downlink BWP subcarrier spacing. + * *Allowed values:* `0` = 15 kHz, `1` = 30 kHz, `2` = 60 kHz, `3` = 120 kHz +* `initialDLBWPcontrolResourceSetZero`: CORESET0 index (valid configurations, based on SCS and frequency bandwith, are given in TS 38.213, Table 13.1 to Table 13.14). +* `ul_frequencyBand`: uplink NR frequency band number. +* `ul_absoluteFrequencyPointA`: ARFCN (frequency number) for Point A, lowest subcarrier of the reference resource block (Common RB 0). + * **Set only for FDD configurations.** + * Frequency separation between DL and UL channels for a specific 5G NR band is defined in 38.101-1 5.4.4-1 for FR1 bands and in 38.101-5 5.4.4-1 for FR1 NTN bands. `ul_absoluteFrequencyPointA` is calculated by substracting the given frequency offset from the `dl_absoluteFrequencyPointA`. +* `ul_carrierBandwidth`: number of PRBs for uplink. +* `initialULBWPlocationAndBandwidth`: resource indicator value (RIV) of the initial BWP. + * Steps to compute this value are provided below. +* `initialULBWPsubcarrierSpacing`: initial uplink BWP subcarrier spacing. + * *Allowed values:* `0` = 15 kHz, `1` = 30 kHz, `2` = 60 kHz, `3` = 120 kHz +* `subcarrierSpacing`: general subcarrier spacing for both DL and UL. + * *Allowed values:* `0` = 15 kHz, `1` = 30 kHz, `2` = 60 kHz, `3` = 120 kHz + +### `RUs` Section + +* `bands`: NR frequency band number for RU(s). + +## Determining the ARFCN value for `absoluteFrequencySSB` and `dl_absoluteFrequencyPointA` + +Follow these steps to find the ARFCN values for `absoluteFrequencySSB`, `dl_absoluteFrequencyPointA`, `initialDLBWPlocationAndBandwidth`, and `initialULBWPlocationAndBandwidth`: +1. Convert RU center frequency to ARFCN value + * Example tool: [5G NR ARFCN Calculator](https://5g-tools.com/5g-nr-arfcn-calculator/) + * Input the center frequency of the RU (in MHz) into the tool to calculate the ARFCN value. + +2. Enter parameters into the online tool for NR Point A computation + * Example tool: [NR Reference Point A Tool](https://www.sqimway.com/nr_refA.php) + * Enter the NR frequency band, ARFCN value for center frequency (use the value calculated in step 1), subcarrier spacing, CORESET0 index (`initialDLBWPcontrolResourceSetZero` in the gNB config file) and bandwidth into the tool. + +3. Obtain required values + * From the tool's output, use the following results for your configuration: + * Arfcn GSCN: This corresponds to `absoluteFrequencySSB` - value for `absoluteFrequencySSB` can be selected freely from the table, if `Coreset(0) check` is "ok". + * Point A Arfcnc: This corresponds to `dl_absoluteFrequencyPointA`. + * locationAndBandwidth full: Use this value for both `initialDLBWPlocationAndBandwidth` and `initialULBWPlocationAndBandwidth`. + +4. Set `dl_absoluteFrequencyPointA`, `absoluteFrequencySSB`, `initialDLBWPlocationAndBandwidth`, and `initialULBWPlocationAndBandwidth` in the gNB configuration file + +## Example calculation +1. Convert RU center frequency to ARFCN value + * Center frequency = 3450 MHz + * Center frequency ARFCN = 630000 + +2. Enter parameters into the online tool for NR Point A computation + * Open the [NR Reference Point A Tool](https://www.sqimway.com/nr_refA.php) and input the following values: + * Frequency band = n78 + * NR Arfcn scan (center frequency) = 630000 + * SCS = 30 kHz + * Bandwidth = 100 MHz + * Control ResourceSet Zero = 11 + +3. Obtain required values + * The tool provides following output values: + * Arfcn GSCN (`absoluteFrequencySSB`) = 630048 + * Point A Arfcnc (`dl_absoluteFrequencyPointA`) = 626724 + * locationAndBandwidth full (`initialDLBWPlocationAndBandwidth`) = 1099 + * locationAndBandwidth full (`initialULBWPlocationAndBandwidth`) = 1099 + diff --git a/docker/Dockerfile.build.fhi72.rhel9 b/docker/Dockerfile.build.fhi72.rhel9 index e8a1f2d76b..942896c4f8 100644 --- a/docker/Dockerfile.build.fhi72.rhel9 +++ b/docker/Dockerfile.build.fhi72.rhel9 @@ -43,10 +43,10 @@ RUN wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz && \ ## Build Fronthaul library RUN git clone https://gerrit.o-ran-sc.org/r/o-du/phy.git /opt/phy && \ cd /opt/phy && \ - git checkout oran_e_maintenance_release_v1.0 &&\ - git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch && \ + git checkout oran_f_release_v1.0 &&\ + git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch && \ cd /opt/phy/fhi_lib/lib && \ - RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1 + WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1 FROM ran-base AS ran-build-fhi72 ARG E2AP_VERSION=E2AP_V3 diff --git a/docker/Dockerfile.build.fhi72.ubuntu22 b/docker/Dockerfile.build.fhi72.ubuntu22 index 16ce820832..e40bff5c48 100644 --- a/docker/Dockerfile.build.fhi72.ubuntu22 +++ b/docker/Dockerfile.build.fhi72.ubuntu22 @@ -56,10 +56,10 @@ RUN wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz && \ ## Build Fronthaul library RUN git clone https://gerrit.o-ran-sc.org/r/o-du/phy.git /opt/phy && \ cd /opt/phy && \ - git checkout oran_e_maintenance_release_v1.0 &&\ - git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch && \ + git checkout oran_f_release_v1.0 &&\ + git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch && \ cd /opt/phy/fhi_lib/lib && \ - RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1 + WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1 FROM ran-base AS ran-build-fhi72 ## Build and install OAI diff --git a/docker/Dockerfile.build.rhel9 b/docker/Dockerfile.build.rhel9 index ba10b3a4cd..cff25b7169 100644 --- a/docker/Dockerfile.build.rhel9 +++ b/docker/Dockerfile.build.rhel9 @@ -44,6 +44,7 @@ RUN /bin/sh oaienv && \ --build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF --cmake-opt \ -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \ --build-lib 'telnetsrv enbscope uescope nrscope' \ + --build-tool-opt -k10 \ -w USRP -t Ethernet \ --noavx512" && \ echo "---- ldd on executables ----" && \ diff --git a/docker/Dockerfile.build.rocky b/docker/Dockerfile.build.rocky index 1126c42057..a3b8180dad 100644 --- a/docker/Dockerfile.build.rocky +++ b/docker/Dockerfile.build.rocky @@ -38,6 +38,7 @@ RUN /bin/sh oaienv && \ CXXFLAGS="-Werror -fstack-protector-strong" CFLAGS="-Werror -fstack-protector-strong" ./build_oai -c --ninja \ --eNB --gNB --RU --UE --nrUE \ --build-lib "telnetsrv enbscope uescope nrscope" \ + --build-tool-opt -k10 \ -w USRP -t Ethernet \ --noavx512 && \ echo "---- ldd on executables ----" && \ diff --git a/docker/Dockerfile.build.ubuntu22 b/docker/Dockerfile.build.ubuntu22 index 9ee0b20158..c0de631c41 100644 --- a/docker/Dockerfile.build.ubuntu22 +++ b/docker/Dockerfile.build.ubuntu22 @@ -45,6 +45,7 @@ RUN /bin/sh oaienv && \ -w USRP -t Ethernet \ --build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \ --noavx512 \ + --build-tool-opt -k10 \ --cmake-opt -DCMAKE_C_FLAGS="-Werror" --cmake-opt -DCMAKE_CXX_FLAGS="-Werror" $BUILD_OPTION && \ # Mainly to see if the sanitize option was perfectly executed echo "---- ldd on executables ----" && \ diff --git a/docker/Dockerfile.build.ubuntu22.cross-arm64 b/docker/Dockerfile.build.ubuntu22.cross-arm64 index 91b53ff6b4..78c7a64f64 100644 --- a/docker/Dockerfile.build.ubuntu22.cross-arm64 +++ b/docker/Dockerfile.build.ubuntu22.cross-arm64 @@ -48,7 +48,7 @@ RUN /bin/sh oaienv && \ -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror" && \ echo "====== Start of log for cross-build executables ======" && \ # making always passing so we can analyze the all.txt file - ninja dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim lte-softmodem nr-softmodem nr-cuup oairu lte-uesoftmodem nr-uesoftmodem params_libconfig coding rfsimulator telnetsrv > ../../log/all.txt 2>&1; \ + ninja -k10 dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim lte-softmodem nr-softmodem nr-cuup oairu lte-uesoftmodem nr-uesoftmodem params_libconfig coding rfsimulator telnetsrv > ../../log/all.txt 2>&1; \ # displaying errors and warnings grep -E -A3 "warning:|error:" ../../log/all.txt || true && \ # will fail only if string "errors:" is found diff --git a/docker/Dockerfile.clang.rhel9 b/docker/Dockerfile.clang.rhel9 index 41d3321fef..d1d4387e61 100644 --- a/docker/Dockerfile.clang.rhel9 +++ b/docker/Dockerfile.clang.rhel9 @@ -40,4 +40,7 @@ RUN /bin/sh oaienv && \ mkdir -p log && \ export CC=/usr/bin/clang && \ export CXX=/usr/bin/clang++ && \ - CFLAGS="-Werror" CXXFLAGS="-Werror -Wno-vla-cxx-extension" ./build_oai --phy_simulators --gNB --eNB --nrUE --UE --ninja --noavx512 --disable-T-Tracer -c + CFLAGS="-Werror" CXXFLAGS="-Werror -Wno-vla-cxx-extension" \ + ./build_oai --phy_simulators --gNB --eNB --nrUE --UE \ + --ninja --build-tool-opt -k10 \ + --noavx512 --disable-T-Tracer -c diff --git a/docker/Dockerfile.gNB.aerial.ubuntu22 b/docker/Dockerfile.gNB.aerial.ubuntu22 index 592421c2b3..c5b090f551 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu22 +++ b/docker/Dockerfile.gNB.aerial.ubuntu22 @@ -54,7 +54,7 @@ RUN /bin/sh oaienv && \ RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ - ./build_oai -c -w AERIAL --gNB --ninja \ + ./build_oai -c -w AERIAL --gNB --ninja --build-tool-opt -k10 \ --cmake-opt -DCMAKE_C_FLAGS="-Werror" --cmake-opt -DCMAKE_CXX_FLAGS="-Werror" diff --git a/docker/Dockerfile.phySim.rhel9 b/docker/Dockerfile.phySim.rhel9 index e568c6bc00..a651b2b31d 100644 --- a/docker/Dockerfile.phySim.rhel9 +++ b/docker/Dockerfile.phySim.rhel9 @@ -38,7 +38,7 @@ RUN dnf install -y libasan libubsan RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ - ./build_oai --phy_simulators --ninja --sanitize --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror + ./build_oai --phy_simulators --ninja --build-tool-opt -k10 --sanitize --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror #start from scratch for target executable FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-physim diff --git a/executables/create_tasks.c b/executables/create_tasks.c index 8382cc4074..ad81beca09 100644 --- a/executables/create_tasks.c +++ b/executables/create_tasks.c @@ -52,12 +52,12 @@ int create_tasks(uint32_t enb_nb) { rrc_enb_init(); itti_mark_task_ready(TASK_RRC_ENB); - if (get_softmodem_params()->emulate_l1 || EPC_MODE_ENABLED) { + if (get_softmodem_params()->emulate_l1 || !IS_SOFTMODEM_NOS1) { rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); AssertFatal(rc >= 0, "Create task for SCTP failed\n"); } - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { rc = itti_create_task(TASK_S1AP, s1ap_eNB_task, NULL); AssertFatal(rc >= 0, "Create task for S1AP failed\n"); rc = itti_create_task(TASK_GTPV1_U, gtpv1uTask, NULL); diff --git a/executables/create_tasks_mbms.c b/executables/create_tasks_mbms.c index 368d9453ba..f595dc1095 100644 --- a/executables/create_tasks_mbms.c +++ b/executables/create_tasks_mbms.c @@ -52,12 +52,11 @@ int create_tasks_mbms(uint32_t enb_nb) { if (enb_nb == 0) return 0; - if(!EPC_MODE_ENABLED){ + if (IS_SOFTMODEM_NOS1) { rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); AssertFatal(rc >= 0, "Create task for SCTP failed\n"); } - LOG_I(MME_APP, "Creating MME_APP eNB Task\n"); rc = itti_create_task (TASK_MME_APP, MME_app_task, NULL); AssertFatal(rc >= 0, "Create task for MME APP failed\n"); @@ -71,12 +70,12 @@ int create_tasks_mbms(uint32_t enb_nb) { rc = itti_create_task (TASK_MCE_APP, MCE_app_task, NULL); AssertFatal(rc >= 0, "Create task for MCE APP failed\n"); - if(!EPC_MODE_ENABLED){ - // rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); - // AssertFatal(rc >= 0, "Create task for SCTP failed\n"); + if (IS_SOFTMODEM_NOS1) { + // rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); + // AssertFatal(rc >= 0, "Create task for SCTP failed\n"); rc = itti_create_task(TASK_GTPV1_U, gtpv1uTask, NULL); AssertFatal(rc >= 0, "Create task for GTPV1U failed\n"); - } + } if (is_m3ap_MCE_enabled()) { rc = itti_create_task(TASK_M3AP_MCE, m3ap_MCE_task, NULL); diff --git a/executables/create_tasks_ue.c b/executables/create_tasks_ue.c index 4cffef909d..50b9221f3f 100644 --- a/executables/create_tasks_ue.c +++ b/executables/create_tasks_ue.c @@ -39,7 +39,7 @@ int create_tasks_ue(uint32_t ue_nb) LOG_D(ENB_APP, "%s(ue_nb:%d)\n", __FUNCTION__, ue_nb); itti_wait_ready(1); - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { # if defined(NAS_BUILT_IN_UE) if (ue_nb > 0) { @@ -57,7 +57,7 @@ int create_tasks_ue(uint32_t ue_nb) } # endif - } /* EPC_MODE_ENABLED */ + } if (ue_nb > 0) { if (itti_create_task (TASK_RRC_UE, rrc_ue_task, NULL) < 0) { diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 223d0c92f3..3511ae0a04 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -117,13 +117,10 @@ runmode_t mode = normal_txrx; FILE *input_fd=NULL; - #if MAX_NUM_CCs == 1 -rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}}; double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}}; double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}}; #else -rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}}; double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}}; double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}}; #endif @@ -455,9 +452,7 @@ int main ( int argc, char **argv ) printf("Reading in command-line options\n"); get_options(uniqCfg); - EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1; - - if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) { + if (CONFIG_ISFLAGSET(CONFIG_ABORT)) { fprintf(stderr,"Getting configuration failed\n"); exit(-1); } @@ -470,7 +465,7 @@ int main ( int argc, char **argv ) printf("configuring for RAU/RRU\n"); cpuf=get_cpu_freq_GHz(); - printf("ITTI init, useMME: %i\n",EPC_MODE_ENABLED); + printf("ITTI init, useMME: %i\n", !IS_SOFTMODEM_NOS1); itti_init(TASK_MAX, tasks_info); init_opt(); diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index 74c63687b0..35fb4d4246 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -114,11 +114,9 @@ FILE *input_fd=NULL; int otg_enabled=0; #if MAX_NUM_CCs == 1 -rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}}; double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}}; double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0}}; #else -rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}}; double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}}; double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0},{20,0,0,0}}; #endif @@ -543,7 +541,6 @@ int main( int argc, char **argv ) { } printf("sf_ahead = %d\n", sf_ahead); - EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1; printf("Running with %d UE instances\n",NB_UE_INST); #if T_TRACER diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index 714d885a16..9bec61f2a0 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -28,7 +28,6 @@ #undef MALLOC #include "assertions.h" #include "PHY/types.h" -#include /* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ #define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n" diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 48011f8d17..8de047ea06 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -107,11 +107,9 @@ char *uecap_file; runmode_t mode = normal_txrx; #if MAX_NUM_CCs == 1 -rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}}; double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}}; double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}}; #else -rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}}; double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}}; double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}}; #endif @@ -490,9 +488,6 @@ int main( int argc, char **argv ) { lock_memory_to_ram(); get_options(uniqCfg); - - EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1; - if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) { fprintf(stderr,"Getting configuration failed\n"); exit(-1); diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 0aa966340b..e2882b4224 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -40,6 +40,7 @@ #include "openair1/PHY/TOOLS/phy_scope_interface.h" #include "PHY/MODULATION/nr_modulation.h" #include "instrumentation.h" +#include "common/utils/threadPool/notified_fifo.h" /* * NR SLOT PROCESSING SEQUENCE @@ -101,8 +102,10 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg); static void start_process_slot_tx(void* arg) { - notifiedFIFO_elt_t *newTx = arg; - pushTpool(&(get_nrUE_params()->Tpool), newTx); + task_t task; + task.args = arg; + task.func = processSlotTX; + pushTpool(&(get_nrUE_params()->Tpool), task); } static size_t dump_L1_UE_meas_stats(PHY_VARS_NR_UE *ue, char *output, size_t max_len) @@ -487,7 +490,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action) void processSlotTX(void *arg) { TracyCZone(ctx, true); - nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg; + nr_rxtx_thread_data_t *rxtxD = arg; const UE_nr_rxtx_proc_t *proc = &rxtxD->proc; PHY_VARS_NR_UE *UE = rxtxD->UE; nr_phy_data_tx_t phy_data = {0}; @@ -550,6 +553,7 @@ void processSlotTX(void *arg) int next_slot = (proc->nr_slot_tx + 1) % slots_per_frame; dynamic_barrier_join(&UE->process_slot_tx_barriers[next_slot]); RU_write(rxtxD, sl_tx_action); + free(rxtxD); TracyCZoneEnd(ctx); } @@ -823,7 +827,7 @@ void *UE_thread(void *arg) while (!oai_exit) { if (syncRunning) { - notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool)); + notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf); if (res) { syncRunning = false; @@ -1003,7 +1007,7 @@ void *UE_thread(void *arg) nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.frame_tx, curMsg.proc.gNB_id); // RX slot processing. We launch and forget. - notifiedFIFO_elt_t *newRx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_rx, NULL, UE_dl_processing); + notifiedFIFO_elt_t *newRx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_tx, NULL, UE_dl_processing); nr_rxtx_thread_data_t *curMsgRx = (nr_rxtx_thread_data_t *)NotifiedFifoData(newRx); *curMsgRx = (nr_rxtx_thread_data_t){.proc = curMsg.proc, .UE = UE}; int ret = UE_dl_preprocessing(UE, &curMsgRx->proc, tx_wait_for_dlsch, &curMsgRx->phy_data, &stats_printed); @@ -1013,8 +1017,7 @@ void *UE_thread(void *arg) // Start TX slot processing here. It runs in parallel with RX slot processing // in current code, DURATION_RX_TO_TX constant is the limit to get UL data to encode from a RX slot - notifiedFIFO_elt_t *newTx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_tx, NULL, processSlotTX); - nr_rxtx_thread_data_t *curMsgTx = (nr_rxtx_thread_data_t *)NotifiedFifoData(newTx); + nr_rxtx_thread_data_t *curMsgTx = calloc(1, sizeof(*curMsgTx)); curMsgTx->proc = curMsg.proc; curMsgTx->writeBlockSize = writeBlockSize; curMsgTx->proc.timestamp_tx = writeTimestamp; @@ -1026,7 +1029,7 @@ void *UE_thread(void *arg) dynamic_barrier_update(&UE->process_slot_tx_barriers[slot], tx_wait_for_dlsch[slot] + sync_to_previous_thread, start_process_slot_tx, - newTx); + curMsgTx); stream_status = STREAM_STATUS_SYNCED; tx_wait_for_dlsch[slot] = 0; } diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 07d3e532f5..ff8a7f7fa8 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -33,7 +33,6 @@ #include "SCHED_NR_UE/defs.h" #include "common/ran_context.h" #include "common/config/config_userapi.h" -//#include "common/utils/threadPool/thread-pool.h" #include "common/utils/load_module_shlib.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "common/utils/nr/nr_common.h" diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 65327cc3b2..40ff2075a5 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -2,6 +2,7 @@ #define NR_UESOFTMODEM_H #include #include +#include "common/utils/threadPool/thread-pool.h" #include "PHY/defs_nr_UE.h" #define CONFIG_HLP_IF_FREQ "IF frequency for RF, if needed\n" @@ -78,7 +79,7 @@ typedef struct { uint64_t optmask; // mask to store boolean config options uint32_t ofdm_offset_divisor; // Divisor for sample offset computation for each OFDM symbol int max_ldpc_iterations; // number of maximum LDPC iterations - tpool_t Tpool; // thread pool + tpool_t Tpool; int UE_scan_carrier; int UE_fo_compensation; uint64_t if_freq; diff --git a/executables/softmodem-common.c b/executables/softmodem-common.c index 394235e8f0..9f39612733 100644 --- a/executables/softmodem-common.c +++ b/executables/softmodem-common.c @@ -46,7 +46,6 @@ static softmodem_params_t softmodem_params; char *parallel_config=NULL; char *worker_config=NULL; int usrp_tx_thread = 0; -char *nfapi_str=NULL; uint8_t nfapi_mode=0; static mapping softmodem_funcs[] = MAPPING_SOFTMODEM_FUNCTIONS; diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index fac59693fd..5c8e032d5e 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -349,7 +349,6 @@ void configure_rru(void *, void *arg); struct timespec timespec_add(struct timespec lhs, struct timespec rhs); struct timespec timespec_sub(struct timespec lhs, struct timespec rhs); extern uint8_t nfapi_mode; -extern int16_t vnf_pnf_sfnslot_delta; #ifdef __cplusplus } #endif diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.c b/nfapi/oai_integration/aerial/fapi_vnf_p7.c index 25508f833b..85308472f3 100644 --- a/nfapi/oai_integration/aerial/fapi_vnf_p7.c +++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.c @@ -380,84 +380,32 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, } nfapi_nr_p7_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *end = pPackedBuf + packedBufLen; uint8_t *data_end = pDataBuf + dataBufLen; - uint8_t *pWritePackedMessage = pPackedBuf; uint8_t *pDataPackedMessage = pDataBuf; - uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint8_t *pPacketBodyField = &pWritePackedMessage[8]; - uint8_t *pPacketBodyFieldStart = &pWritePackedMessage[8]; uint8_t *pPackedDataField = &pDataPackedMessage[0]; uint8_t *pPackedDataFieldStart = &pDataPackedMessage[0]; - - // PHY API message header - // Number of messages [0] - // Opaque handle [1] - // PHY API Message structure - // Message type ID [2,3] - // Message Length [4,5,6,7] - // Message Body [8,...] - if (!(push8(1, &pWritePackedMessage, pPackMessageEnd) && push8(0, &pWritePackedMessage, pPackMessageEnd) - && push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd))) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); - return -1; - } - - uint8_t **ppWriteBody = &pPacketBodyField; uint8_t **ppWriteData = &pPackedDataField; + const uint32_t dataBufLen32 = (dataBufLen + 3) / 4; nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)pMessageHeader; - - if (!(push16(pNfapiMsg->SFN, ppWriteBody, end) && push16(pNfapiMsg->Slot, ppWriteBody, end) - && push16(pNfapiMsg->Number_of_PDUs, ppWriteBody, end))) { - return 0; - } - + // Actual payloads are packed in a separate buffer for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)&pNfapiMsg->pdu_list[i]; // recalculate PDU_Length for Aerial (leave only the size occupied in the payload buffer afterward) // assuming there is only 1 TLV present value->PDU_length = value->TLVs[0].length; - if (!(push32(value->PDU_length, ppWriteBody, end) && // cuBB expects TX_DATA.request PDUSize to be 32 bit - push16(value->PDU_index, ppWriteBody, end) && push32(value->num_TLV, ppWriteBody, end))) { - return 0; - } - uint16_t k = 0; - uint16_t total_number_of_tlvs = value->num_TLV; - - for (; k < total_number_of_tlvs; ++k) { - // For Aerial, the TLV tag is always 2 - if (!(push16(/*value->TLVs[k].tag*/ 2, ppWriteBody, end) && push16(/*value->TLVs[k].length*/ 4, ppWriteBody, end))) { - return 0; - } - // value - if (!push32(0, ppWriteBody, end)) { - return 0; - } - } - } - - // Actual payloads are packed in a separate buffer - for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { - nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)&pNfapiMsg->pdu_list[i]; - - uint16_t k = 0; - uint16_t total_number_of_tlvs = value->num_TLV; - - for (; k < total_number_of_tlvs; ++k) { + for (uint32_t k = 0; k < value->num_TLV; ++k) { + // Ensure tag is 2 + value->TLVs[k].tag = 2; + uint32_t num_values_to_push = ((value->TLVs[k].length + 3) / 4); if (value->TLVs[k].length > 0) { if (value->TLVs[k].length % 4 != 0) { - if (!pusharray32(value->TLVs[k].value.direct, - (dataBufLen + 3) / 4, - ((value->TLVs[k].length + 3) / 4) - 1, - ppWriteData, - data_end)) { + if (!pusharray32(value->TLVs[k].value.direct, dataBufLen32, num_values_to_push - 1, ppWriteData, data_end)) { return 0; } int bytesToAdd = 4 - (4 - (value->TLVs[k].length % 4)) % 4; if (bytesToAdd != 4) { for (int j = 0; j < bytesToAdd; j++) { - uint8_t toPush = (uint8_t)(value->TLVs[k].value.direct[((value->TLVs[k].length + 3) / 4) - 1] >> (j * 8)); + uint8_t toPush = (uint8_t)(value->TLVs[k].value.direct[num_values_to_push - 1] >> (j * 8)); if (!push8(toPush, ppWriteData, data_end)) { return 0; } @@ -465,11 +413,7 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, } } else { // no padding needed - if (!pusharray32(value->TLVs[k].value.direct, - (dataBufLen + 3) / 4, - ((value->TLVs[k].length + 3) / 4), - ppWriteData, - data_end)) { + if (!pusharray32(value->TLVs[k].value.direct, dataBufLen32, num_values_to_push, ppWriteData, data_end)) { return 0; } } @@ -484,26 +428,12 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, uintptr_t dataEnd = (uintptr_t)pPackedDataField; data_len[0] = dataEnd - dataHead; - // check for a valid message length - uintptr_t msgHead = (uintptr_t)pPacketBodyFieldStart; - uintptr_t msgEnd = (uintptr_t)pPacketBodyField; - uint32_t packedMsgLen = msgEnd - msgHead; - uint16_t packedMsgLen16; - if (packedMsgLen > packedBufLen + dataBufLen) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return 0; - } else { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - // Update the message length in the header - pMessageHeader->message_length = packedMsgLen16; + if (!fapi_nr_p7_message_pack(pMessageBuf, pPackedBuf, packedBufLen, config)) { + return -1; + } - // Update the message length in the header - if (!push32(packedMsgLen, &pPackedLengthField, pPackMessageEnd)) - return 0; - - return (packedMsgLen16); + return (int32_t)(pMessageHeader->message_length); } diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index c96acd9fba..c0a4622aa4 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -78,16 +78,12 @@ extern int nfapi_sync_var; extern int sync_var; nfapi_tx_request_pdu_t *tx_request_pdu[1023][10][10]; // [frame][subframe][max_num_pdus] -uint8_t nr_tx_pdus[32][16][4096]; nfapi_nr_pdu_t *tx_data_request[1023][20][10]; //[frame][slot][max_num_pdus] uint8_t tx_pdus[32][8][4096]; nfapi_ue_release_request_body_t release_rntis; -nfapi_nr_pnf_param_response_t g_pnf_param_resp; - - -nfapi_pnf_p7_config_t *p7_config_g = NULL; +static nfapi_pnf_p7_config_t *p7_config_g = NULL; void *pnf_allocate(size_t size) { return malloc(size); @@ -1727,8 +1723,8 @@ int pnf_nr_sim_pack_vendor_extention_tlv(void *ve, uint8_t **ppWritePackedMsg, u return -1; } -nfapi_dl_config_request_t dummy_dl_config_req; -nfapi_tx_request_t dummy_tx_req; +static nfapi_dl_config_request_t dummy_dl_config_req; +static nfapi_tx_request_t dummy_tx_req; int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_start_request_t *req) { printf("[PNF] Received NFAPI_START_REQ phy_id:%d\n", req->header.phy_id); diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c index 8e58e51178..a247541315 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c @@ -1509,7 +1509,7 @@ uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg return 1; } -static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end, uint32_t *payload_offset) { nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)tlv; if (!(push32(value->PDU_length, ppWritePackedMsg, end) && push16(value->PDU_index, ppWritePackedMsg, end) @@ -1517,8 +1517,15 @@ static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg return 0; for (int i = 0; i < value->num_TLV; ++i) { - if (!(push16(value->TLVs[i].tag, ppWritePackedMsg, end) && push32(value->TLVs[i].length, ppWritePackedMsg, end))) + if (!push16(value->TLVs[i].tag, ppWritePackedMsg, end)) return 0; +#ifdef ENABLE_AERIAL + if (!push16(value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; +#else + if (!push32(value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; +#endif const uint32_t byte_len = (value->TLVs[i].length + 3) / 4; switch (value->TLVs[i].tag) { case 0: { @@ -1537,7 +1544,14 @@ static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg break; } - + case 2: { + // Currently Tag = 2 is only used for Aerial + if (!push32(*payload_offset, ppWritePackedMsg, end)) { + return 0; + } + *payload_offset += value->TLVs[i].length; + break; + } default: { NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag); break; @@ -1555,9 +1569,9 @@ uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end))) return 0; - + uint32_t payload_offset = 0; for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { - if (!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) { + if (!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end, &payload_offset)) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. Error packing TX_DATA.request PDU #%d, PDU length = %d PDU IDX = %d\n", __FUNCTION__, diff --git a/nfapi/open-nFAPI/pnf_sim/src/main.cpp b/nfapi/open-nFAPI/pnf_sim/src/main.cpp index 251e2a48cb..679b675f68 100644 --- a/nfapi/open-nFAPI/pnf_sim/src/main.cpp +++ b/nfapi/open-nFAPI/pnf_sim/src/main.cpp @@ -59,10 +59,6 @@ static uint32_t rand_range(uint32_t min, uint32_t max) return ((rand() % (max + 1 - min)) + min); } - - -extern "C" nfapi_pnf_param_response_t g_pnf_param_resp; - extern "C" { diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index a30efaf47f..e687121312 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -2068,7 +2068,7 @@ void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } -int16_t vnf_pnf_sfnslot_delta; +static int16_t vnf_pnf_sfnslot_delta; void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { diff --git a/openair1/PHY/CODING/nrLDPC_defs.h b/openair1/PHY/CODING/nrLDPC_defs.h index 3ff2381d0b..628862c687 100644 --- a/openair1/PHY/CODING/nrLDPC_defs.h +++ b/openair1/PHY/CODING/nrLDPC_defs.h @@ -64,6 +64,7 @@ typedef struct { nrLDPC_params_per_cb_t perCB[NR_LDPC_MAX_NUM_CB]; // Redundancy version index uint8_t rv; + task_ans_t *ans; } encoder_implemparams_t; typedef int32_t(LDPC_initfunc_t)(void); diff --git a/openair1/PHY/LTE_ESTIMATION/freq_equalization.c b/openair1/PHY/LTE_ESTIMATION/freq_equalization.c index 2b42d68fd0..e32c86f20e 100644 --- a/openair1/PHY/LTE_ESTIMATION/freq_equalization.c +++ b/openair1/PHY/LTE_ESTIMATION/freq_equalization.c @@ -24,263 +24,263 @@ #include "PHY/LTE_ESTIMATION/lte_estimation.h" // This is 4096/(1:4096) in simde__m128i format -simde__m128i inv_ch[4096];/* = {512,512,512,512,512,512,512,512, - 256,256,256,256,256,256,256,256, - 170,170,170,170,170,170,170,170, - 128,128,128,128,128,128,128,128, - 102,102,102,102,102,102,102,102, - 85,85,85,85,85,85,85,85, - 73,73,73,73,73,73,73,73, - 64,64,64,64,64,64,64,64, - 56,56,56,56,56,56,56,56, - 51,51,51,51,51,51,51,51, - 46,46,46,46,46,46,46,46, - 42,42,42,42,42,42,42,42, - 39,39,39,39,39,39,39,39, - 36,36,36,36,36,36,36,36, - 34,34,34,34,34,34,34,34, - 32,32,32,32,32,32,32,32, - 30,30,30,30,30,30,30,30, - 28,28,28,28,28,28,28,28, - 26,26,26,26,26,26,26,26, - 25,25,25,25,25,25,25,25, - 24,24,24,24,24,24,24,24, - 23,23,23,23,23,23,23,23, - 22,22,22,22,22,22,22,22, - 21,21,21,21,21,21,21,21, - 20,20,20,20,20,20,20,20, - 19,19,19,19,19,19,19,19, - 18,18,18,18,18,18,18,18, - 18,18,18,18,18,18,18,18, - 17,17,17,17,17,17,17,17, - 17,17,17,17,17,17,17,17, - 16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16, - 15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15, - 14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,14, - 13,13,13,13,13,13,13,13, - 13,13,13,13,13,13,13,13, - 13,13,13,13,13,13,13,13, - 12,12,12,12,12,12,12,12, - 12,12,12,12,12,12,12,12, - 12,12,12,12,12,12,12,12, - 11,11,11,11,11,11,11,11, - 11,11,11,11,11,11,11,11, - 11,11,11,11,11,11,11,11, - 11,11,11,11,11,11,11,11, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 9,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9, - 8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8, - 7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2, - };*/ +static simde__m128i inv_ch[4096]; /* = {512,512,512,512,512,512,512,512, + 256,256,256,256,256,256,256,256, + 170,170,170,170,170,170,170,170, + 128,128,128,128,128,128,128,128, + 102,102,102,102,102,102,102,102, + 85,85,85,85,85,85,85,85, + 73,73,73,73,73,73,73,73, + 64,64,64,64,64,64,64,64, + 56,56,56,56,56,56,56,56, + 51,51,51,51,51,51,51,51, + 46,46,46,46,46,46,46,46, + 42,42,42,42,42,42,42,42, + 39,39,39,39,39,39,39,39, + 36,36,36,36,36,36,36,36, + 34,34,34,34,34,34,34,34, + 32,32,32,32,32,32,32,32, + 30,30,30,30,30,30,30,30, + 28,28,28,28,28,28,28,28, + 26,26,26,26,26,26,26,26, + 25,25,25,25,25,25,25,25, + 24,24,24,24,24,24,24,24, + 23,23,23,23,23,23,23,23, + 22,22,22,22,22,22,22,22, + 21,21,21,21,21,21,21,21, + 20,20,20,20,20,20,20,20, + 19,19,19,19,19,19,19,19, + 18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18, + 17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17, + 16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16, + 15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15, + 14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14, + 13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13, + 12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12, + 11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9, + 8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8, + 7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7, + 6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + };*/ void init_fde() { for (int i=1;i<4096;i++) inv_ch[i] = simde_mm_set1_epi16(4096/i); diff --git a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c index db6bdff2cd..f1b26c8d4e 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c @@ -29,8 +29,7 @@ #define k1 1024 #define k2 (1024-k1) -int32_t rx_power_avg_eNB[3]; - +static int32_t rx_power_avg_eNB[3]; void dump_I0_stats(FILE *fd,PHY_VARS_eNB *eNB) { diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 8541d11771..dc3c98c4f1 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -42,7 +42,6 @@ #include "common/utils/LOG/log.h" #include "executables/lte-softmodem.h" #include -#include //#define DEBUG_DLSCH_CODING //#define DEBUG_DLSCH_FREE 1 @@ -284,6 +283,9 @@ static void TPencode(void * arg) { rdata->r, hadlsch->nb_rb); stop_meas(rdata->rm_stats); + + // Task completed in parallel + completed_task_ans(rdata->ans); } int dlsch_encoding(PHY_VARS_eNB *eNB, @@ -321,8 +323,6 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, num_pdcch_symbols, frame,subframe,beamforming_mode); - int nbEncode = 0; - // if (hadlsch->Ndi == 1) { // this is a new packet if (hadlsch->round == 0) { // this is a new packet // Add 24-bit crc (polynomial A) to payload @@ -349,13 +349,14 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, return(-1); } - notifiedFIFO_t respEncode; - initNotifiedFIFO(&respEncode); - for (int r=0, r_offset=0; rC; r++) { - - union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}}; - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, &respEncode, TPencode); - turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req); + turboEncode_t arr[hadlsch->C]; + task_ans_t ans[hadlsch->C]; + memset(ans, 0, hadlsch->C * sizeof(task_ans_t)); + + for (int r = 0, r_offset = 0; r < hadlsch->C; r++) { + turboEncode_t *rdata = &arr[r]; + rdata->ans = &ans[r]; + rdata->input=hadlsch->c[r]; rdata->Kr_bytes= ( rCminus ? hadlsch->Kminus : hadlsch->Kplus) >>3; rdata->filler=(r==0) ? hadlsch->F : 0; @@ -369,8 +370,8 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, rdata->r_offset=r_offset; rdata->G=G; - pushTpool(proc->threadPool, req); - nbEncode++; + task_t t = {.func = TPencode, .args = rdata}; + pushTpool(proc->threadPool, t); int Qm=hadlsch->Qm; int C=hadlsch->C; @@ -382,14 +383,9 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, else r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); } - // Wait all other threads finish to process - while (nbEncode) { - notifiedFIFO_elt_t *res = pullTpool(&respEncode, proc->threadPool); - if (res == NULL) - break; // Tpool has been stopped - delNotifiedFIFO_elt(res); - nbEncode--; - } + + join_task_ans(ans, hadlsch->C); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); return(0); } @@ -454,14 +450,14 @@ int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB, &hadlsch->F)<0) return(-1); } - int nbEncode = 0; - notifiedFIFO_t respEncode; - initNotifiedFIFO(&respEncode); - for (int r=0, r_offset=0; rC; r++) { - - union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}}; - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, &respEncode, TPencode); - turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req); + turboEncode_t arr[hadlsch->C]; + task_ans_t ans[hadlsch->C]; + memset(ans, 0, hadlsch->C * sizeof(task_ans_t)); + + for (int r = 0, r_offset = 0; r < hadlsch->C; r++) { + turboEncode_t *rdata = &arr[r]; + rdata->ans = &ans[r]; + rdata->input=hadlsch->c[r]; rdata->Kr_bytes= ( rCminus ? hadlsch->Kminus : hadlsch->Kplus) >>3; rdata->filler=(r==0) ? hadlsch->F : 0; @@ -475,8 +471,8 @@ int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB, rdata->r_offset=r_offset; rdata->G=G; - pushTpool(proc->threadPool, req); - nbEncode++; + task_t t = {.func = TPencode, .args = rdata}; + pushTpool(proc->threadPool, t); int Qm=hadlsch->Qm; int C=hadlsch->C; @@ -488,14 +484,9 @@ int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB, else r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); } - // Wait all other threads finish to process - while (nbEncode) { - notifiedFIFO_elt_t *res = pullTpool(&respEncode, proc->threadPool); - if (res == NULL) - break; // Tpool has been stopped - delNotifiedFIFO_elt(res); - nbEncode--; - } + + join_task_ans(ans, hadlsch->C); + return(0); } diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index b9d4fbc906..bb2da63964 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -3025,22 +3025,20 @@ inline int check_skip_dc(int rb,LTE_DL_FRAME_PARMS *frame_parms) { return(0); } +static uint64_t qam4_tm2_p2_0[8][16] __attribute__((aligned(32))); +static uint64_t qam4_tm2_p2_1[8][16] __attribute__((aligned(32))); +static uint64_t qam4_tm2_p2_b0[8][4][16] __attribute__((aligned(32))); +static uint64_t qam4_tm2_p2_b1[8][4][16] __attribute__((aligned(32))); -uint64_t qam4_tm2_p2_0[8][16] __attribute__ ((aligned(32))); -uint64_t qam4_tm2_p2_1[8][16] __attribute__ ((aligned(32))); -uint64_t qam4_tm2_p2_b0[8][4][16] __attribute__ ((aligned(32))); -uint64_t qam4_tm2_p2_b1[8][4][16] __attribute__ ((aligned(32))); - -uint64_t qam16_tm2_p2_0[8][256] __attribute__ ((aligned(32))); -uint64_t qam16_tm2_p2_1[8][256] __attribute__ ((aligned(32))); -uint64_t qam16_tm2_p2_b0[8][4][256] __attribute__ ((aligned(32))); -uint64_t qam16_tm2_p2_b1[8][4][256] __attribute__ ((aligned(32))); - -uint64_t qam64_tm2_p2_0[8][4096] __attribute__ ((aligned(32))); -uint64_t qam64_tm2_p2_1[8][4096] __attribute__ ((aligned(32))); -uint64_t qam64_tm2_p2_b0[8][4][4096] __attribute__ ((aligned(32))); -uint64_t qam64_tm2_p2_b1[8][4][4096] __attribute__ ((aligned(32))); +static uint64_t qam16_tm2_p2_0[8][256] __attribute__((aligned(32))); +static uint64_t qam16_tm2_p2_1[8][256] __attribute__((aligned(32))); +static uint64_t qam16_tm2_p2_b0[8][4][256] __attribute__((aligned(32))); +static uint64_t qam16_tm2_p2_b1[8][4][256] __attribute__((aligned(32))); +static uint64_t qam64_tm2_p2_0[8][4096] __attribute__((aligned(32))); +static uint64_t qam64_tm2_p2_1[8][4096] __attribute__((aligned(32))); +static uint64_t qam64_tm2_p2_b0[8][4][4096] __attribute__((aligned(32))); +static uint64_t qam64_tm2_p2_b1[8][4][4096] __attribute__((aligned(32))); void init_modulation_LUT_qam4_tm2_p2() { diff --git a/openair1/PHY/LTE_TRANSPORT/edci.c b/openair1/PHY/LTE_TRANSPORT/edci.c index f3a43584fb..8370b35b49 100644 --- a/openair1/PHY/LTE_TRANSPORT/edci.c +++ b/openair1/PHY/LTE_TRANSPORT/edci.c @@ -235,8 +235,7 @@ void init_mpdcch2ss1tab_normal_regular_subframe_evenNRBDL(PHY_VARS_eNB *eNB) { extern uint8_t *generate_dci0(uint8_t *dci, uint8_t *e, uint8_t DCI_LENGTH, uint16_t coded_bits, uint16_t rnti); - -uint16_t mpdcch_dmrs_tab[12 * 6]; +static uint16_t mpdcch_dmrs_tab[12 * 6]; void init_mpdcch_dmrs_tab(uint16_t oss) { int re = 5 * oss; diff --git a/openair1/PHY/LTE_TRANSPORT/prach_common.c b/openair1/PHY/LTE_TRANSPORT/prach_common.c index 14bf35aab7..2d9ef9d712 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach_common.c +++ b/openair1/PHY/LTE_TRANSPORT/prach_common.c @@ -41,7 +41,7 @@ const uint16_t NCS_restricted[15] = {15, 18, 22, 26, 32, 38, 46, 55, 68, 82, 100 const uint16_t NCS_4[7] = {2, 4, 6, 8, 10, 12, 15}; int16_t ru[2*839]; // quantized roots of unity -uint32_t ZC_inv[839]; // multiplicative inverse for roots u +static uint32_t ZC_inv[839]; // multiplicative inverse for roots u uint16_t du[838]; extern PRACH_TDD_PREAMBLE_MAP tdd_preamble_map[64][7]; diff --git a/openair1/PHY/LTE_TRANSPORT/prach_extern.h b/openair1/PHY/LTE_TRANSPORT/prach_extern.h index 6f9654fbb0..75644e4a5b 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach_extern.h +++ b/openair1/PHY/LTE_TRANSPORT/prach_extern.h @@ -44,8 +44,7 @@ extern const uint16_t NCS_unrestricted[16]; extern const uint16_t NCS_restricted[15]; extern const uint16_t NCS_4[7]; -extern int16_t ru[2*839]; // quantized roots of unity -extern uint32_t ZC_inv[839]; // multiplicative inverse for roots u +extern int16_t ru[2 * 839]; // quantized roots of unity extern uint16_t du[838]; diff --git a/openair1/PHY/LTE_TRANSPORT/transport_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_proto.h index a6765c0fe2..9cf09d7b52 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_proto.h @@ -36,6 +36,7 @@ #include "nfapi_interface.h" #include "transport_common_proto.h" + // Functions below implement 36-211 and 36-212 /** @addtogroup _PHY_TRANSPORT_ @@ -520,12 +521,13 @@ void rx_ulsch(PHY_VARS_eNB *eNB, @param llr8_flag If 1, indicate that the 8-bit turbo decoder should be used @returns 0 on success */ -unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, - L1_rxtx_proc_t *proc, - uint8_t UE_id, - uint8_t control_only_flag, - uint8_t Nbundled, - uint8_t llr8_flag); +unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, + L1_rxtx_proc_t *proc, + uint8_t UE_id, + uint8_t control_only_flag, + uint8_t Nbundled, + uint8_t llr8_flag, + thread_info_tm_t *t_info); void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, L1_rxtx_proc_t *proc, diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 31aff198dd..be998beb44 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -239,8 +239,10 @@ void processULSegment(void * arg) { 1, r, &E)==-1) { - LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); - return; + // Task completed in parallel + completed_task_ans(rdata->ans); + LOG_E(PHY, "ulsch_decoding.c: Problem in rate matching\n"); + return; } stop_meas(&eNB->ulsch_rate_unmatching_stats); int max_Ncb = 3*ulsch_harq->RTC[r]*32 ; @@ -284,6 +286,9 @@ void processULSegment(void * arg) { &eNB->ulsch_tc_intl1_stats, &eNB->ulsch_tc_intl2_stats, &ulsch_harq->abort_decode); + + // Task completed in parallel + completed_task_ans(rdata->ans); } /*! @@ -295,7 +300,12 @@ void processULSegment(void * arg) { @returns 0 on success */ -static int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int UE_id, int harq_pid, int llr8_flag) +static int ulsch_decoding_data(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + int UE_id, + int harq_pid, + int llr8_flag, + thread_info_tm_t *t_info) { unsigned int r_offset=0; int offset = 0; @@ -330,13 +340,11 @@ static int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int UE_i E = ulsch_harq->Qm * (Gp/ulsch_harq->C); else E = ulsch_harq->Qm * ((GpmodC==0?0:1) + (Gp/ulsch_harq->C)); - - union turboReqUnion id= {.s={ulsch->rnti,proc->frame_rx,proc->subframe_rx,0,0}}; - notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboDecode_t), - id.p, - proc->respDecode, - processULSegment); - turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req); + + turboDecode_t *rdata = &((turboDecode_t *)t_info->buf)[t_info->len]; + DevAssert(t_info->len < t_info->cap); + rdata->ans = &t_info->ans[t_info->len]; + t_info->len += 1; rdata->eNB=eNB; rdata->frame=proc->frame_rx; @@ -355,7 +363,10 @@ static int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int UE_i rdata->function=td; int Fbytes=(r==0) ? rdata->Fbits>>3 : 0; int sz=Kr_bytes - Fbytes - ((ulsch_harq->C>1)?3:0); - pushTpool(proc->threadPool,req); + + task_t t = {.func = &processULSegment, .args = rdata}; + pushTpool(proc->threadPool, t); + proc->nbDecode++; LOG_D(PHY,"Added a block to decode, in pipe: %d\n",proc->nbDecode); r_offset+=E; @@ -390,12 +401,13 @@ static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, // printf("n=%d : c %x\n",n,x1^x2); } -unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, - L1_rxtx_proc_t *proc, - uint8_t UE_id, - uint8_t control_only_flag, - uint8_t Nbundled, - uint8_t llr8_flag) +unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + uint8_t UE_id, + uint8_t control_only_flag, + uint8_t Nbundled, + uint8_t llr8_flag, + thread_info_tm_t *t_info) { int16_t *ulsch_llr = eNB->pusch_vars[UE_id]->llr; LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; @@ -1082,7 +1094,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, LOG_D(PHY,"frame %d subframe %d O_ACK:%d o_ACK[]=%d:%d:%d:%d\n",frame,subframe,ulsch_harq->O_ACK,ulsch_harq->o_ACK[0],ulsch_harq->o_ACK[1],ulsch_harq->o_ACK[2],ulsch_harq->o_ACK[3]); // Do ULSCH Decoding for data portion - ret = ulsch_decoding_data(eNB, proc, UE_id, harq_pid, llr8_flag); + ret = ulsch_decoding_data(eNB, proc, UE_id, harq_pid, llr8_flag, t_info); return(ret); } diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 4052e5ce89..0370285e07 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -560,7 +560,7 @@ void ulsch_channel_level(int32_t **drs_ch_estimates_ext, simde_m_empty(); } -int ulsch_power_LUT[750]; +static int ulsch_power_LUT[750]; void init_ulsch_power_LUT(void) { int i; diff --git a/openair1/PHY/LTE_UE_TRANSPORT/rar_tools_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/rar_tools_ue.c index b856976638..44855e551e 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/rar_tools_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/rar_tools_ue.c @@ -35,22 +35,11 @@ #include "LAYER2/MAC/mac.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "transport_proto_ue.h" +#include "openair1/PHY/LTE_TRANSPORT/dci_tools_common_extern.h" #include "PHY/LTE_TRANSPORT/transport_vars.h" #include "assertions.h" - -extern uint16_t RIV2nb_rb_LUT6[32]; -extern uint16_t RIV2first_rb_LUT6[32]; -extern uint16_t RIV2nb_rb_LUT25[512]; -extern uint16_t RIV2first_rb_LUT25[512]; -extern uint16_t RIV2nb_rb_LUT50[1600]; -extern uint16_t RIV2first_rb_LUT50[1600]; -extern uint16_t RIV2nb_rb_LUT100[6000]; -extern uint16_t RIV2first_rb_LUT100[600]; - -extern uint16_t RIV_max6,RIV_max25,RIV_max50,RIV_max100; - -int8_t delta_PUSCH_msg2[8] = {-6,-4,-2,0,2,4,6,8}; +static int8_t delta_PUSCH_msg2[8] = {-6, -4, -2, 0, 2, 4, 6, 8}; int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index e8570a3bbc..cae3a30160 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -409,6 +409,7 @@ static void nr_pusch_antenna_processing(void *arg) *(rdata->noise_amp2) = noise_amp2; *(rdata->nest_count) = nest_count; } + completed_task_ans(rdata->ans); } @@ -503,14 +504,13 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, start_meas(&gNB->pusch_channel_estimation_antenna_processing_stats); int numAntennas = gNB->dmrs_num_antennas_per_thread; int num_jobs = CEILIDIV(gNB->frame_parms.nb_antennas_rx, numAntennas); + puschAntennaProc_t rdatas[num_jobs]; + memset(rdatas, 0, sizeof(rdatas)); + task_ans_t ans[num_jobs]; + memset(ans, 0, sizeof(ans)); for (int job_id = 0; job_id < num_jobs; job_id++) { - union puschAntennaReqUnion id = {.s = {ul_id, 0}}; - id.p = 1 + job_id * numAntennas; - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschAntennaProc_t), - id.p, - &respPuschAarx, - &nr_pusch_antenna_processing); // create a job for Tpool - puschAntennaProc_t *rdata = (puschAntennaProc_t *)NotifiedFifoData(req); // data for the job + puschAntennaProc_t *rdata = &rdatas[job_id]; + task_t task = {.func = nr_pusch_antenna_processing, .args = rdata}; // Local init in the current loop rdata->Ns = Ns; @@ -531,22 +531,18 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, rdata->pusch_vars = &gNB->pusch_vars[ul_id]; rdata->chest_freq = gNB->chest_freq; rdata->rxdataF = gNB->common_vars.rxdataF; + rdata->ans = &ans[job_id]; // Call the nr_pusch_antenna_processing function if (job_id == num_jobs - 1) { // Run the last job inline nr_pusch_antenna_processing(rdata); - delNotifiedFIFO_elt(req); } else { - pushTpool(&gNB->threadPool, req); + pushTpool(&gNB->threadPool, task); } LOG_D(PHY, "Added Antenna (count %d/%d) to process, in pipe\n", job_id, num_jobs); } // Antenna Loop - while (num_jobs - 1 > 0) { - notifiedFIFO_elt_t *req = pullTpool(&respPuschAarx, &gNB->threadPool); - num_jobs--; - delNotifiedFIFO_elt(req); - } + join_task_ans(ans, num_jobs - 1); stop_meas(&gNB->pusch_channel_estimation_antenna_processing_stats); for (int aarx = 0; aarx < gNB->frame_parms.nb_antennas_rx; aarx++) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 7a29c8163a..b66b785b7d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -117,7 +117,7 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) return(dlsch); } -void ldpc8blocks(void *p) +static void ldpc8blocks(void *p) { encoder_implemparams_t *impp=(encoder_implemparams_t *) p; NR_DL_gNB_HARQ_t *harq = (NR_DL_gNB_HARQ_t *)impp->harq; @@ -232,6 +232,9 @@ void ldpc8blocks(void *p) #endif r_offset += E; } + + // Task running in // completed + completed_task_ans(impp->ans); } int nr_dlsch_encoding(PHY_VARS_gNB *gNB, @@ -369,24 +372,23 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, } ldpc_interface_offload.LDPCencoder(harq->c, &impp.output, &impp); } else { - notifiedFIFO_t nf; - initNotifiedFIFO(&nf); - int nbJobs = 0; - for (int j = 0; j < (impp.n_segments / 8 + ((impp.n_segments & 7) == 0 ? 0 : 1)); j++) { - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(impp), j, &nf, ldpc8blocks); - encoder_implemparams_t *perJobImpp = (encoder_implemparams_t *)NotifiedFifoData(req); + size_t const n_seg = (impp.n_segments / 8 + ((impp.n_segments & 7) == 0 ? 0 : 1)); + + encoder_implemparams_t arr[n_seg]; + task_ans_t ans[n_seg]; + memset(ans, 0, n_seg * sizeof(task_ans_t)); + + for (int j = 0; j < n_seg; j++) { + encoder_implemparams_t *perJobImpp = &arr[j]; *perJobImpp = impp; perJobImpp->macro_num = j; - pushTpool(&gNB->threadPool, req); - nbJobs++; - } - while (nbJobs) { - notifiedFIFO_elt_t *req = pullTpool(&nf, &gNB->threadPool); - if (req == NULL) - break; // Tpool has been stopped - delNotifiedFIFO_elt(req); - nbJobs--; + perJobImpp->ans = &ans[j]; + + task_t t = {.func = ldpc8blocks, .args = perJobImpp}; + pushTpool(&gNB->threadPool, t); } + + join_task_ans(ans, n_seg); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT); return 0; diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h index fa7d085ed0..f771d9050a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -62,7 +62,8 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint32_t frame, uint8_t nr_tti_rx, uint8_t harq_pid, - uint32_t G); + uint32_t G, + thread_info_tm_t *t_info); /*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 @param llr, Pointer to llr bits diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 44bb20115d..55c32b48d2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -50,6 +50,10 @@ //#define DEBUG_ULSCH_DECODING //#define gNB_DEBUG_TRACE +#include +#include +#include + #define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384 //#define DEBUG_CRC #ifdef DEBUG_CRC @@ -181,6 +185,9 @@ static void nr_processULSegment(void *arg) LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n"); rdata->decodeIterations = max_ldpc_iterations + 1; set_abort(&ulsch_harq->abort_decode, true); + + // Task completed + completed_task_ans(rdata->ans); return; } @@ -220,6 +227,9 @@ static void nr_processULSegment(void *arg) if (rdata->decodeIterations <= p_decoderParms->numMaxIter) memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3); + + // Task completed + completed_task_ans(rdata->ans); } int decode_offload(PHY_VARS_gNB *phy_vars_gNB, @@ -320,7 +330,8 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint32_t frame, uint8_t nr_tti_rx, uint8_t harq_pid, - uint32_t G) + uint32_t G, + thread_info_tm_t *t_info) { if (!ulsch_llr) { LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n"); @@ -430,9 +441,12 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, set_abort(&harq_process->abort_decode, false); for (int r = 0; r < harq_process->C; r++) { int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); - union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}}; - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, &phy_vars_gNB->respDecode, &nr_processULSegment); - ldpcDecode_t *rdata = (ldpcDecode_t *)NotifiedFifoData(req); + + ldpcDecode_t *rdata = &((ldpcDecode_t *)t_info->buf)[t_info->len]; + DevAssert(t_info->len < t_info->cap); + rdata->ans = &t_info->ans[t_info->len]; + t_info->len += 1; + decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, E, decParams.BG, @@ -457,7 +471,10 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, rdata->ulsch = ulsch; rdata->ulsch_id = ULSCH_id; rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes; - pushTpool(&phy_vars_gNB->threadPool, req); + + task_t t = {.func = &nr_processULSegment, .args = rdata}; + pushTpool(&phy_vars_gNB->threadPool, t); + LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r); r_offset += E; offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 6a57c1eafe..d94e60a9c8 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1179,6 +1179,7 @@ typedef struct puschSymbolProc_s { int16_t *scramblingSequence; uint32_t nvar; int beam_nb; + task_ans_t *ans; } puschSymbolProc_t; static void nr_pusch_symbol_processing(void *arg) @@ -1227,6 +1228,9 @@ static void nr_pusch_symbol_processing(void *arg) for (int i = 0; i < end; i++) llr16[i] = llr_ptr[i] * s[i]; } + + // Task running in // completed + completed_task_ans(rdata->ans); } static uint32_t average_u32(const uint32_t *x, uint16_t size) @@ -1483,8 +1487,13 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, start_meas(&gNB->rx_pusch_symbol_processing_stats); int numSymbols = gNB->num_pusch_symbols_per_thread; - int total_res = 0; + int const loop_iter = rel15_ul->nr_of_symbols / numSymbols; + puschSymbolProc_t arr[loop_iter]; + task_ans_t arr_ans[loop_iter]; + + memset(arr_ans, 0, loop_iter * sizeof(task_ans_t)); + int sz_arr = 0; for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < end_symbol; symbol += numSymbols) { int res_per_task = 0; for (int s = 0; s < numSymbols; s++) { @@ -1496,10 +1505,9 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, } total_res += res_per_task; if (res_per_task > 0) { - union puschSymbolReqUnion id = {.s={ulsch_id,frame,slot,0}}; - id.p=1+symbol; - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschSymbolProc_t), id.p, &gNB->respPuschSymb, &nr_pusch_symbol_processing); // create a job for Tpool - puschSymbolProc_t *rdata = (puschSymbolProc_t*)NotifiedFifoData(req); // data for the job + puschSymbolProc_t *rdata = &arr[sz_arr]; + rdata->ans = &arr_ans[sz_arr]; + ++sz_arr; rdata->gNB = gNB; rdata->frame_parms = frame_parms; @@ -1517,7 +1525,8 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { nr_pusch_symbol_processing(rdata); } else { - pushTpool(&gNB->threadPool, req); + task_t t = {.func = &nr_pusch_symbol_processing, .args = rdata}; + pushTpool(&gNB->threadPool, t); nbSymb++; } @@ -1525,12 +1534,9 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, } } // symbol loop - while (nbSymb) { - notifiedFIFO_elt_t *req = pullTpool(&gNB->respPuschSymb, &gNB->threadPool); - nbSymb--; - delNotifiedFIFO_elt(req); + if (nbSymb > 0) { + join_task_ans(arr_ans, sz_arr); } - stop_meas(&gNB->rx_pusch_symbol_processing_stats); // Copy the data to the scope. This cannot be performed in one call to gNBscopeCopy because the data is not contiguous in the diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 72cb374470..e545766206 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -873,8 +873,8 @@ static simde__m256i pucch2_11bit[2048 * 2]; static simde__m256i *pucch2_lut[9] = {pucch2_3bit, pucch2_4bit, pucch2_5bit, pucch2_6bit, pucch2_7bit, pucch2_8bit, pucch2_9bit, pucch2_10bit, pucch2_11bit}; -simde__m64 pucch2_polar_4bit[16]; -simde__m128i pucch2_polar_llr_num_lut[256],pucch2_polar_llr_den_lut[256]; +static simde__m64 pucch2_polar_4bit[16]; +static simde__m128i pucch2_polar_llr_num_lut[256], pucch2_polar_llr_den_lut[256]; void init_pucch2_luts() { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 58114dfeb5..8285a7036c 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -70,15 +70,13 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid, } static bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, - notifiedFIFO_elt_t *req, - notifiedFIFO_t *nf_p, - const bool last, + ldpcDecode_ue_t *rdata, + bool last, int b_size, uint8_t b[b_size], int *num_seg_ok, const UE_nr_rxtx_proc_t *proc) { - ldpcDecode_ue_t *rdata = (ldpcDecode_ue_t*) NotifiedFifoData(req); NR_DL_UE_HARQ_t *harq_process = rdata->harq_process; NR_UE_DLSCH_t *dlsch = (NR_UE_DLSCH_t *) rdata->dlsch; int r = rdata->segment_r; @@ -257,6 +255,7 @@ static void nr_processDLSegment(void *arg) memcpy(harq_process->c[r], LDPCoutput, Kr >> 3); stop_meas(&rdata->ts_ldpc_decode); } + completed_task_ans(rdata->ans); } uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, @@ -369,16 +368,17 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, Kr = harq_process->K; Kr_bytes = Kr>>3; offset = 0; - notifiedFIFO_t nf; - initNotifiedFIFO(&nf); + + ldpcDecode_ue_t arr[harq_process->C]; + task_ans_t ans[harq_process->C]; + memset(ans, 0, harq_process->C * sizeof(task_ans_t)); set_abort(&harq_process->abort_decode, false); for (r=0; rC; r++) { //printf("start rx segment %d\n",r); uint32_t E = nr_get_E(G, harq_process->C, dlsch->dlsch_config.qamModOrder, dlsch->Nl, r); decParams.R = nr_get_R_ldpc_decoder(dlsch->dlsch_config.rv, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->DLround); - union ldpcReqUnion id = {.s = {dlsch->rnti, frame, nr_slot_rx, 0, 0}}; - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_ue_t), id.p, &nf, &nr_processDLSegment); - ldpcDecode_ue_t * rdata=(ldpcDecode_ue_t *) NotifiedFifoData(req); + ldpcDecode_ue_t *rdata = &arr[r]; + rdata->ans = &ans[r]; rdata->phy_vars_ue = phy_vars_ue; rdata->harq_process = harq_process; @@ -398,7 +398,8 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, reset_meas(&rdata->ts_deinterleave); reset_meas(&rdata->ts_rate_unmatch); reset_meas(&rdata->ts_ldpc_decode); - pushTpool(&get_nrUE_params()->Tpool,req); + task_t t = {.args = rdata, .func = nr_processDLSegment}; + pushTpool(&get_nrUE_params()->Tpool, t); LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r); r_offset += E; offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); @@ -406,13 +407,11 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, } int num_seg_ok = 0; int nbDecode = harq_process->C; - while (nbDecode) { - notifiedFIFO_elt_t *req=pullTpool(&nf, &get_nrUE_params()->Tpool); - if (req == NULL) - break; // Tpool has been stopped - nr_ue_postDecode(phy_vars_ue, req, &nf, nbDecode == 1, b_size, b, &num_seg_ok, proc); - delNotifiedFIFO_elt(req); - nbDecode--; + if (nbDecode > 0) { + join_task_ans(ans, nbDecode); + for (size_t i = 0; i < nbDecode; ++i) { + nr_ue_postDecode(phy_vars_ue, &arr[i], i == nbDecode - 1, b_size, b, &num_seg_ok, proc); + } } LOG_D(PHY, "%d.%d DLSCH Decoded, harq_pid %d, round %d, result: %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d " diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 1d0d85ec54..b6b76ab8a8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -288,6 +288,8 @@ void nr_scan_ssb(void *arg) } } } + + completed_task_ans(ssbInfo->ans); } nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, @@ -299,18 +301,18 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, { NR_DL_FRAME_PARMS *fp = &ue->frame_parms; - notifiedFIFO_t nf; - initNotifiedFIFO(&nf); - // Perform SSB scanning in parallel. One GSCN per thread. LOG_I(NR_PHY, "Starting cell search with center freq: %ld, bandwidth: %d. Scanning for %d number of GSCN.\n", fp->dl_CarrierFreq, fp->N_RB_DL, numGscn); + + task_ans_t ans[numGscn]; + memset(ans, 0, sizeof(ans)); + nr_ue_ssb_scan_t ssb_info[numGscn]; for (int s = 0; s < numGscn; s++) { - notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(nr_ue_ssb_scan_t), gscnInfo[s].gscn, &nf, &nr_scan_ssb); - nr_ue_ssb_scan_t *ssbInfo = (nr_ue_ssb_scan_t *)NotifiedFifoData(req); + nr_ue_ssb_scan_t *ssbInfo = &ssb_info[s]; *ssbInfo = (nr_ue_ssb_scan_t){.gscnInfo = gscnInfo[s], .fp = &ue->frame_parms, .proc = proc, @@ -329,32 +331,34 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, ssbInfo->gscnInfo.gscn, ssbInfo->gscnInfo.ssbFirstSC, ssbInfo->gscnInfo.ssRef); - pushTpool(&get_nrUE_params()->Tpool, req); + ssbInfo->ans = &ans[s]; + task_t t = {.func = nr_scan_ssb, .args = ssbInfo}; + pushTpool(&get_nrUE_params()->Tpool, t); } // Collect the scan results nr_ue_ssb_scan_t res = {0}; - while (numGscn) { - notifiedFIFO_elt_t *req = pullTpool(&nf, &get_nrUE_params()->Tpool); - nr_ue_ssb_scan_t *ssbInfo = (nr_ue_ssb_scan_t *)NotifiedFifoData(req); - if (ssbInfo->syncRes.cell_detected) { - LOG_A(NR_PHY, - "Cell Detected with GSCN: %d, SSB SC offset: %d, SSB Ref: %lf, PSS Corr peak: %d dB, PSS Corr Average: %d\n", - ssbInfo->gscnInfo.gscn, - ssbInfo->gscnInfo.ssbFirstSC, - ssbInfo->gscnInfo.ssRef, - ssbInfo->pssCorrPeakPower, - ssbInfo->pssCorrAvgPower); - if (!res.syncRes.cell_detected) { // take the first cell detected - res = *ssbInfo; + if (numGscn > 0) { + join_task_ans(ans, numGscn); + for (int i = 0; i < numGscn; i++) { + nr_ue_ssb_scan_t *ssbInfo = &ssb_info[i]; + if (ssbInfo->syncRes.cell_detected) { + LOG_I(NR_PHY, + "Cell Detected with GSCN: %d, SSB SC offset: %d, SSB Ref: %lf, PSS Corr peak: %d dB, PSS Corr Average: %d\n", + ssbInfo->gscnInfo.gscn, + ssbInfo->gscnInfo.ssbFirstSC, + ssbInfo->gscnInfo.ssRef, + ssbInfo->pssCorrPeakPower, + ssbInfo->pssCorrAvgPower); + if (!res.syncRes.cell_detected) { // take the first cell detected + res = *ssbInfo; + } } + for (int ant = 0; ant < fp->nb_antennas_rx; ant++) { + free(ssbInfo->rxdata[ant]); + } + free(ssbInfo->rxdata); } - for (int ant = 0; ant < fp->nb_antennas_rx; ant++) { - free(ssbInfo->rxdata[ant]); - } - free(ssbInfo->rxdata); - delNotifiedFIFO_elt(req); - numGscn--; } // Set globals based on detected cell diff --git a/openair1/PHY/TOOLS/CMakeLists.txt b/openair1/PHY/TOOLS/CMakeLists.txt index 574899f3e7..58db255f0c 100644 --- a/openair1/PHY/TOOLS/CMakeLists.txt +++ b/openair1/PHY/TOOLS/CMakeLists.txt @@ -47,10 +47,10 @@ if(ENABLE_UESCOPE OR ENABLE_ENBSCOPE OR ENABLE_NRSCOPE) target_link_libraries(xforms_common PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_library(enbscope MODULE lte_enb_scope.c $) - target_link_libraries(enbscope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) + target_link_libraries(enbscope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL) add_library(uescope MODULE lte_ue_scope.c $) - target_link_libraries(uescope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) + target_link_libraries(uescope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL) add_library(nrscope MODULE nr_phy_scope.c) target_link_libraries(nrscope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL) diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index e3e7df19f4..1b0182bffd 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -39,8 +39,9 @@ #include "time_meas.h" #include "defs_common.h" #include "nfapi_nr_interface_scf.h" -#include #include +#include "common/utils/threadPool/task_ans.h" +#include "common/utils/threadPool/thread-pool.h" #define MAX_BANDS_PER_RRU 4 #define MAX_RRU_CONFIG_SIZE 1024 @@ -175,7 +176,8 @@ typedef struct { struct RU_t_s *ru; int startSymbol; int endSymbol; - int slot; + int slot; + task_ans_t *ans; } feprx_cmd_t; typedef struct { @@ -184,6 +186,7 @@ typedef struct { int slot; int startSymbol; int numSymbols; + task_ans_t *ans; } feptx_cmd_t; typedef struct { @@ -426,7 +429,7 @@ typedef enum { typedef struct RU_t_s { - /// ThreadPool for RU + /// ThreadPool for RU tpool_t *threadPool; /// index of this ru uint32_t idx; diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index a10956114a..68ebf65462 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -66,7 +66,7 @@ #include "PHY/LTE_TRANSPORT/transport_eNB.h" #include "openair2/PHY_INTERFACE/IF_Module.h" #include "common/openairinterface5g_limits.h" - +#include "common/utils/threadPool/task_ans.h" #define PBCH_A 24 #define MAX_NUM_RU_PER_eNB 64 @@ -786,6 +786,7 @@ typedef struct TurboDecode_s { int offset; int maxIterations; int decodeIterations; + task_ans_t *ans; } turboDecode_t; #define TURBO_SIMD_SOFTBITS 96+12+3+3*6144 @@ -802,6 +803,7 @@ typedef struct turboEncode_s { time_stats_t *rm_stats; time_stats_t *te_stats; time_stats_t *i_stats; + task_ans_t *ans; } turboEncode_t; diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 81d193634a..f6e6559414 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -575,7 +575,7 @@ typedef struct PHY_VARS_gNB_s { struct processingData_L1tx *msgDataTx; void *scopeData; /// structure for analyzing high-level RT measurements - rt_L1_profiling_t rt_L1_profiling; + rt_L1_profiling_t rt_L1_profiling; } PHY_VARS_gNB; struct puschSymbolReqId { @@ -609,6 +609,7 @@ typedef struct puschAntennaProc_s { NR_gNB_PUSCH *pusch_vars; NR_DL_FRAME_PARMS *frame_parms; c16_t ***rxdataF; + task_ans_t* ans; } puschAntennaProc_t; struct puschAntennaReqId { @@ -641,6 +642,7 @@ typedef struct LDPCDecode_s { int offset; int decodeIterations; uint32_t tbslbrm; + task_ans_t *ans; } ldpcDecode_t; struct ldpcReqId { @@ -661,6 +663,7 @@ typedef struct processingData_L1 { int slot_rx; openair0_timestamp timestamp_tx; PHY_VARS_gNB *gNB; + notifiedFIFO_elt_t *elt; } processingData_L1_t; typedef struct processingData_L1tx { diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 182450f0e7..774309831c 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -576,6 +576,7 @@ typedef struct { int pssCorrPeakPower; int pssCorrAvgPower; int adjust_rxgain; + task_ans_t *ans; } nr_ue_ssb_scan_t; typedef struct nr_phy_data_tx_s { @@ -632,6 +633,7 @@ typedef struct LDPCDecode_ue_s { time_stats_t ts_deinterleave; time_stats_t ts_rate_unmatch; time_stats_t ts_ldpc_decode; + task_ans_t *ans; } ldpcDecode_ue_t; static inline void start_meas_nr_ue_phy(PHY_VARS_NR_UE *ue, int meas_index) { diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 15208998ae..db68730c33 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1232,10 +1232,8 @@ uci_procedures(PHY_VARS_eNB *eNB, } // end loop for (int i = 0; i < NUMBER_OF_UCI_MAX; i++) { } -void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) +void postDecode(L1_rxtx_proc_t *proc, turboDecode_t *rdata) { - turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req); - LTE_eNB_ULSCH_t *ulsch = rdata->eNB->ulsch[rdata->UEid]; LTE_UL_eNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; PHY_VARS_eNB *eNB=rdata->eNB; @@ -1330,6 +1328,10 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { const int frame = proc->frame_rx; uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); + turboDecode_t arr[64] = {0}; + task_ans_t ans[64] = {0}; + thread_info_tm_t t_info = {.ans = ans, .cap = 64, .len = 0, .buf = (uint8_t *)arr}; + for (i = 0; i < NUMBER_OF_ULSCH_MAX; i++) { ulsch = eNB->ulsch[i]; if (!ulsch) continue; @@ -1398,7 +1400,8 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { i, 0, // control_only_flag ulsch_harq->V_UL_DAI, - ulsch_harq->nb_rb > 20 ? 1 : 0); + ulsch_harq->nb_rb > 20 ? 1 : 0, + &t_info); } else if ((ulsch) && (ulsch->rnti>0) && @@ -1415,14 +1418,12 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { } // for (i=0; inbDecode; - while (proc->nbDecode > 0) { - notifiedFIFO_elt_t *req=pullTpool(proc->respDecode, proc->threadPool); - if (req == NULL) - break; // Tpool has been stopped - postDecode(proc, req); - const time_stats_t ts = exec_time_stats_NotifiedFIFO(req); - merge_meas(&eNB->ulsch_turbo_decoding_stats, &ts); - delNotifiedFIFO_elt(req); + DevAssert(t_info.len == proc->nbDecode); + if (proc->nbDecode > 0) { + join_task_ans(t_info.ans, t_info.len); + for (size_t i = 0; i < t_info.len; ++i) { + postDecode(proc, &arr[i]); + } } if (decode) stop_meas(&eNB->ulsch_decoding_stats); diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index 475bbed493..7a0b21ace7 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -289,47 +289,59 @@ void nr_feptx(void *arg) ////////////FEPTX//////////// nr_feptx0(ru, slot, startSymbol, numSymbols, aa); + + // Task completed in // + completed_task_ans(feptx->ans); } // RU FEP TX using thread-pool void nr_feptx_tp(RU_t *ru, int frame_tx, int slot) { nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config; - int nbfeptx = 0; if (nr_slot_select(cfg, frame_tx, slot) == NR_UPLINK_SLOT) return; if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM, 1); start_meas(&ru->ofdm_total_stats); + + size_t const sz = ru->nb_tx + (ru->half_slot_parallelization > 0) * ru->nb_tx; + AssertFatal(sz < 64, "Please, increase the buffer size"); + feptx_cmd_t arr[64] = {0}; + task_ans_t ans[64] = {0}; + + int nbfeptx = 0; for (int aid = 0; aid < ru->nb_tx; aid++) { - notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(feptx_cmd_t), 2000 + aid, ru->respfeptx, nr_feptx); - feptx_cmd_t *feptx_cmd = (feptx_cmd_t*)NotifiedFifoData(req); + feptx_cmd_t *feptx_cmd = &arr[nbfeptx]; + feptx_cmd->ans = &ans[nbfeptx]; + feptx_cmd->aid = aid; feptx_cmd->ru = ru; feptx_cmd->slot = slot; feptx_cmd->startSymbol = 0; - feptx_cmd->numSymbols = (ru->half_slot_parallelization > 0) ? - ru->nr_frame_parms->symbols_per_slot >> 1 : - ru->nr_frame_parms->symbols_per_slot; - pushTpool(ru->threadPool, req); + feptx_cmd->numSymbols = + (ru->half_slot_parallelization > 0) ? ru->nr_frame_parms->symbols_per_slot >> 1 : ru->nr_frame_parms->symbols_per_slot; + + task_t t = {.func = nr_feptx, .args = feptx_cmd}; + pushTpool(ru->threadPool, t); nbfeptx++; if (ru->half_slot_parallelization > 0) { - notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(feptx_cmd_t), 2000 + aid + ru->nb_tx, ru->respfeptx, nr_feptx); - feptx_cmd_t *feptx_cmd = (feptx_cmd_t*)NotifiedFifoData(req); + feptx_cmd_t *feptx_cmd = &arr[nbfeptx]; + feptx_cmd->ans = &ans[nbfeptx]; + feptx_cmd->aid = aid; feptx_cmd->ru = ru; feptx_cmd->slot = slot; feptx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot >> 1; feptx_cmd->numSymbols = ru->nr_frame_parms->symbols_per_slot >> 1; - pushTpool(ru->threadPool, req); + + task_t t = {.func = nr_feptx, .args = feptx_cmd}; + pushTpool(ru->threadPool, t); nbfeptx++; } } - while (nbfeptx > 0) { - notifiedFIFO_elt_t *req=pullTpool(ru->respfeptx, ru->threadPool); - delNotifiedFIFO_elt(req); - nbfeptx--; - } + + join_task_ans(ans, nbfeptx); + stop_meas(&ru->ofdm_total_stats); if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM, 0); @@ -359,6 +371,9 @@ void nr_fep(void* arg) tti_rx, ru->N_TA_offset); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+aid, 0); + + // Task completed in // + completed_task_ans(feprx_cmd->ans); } // RU RX FEP using thread-pool @@ -367,33 +382,45 @@ void nr_fep_tp(RU_t *ru, int slot) { int nbfeprx=0; if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 ); start_meas(&ru->ofdm_demod_stats); + + size_t const sz = ru->nb_rx + (ru->half_slot_parallelization > 0) * ru->nb_rx; + AssertFatal(sz < 64, "Please, increase buffer size"); + feprx_cmd_t arr[64] = {0}; + task_ans_t ans[64] = {0}; + for (int aid=0;aidnb_rx;aid++) { - notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(feprx_cmd_t), 1000 + aid,ru->respfeprx,nr_fep); - feprx_cmd_t *feprx_cmd=(feprx_cmd_t*)NotifiedFifoData(req); - feprx_cmd->aid = aid; - feprx_cmd->ru = ru; - feprx_cmd->slot = ru->proc.tti_rx; - feprx_cmd->startSymbol = 0; - feprx_cmd->endSymbol = (ru->half_slot_parallelization > 0)?(ru->nr_frame_parms->symbols_per_slot>>1)-1:(ru->nr_frame_parms->symbols_per_slot-1); - pushTpool(ru->threadPool,req); - nbfeprx++; - if (ru->half_slot_parallelization>0) { - notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(feprx_cmd_t), 1000 + aid + ru->nb_rx,ru->respfeprx,nr_fep); - feprx_cmd_t *feprx_cmd=(feprx_cmd_t*)NotifiedFifoData(req); - feprx_cmd->aid = aid; - feprx_cmd->ru = ru; - feprx_cmd->slot = ru->proc.tti_rx; - feprx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot>>1; - feprx_cmd->endSymbol = ru->nr_frame_parms->symbols_per_slot-1; - pushTpool(ru->threadPool,req); - nbfeprx++; - } - } - while (nbfeprx>0) { - notifiedFIFO_elt_t *req=pullTpool(ru->respfeprx, ru->threadPool); - delNotifiedFIFO_elt(req); - nbfeprx--; + feprx_cmd_t *feprx_cmd = &arr[nbfeprx]; + feprx_cmd->ans = &ans[nbfeprx]; + + feprx_cmd->aid = aid; + feprx_cmd->ru = ru; + feprx_cmd->slot = ru->proc.tti_rx; + feprx_cmd->startSymbol = 0; + feprx_cmd->endSymbol = (ru->half_slot_parallelization > 0) ? (ru->nr_frame_parms->symbols_per_slot >> 1) - 1 + : (ru->nr_frame_parms->symbols_per_slot - 1); + + task_t t = {.func = nr_fep, .args = feprx_cmd}; + pushTpool(ru->threadPool, t); + nbfeprx++; + if (ru->half_slot_parallelization > 0) { + feprx_cmd_t *feprx_cmd = &arr[nbfeprx]; + feprx_cmd->ans = &ans[nbfeprx]; + + feprx_cmd->aid = aid; + feprx_cmd->ru = ru; + feprx_cmd->slot = ru->proc.tti_rx; + feprx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot >> 1; + feprx_cmd->endSymbol = ru->nr_frame_parms->symbols_per_slot - 1; + + task_t t = {.func = nr_fep, .args = feprx_cmd}; + pushTpool(ru->threadPool, t); + + nbfeprx++; + } } + + join_task_ans(ans, nbfeprx); + stop_meas(&ru->ofdm_demod_stats); if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 0 ); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 221e463408..7b3a82c7ce 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -39,6 +39,7 @@ #include "nfapi/oai_integration/vendor_ext.h" #include "assertions.h" #include +#include //#define DEBUG_RXDATA //#define SRS_IND_DEBUG @@ -304,9 +305,8 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX + gNB->CC_id, 0); } -static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) +static void nr_postDecode(PHY_VARS_gNB *gNB, ldpcDecode_t *rdata) { - ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req); NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; NR_gNB_ULSCH_t *ulsch = rdata->ulsch; int r = rdata->segment_r; @@ -415,7 +415,12 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) } } -static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid) +static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, + int frame_rx, + int slot_rx, + int ULSCH_id, + uint8_t harq_pid, + thread_info_tm_t *t_info) { NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu; @@ -466,9 +471,17 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int * measurement per processed TB.*/ if (gNB->max_nb_pusch == 1) start_meas(&gNB->ulsch_decoding_stats); - int nbDecode = - nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G); + int const nbDecode = nr_ulsch_decoding(gNB, + ULSCH_id, + gNB->pusch_vars[ULSCH_id].llr, + frame_parms, + pusch_pdu, + frame_rx, + slot_rx, + harq_pid, + G, + t_info); return nbDecode; } @@ -827,6 +840,11 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) } } + ldpcDecode_t arr[64]; + task_ans_t ans[64] = {0}; + thread_info_tm_t t_info = {.buf = (uint8_t *)arr, .len = 0, .cap = 64, .ans = ans}; + + // int64_t const t0 = time_now_ns(); int totalDecode = 0; for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; @@ -924,21 +942,20 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) // LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1); // LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 1); - int const tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid); + int const tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, &t_info); if (tasks_added > 0) totalDecode += tasks_added; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0); } } - while (totalDecode > 0) { - notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool); - if (req == NULL) - break; // Tpool has been stopped - nr_postDecode(gNB, req); - delNotifiedFIFO_elt(req); - totalDecode--; - } + + DevAssert(totalDecode == t_info.len); + + join_task_ans(t_info.ans, t_info.len); + for (int i = 0; i < t_info.len; ++i) { + nr_postDecode(gNB, &arr[i]); + } /* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1 * (valid for unitary physical simulators). ULSCH processing loop is then executed * only once, which ensures exactly one start and stop of the ULSCH decoding time diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index aab41da209..664a293a96 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -409,6 +409,8 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, rxdataF); if (ret==0) { + T(T_NRUE_PHY_MIB, T_INT(frame_rx), T_INT(nr_slot_rx), + T_INT(ssb_index), T_BUFFER(result.decoded_output, 3)); #ifdef DEBUG_PHY_PROC LOG_D(PHY, diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index 6aebb80dac..da02d13be1 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -661,6 +661,7 @@ int main(int argc, char **argv) free(gNB->gNB_config.tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list); free(gNB->gNB_config.tdd_table.max_tdd_periodicity_list); + abortTpool(&gNB->threadPool); phy_free_nr_gNB(gNB); free(RC.gNB[0]); free(RC.gNB); diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 306e882ebf..f578e217e9 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -45,7 +45,6 @@ #include "openair1/SIMULATION/TOOLS/sim.h" #include "openair1/SIMULATION/RF/rf.h" #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" -#include "common/utils/threadPool/thread-pool.h" #include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h" #include "executables/nr-uesoftmodem.h" #include "nfapi/oai_integration/vendor_ext.h" @@ -91,9 +90,8 @@ void deref_sched_response(int _) exit(1); } -int nr_postDecode_sim(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req, int *nb_ok) +int nr_postDecode_sim(PHY_VARS_gNB *gNB, ldpcDecode_t *rdata, int *nb_ok) { - ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req); NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; int r = rdata->segment_r; @@ -107,8 +105,10 @@ int nr_postDecode_sim(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req, int *nb_ok) } // if all segments are done - if (rdata->nbSegments == ulsch_harq->processedSegments) + if (rdata->nbSegments == ulsch_harq->processedSegments) { return *nb_ok == rdata->nbSegments; + } + return 0; } @@ -594,20 +594,23 @@ int main(int argc, char **argv) exit(-1); #endif - int nbDecode = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G); - int nb_ok = 0; - if (nbDecode > 0) - while (nbDecode > 0) { - notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool); - ret = nr_postDecode_sim(gNB, req, &nb_ok); - delNotifiedFIFO_elt(req); - nbDecode--; - } + ldpcDecode_t arr[16] = {0}; + task_ans_t ans[16] = {0}; + thread_info_tm_t t_info = {.buf = (uint8_t *)arr, .cap = 16, .len = 0, .ans = ans}; + int nbDecode = + nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G, &t_info); + DevAssert(nbDecode > 0); + int nb_ok = 0; + join_task_ans(t_info.ans, t_info.len); + for (size_t i = 0; i < nbDecode; ++i) { + ret = nr_postDecode_sim(gNB, &arr[i], &nb_ok); + } + nbDecode = 0; if (ret) n_errors++; } - + printf("*****************************************\n"); printf("SNR %f, BLER %f (false positive %f)\n", SNR, (float) n_errors / (float) n_trials, @@ -633,6 +636,7 @@ int main(int argc, char **argv) term_nr_ue_signal(UE, 1); free(UE); + abortTpool(&gNB->threadPool); phy_free_nr_gNB(gNB); free(RC.gNB[0]); free(RC.gNB); diff --git a/openair1/SIMULATION/TOOLS/DOC/channel_simulation.md b/openair1/SIMULATION/TOOLS/DOC/channel_simulation.md index 347f575bfb..070ee61ca0 100644 --- a/openair1/SIMULATION/TOOLS/DOC/channel_simulation.md +++ b/openair1/SIMULATION/TOOLS/DOC/channel_simulation.md @@ -1,5 +1,13 @@ [[_TOC_]] +This document is complementary to the [RFSIMULATOR Tutorial](../../../../radio/rfsimulator/README.md). + +# Channel Modeling + +Channel models in the context of wireless communication refer to mathematical models that simulate the effects of transmission mediums on signal propagation. These models account for factors such as attenuation, interference, and fading, which can affect the quality of communication between transmitter and receiver. + +Different channel models represent different real-world scenarios, such as urban environments, indoor spaces, or rural areas. By using these models, researchers and engineers can predict and evaluate the performance of wireless systems under various conditions. + # OAI channel simulation feature OpenAirInterface RFSimulator incorporates a channel simulation feature. This feature allows any component to modify the time domain samples of a RF channel. It achieves this by applying predefined models, such as those defined in 3GPP TR 36.873 or TR 38.901. @@ -8,7 +16,6 @@ The definition, configuration, and real-time modification of a channel model are The RFSimulator is the exclusive option that provides access to all the configuration and real-time modification features of OAI's channel simulation. This makes it a comprehensive tool for managing and manipulating channel simulations in OAI. - # Implementation OAI channel simulation is using the [config module](../../../../common/config/DOC/config.md) to get its parameters at init time. The [telnet server](../../../../common/utils/telnetsrv/DOC/telnetsrv.md) includes a set of commands which can be used to dynamically modify some channel model parameters. @@ -39,13 +46,22 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, # Channel Model configuration file -To define and use a channel model for uplink, the gNB configuration file needs to include a channel configuration file. To do this, add `@include "channelmod_rfsimu.conf"` at the end of the gNB configuration file, and place the channel configuration file in the same directory. The same shall be done for downlink by including the channel model configuration file at the end of UE configuration file (e.g. [`ci-scripts/conf_files/nrue.uicc.conf`](../../../../ci-scripts/conf_files/nrue.uicc.conf)). +To define and use a channel model for uplink, the gNB configuration file needs to include a channel configuration file. To do this, add: + +```bash +@include "channelmod_rfsimu.conf" +``` + +at the end of the gNB configuration file, and place the channel configuration file in the same directory. The same shall be done for downlink by including the channel model configuration file at the end of UE configuration file. E.g. + +* nrUE [`ci-scripts/conf_files/nrue.uicc.conf`](../../../../ci-scripts/conf_files/nrue.uicc.conf) +* gNB [gnb.sa.band78.106prb.rfsim.conf](../../../../ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf) All channel simulation parameters are defined in the `channelmod` section. Most parameters are specific to a channel model and are only used by the rfsimulator. An example of the configuration file can be found here: * [`ci-scripts/conf_files/channelmod_rfsimu.conf`](../../../../ci-scripts/conf_files/channelmod_rfsimu.conf) -e.g.: +e.g. a simple scenario to with an AWGN channel: ```bash channelmod = { @@ -76,6 +92,29 @@ channelmod = { where `rfsimu_channel_ue0` will be activated on server side (i.e. eNB/gNB) for uplink and `rfsimu_channel_enB0` will be activated on client side (i.e. UE) for downlink. +## Edit the configuration file + +How simulate noise of a AWGN channel? Starting from the configuration file in the previous section, in the `rfsimu_channel_enB0` model part, set the noise power to: + +```bash + noise_power_dB = -10 +``` + +In the `rfsimu_channel_ue0` model part, set the noise power to: +```bash + noise_power_dB = -20; +``` + +and the rest of the `channelmod_rfsimu.conf` remains unchanged. + +## Monitoring by nr-scope + +In order to verify the effects of the changes introduced by the channel simulation, the `nr-scope` constellation tool can be used to track and analyze the modulation constellation points. This tool allows users to visualize the modulation scheme being used and assess the quality of the received signals. By observing the constellation points, users can verify whether the changes made to the system configuration have resulted in. + +# Build the telnet server library + +Please refer to this documentation [telnetusage.md](../../../../common/utils/telnetsrv/DOC/telnetusage.md). + # Run OAI with a channel model When the `chanmod` option is enabled, the RF channel simulator with a channel modeling function is called. Add the following options to the command line to enable the channel model: diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c index 984c3de887..330d29567a 100644 --- a/openair2/E1AP/e1ap_common.c +++ b/openair2/E1AP/e1ap_common.c @@ -55,7 +55,7 @@ void createE1inst(E1_t type, instance_t instance, uint64_t gnb_id, e1ap_net_conf e1ap_inst[instance]->gtpInstF1U = -1; } -E1AP_TransactionID_t transacID[E1AP_MAX_NUM_TRANSAC_IDS] = {0}; +static E1AP_TransactionID_t transacID[E1AP_MAX_NUM_TRANSAC_IDS] = {0}; void e1ap_common_init() { srand(time(NULL)); diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 4fcebc957e..571d008e84 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -210,7 +210,7 @@ void *eNB_app_task(void *args_p) { itti_mark_task_ready (TASK_ENB_APP); /* Try to register each eNB */ - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { register_enb_pending = eNB_app_register(enb_id_start, enb_id_end); } @@ -248,67 +248,81 @@ void *eNB_app_task(void *args_p) { break; case S1AP_REGISTER_ENB_CNF: - if (EPC_MODE_ENABLED) { - LOG_I(ENB_APP, "[eNB %ld] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), - S1AP_REGISTER_ENB_CNF(msg_p).nb_mme); - register_enb_pending--; + if (!IS_SOFTMODEM_NOS1) { + LOG_I(ENB_APP, + "[eNB %ld] Received %s: associated MME %d\n", + instance, + ITTI_MSG_NAME(msg_p), + S1AP_REGISTER_ENB_CNF(msg_p).nb_mme); + register_enb_pending--; - /* Check if at least eNB is registered with one MME */ - if (S1AP_REGISTER_ENB_CNF(msg_p).nb_mme > 0) { - registered_enb++; - } + /* Check if at least eNB is registered with one MME */ + if (S1AP_REGISTER_ENB_CNF(msg_p).nb_mme > 0) { + registered_enb++; + } - /* Check if all register eNB requests have been processed */ - if (register_enb_pending == 0) { - if (registered_enb == enb_nb) { - /* If all eNB are registered, start L2L1 task */ - MessageDef *msg_init_p; - msg_init_p = itti_alloc_new_message (TASK_ENB_APP, 0, INITIALIZE_MESSAGE); - itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); - } else { - LOG_W(ENB_APP, " %d eNB not associated with a MME, retrying registration in %d seconds ...\n", - enb_nb - registered_enb, ENB_REGISTER_RETRY_DELAY); + /* Check if all register eNB requests have been processed */ + if (register_enb_pending == 0) { + if (registered_enb == enb_nb) { + /* If all eNB are registered, start L2L1 task */ + MessageDef *msg_init_p; + msg_init_p = itti_alloc_new_message(TASK_ENB_APP, 0, INITIALIZE_MESSAGE); + itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); + } else { + LOG_W(ENB_APP, + " %d eNB not associated with a MME, retrying registration in %d seconds ...\n", + enb_nb - registered_enb, + ENB_REGISTER_RETRY_DELAY); - /* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */ - if (timer_setup (ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT, - NULL, &enb_register_retry_timer_id) < 0) { - LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n"); - sleep(ENB_REGISTER_RETRY_DELAY); - /* Restart the registration process */ - registered_enb = 0; - register_enb_pending = eNB_app_register(enb_id_start, enb_id_end); - } + /* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */ + if (timer_setup(ENB_REGISTER_RETRY_DELAY, + 0, + TASK_ENB_APP, + INSTANCE_DEFAULT, + TIMER_ONE_SHOT, + NULL, + &enb_register_retry_timer_id) + < 0) { + LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n"); + sleep(ENB_REGISTER_RETRY_DELAY); + /* Restart the registration process */ + registered_enb = 0; + register_enb_pending = eNB_app_register(enb_id_start, enb_id_end); } } - } /* if (EPC_MODE_ENABLED) */ + } + } /* if ((!IS_SOFTMODEM_NOS1)) */ break; case S1AP_DEREGISTERED_ENB_IND: - if (EPC_MODE_ENABLED) { - LOG_W(ENB_APP, "[eNB %ld] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), - S1AP_DEREGISTERED_ENB_IND(msg_p).nb_mme); - /* TODO handle recovering of registration */ + if (!IS_SOFTMODEM_NOS1) { + LOG_W(ENB_APP, + "[eNB %ld] Received %s: associated MME %d\n", + instance, + ITTI_MSG_NAME(msg_p), + S1AP_DEREGISTERED_ENB_IND(msg_p).nb_mme); + /* TODO handle recovering of registration */ } break; case TIMER_HAS_EXPIRED: - if (EPC_MODE_ENABLED) { - LOG_I(ENB_APP, " Received %s: timer_id %ld\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id); + if (!IS_SOFTMODEM_NOS1) { + LOG_I(ENB_APP, " Received %s: timer_id %ld\n", ITTI_MSG_NAME(msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id); - if (TIMER_HAS_EXPIRED (msg_p).timer_id == enb_register_retry_timer_id) { - /* Restart the registration process */ - registered_enb = 0; - register_enb_pending = eNB_app_register(enb_id_start, enb_id_end); - } + if (TIMER_HAS_EXPIRED(msg_p).timer_id == enb_register_retry_timer_id) { + /* Restart the registration process */ + registered_enb = 0; + register_enb_pending = eNB_app_register(enb_id_start, enb_id_end); + } - if (TIMER_HAS_EXPIRED (msg_p).timer_id == x2_enb_register_retry_timer_id) { - /* Restart the registration process */ - x2_registered_enb = 0; - x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end); - } - } /* if (EPC_MODE_ENABLED) */ + if (TIMER_HAS_EXPIRED(msg_p).timer_id == x2_enb_register_retry_timer_id) { + /* Restart the registration process */ + x2_registered_enb = 0; + x2_register_enb_pending = eNB_app_register_x2(enb_id_start, enb_id_end); + } + } /* if ((!IS_SOFTMODEM_NOS1)) */ // if(TIMER_HAS_EXPIRED (msg_p).timer_id == m2_enb_register_retry_timer_id) { // diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 2f775f504e..9d0d81cfc8 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -295,7 +295,7 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc) { if (ENBParamList.paramarray[i][ENB_ENB_ID_IDX].uptr == NULL) { // Calculate a default eNB ID - if (EPC_MODE_ENABLED) { + if ((!IS_SOFTMODEM_NOS1)) { uint32_t hash; hash = s1ap_generate_eNB_id (); enb_id = i + (hash & 0xFFFF8); @@ -1892,7 +1892,7 @@ int RCconfig_M2(MessageDef *msg_p, uint32_t i) { for (k = 0; k < ENBParamList.numelt; k++) { if (ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr == NULL) { // Calculate a default eNB ID - if (EPC_MODE_ENABLED) { + if ((!IS_SOFTMODEM_NOS1)) { uint32_t hash; hash = s1ap_generate_eNB_id (); enb_id = k + (hash & 0xFFFF8); @@ -2072,7 +2072,7 @@ int RCconfig_M2(MessageDef *msg_p, uint32_t i) { M2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS; M2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS; - if (EPC_MODE_ENABLED) { + if ((!IS_SOFTMODEM_NOS1)) { sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_SCTP_CONFIG); config_get(config_get_if(), SCTPParams, sizeofArray(SCTPParams), aprefix); M2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[ENB_SCTP_INSTREAMS_IDX].uptr); @@ -2140,7 +2140,7 @@ int RCconfig_S1( for (int k = 0; k < ENBParamList.numelt; k++) { if (ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr == NULL) { // Calculate a default eNB ID - if (EPC_MODE_ENABLED) { + if ((!IS_SOFTMODEM_NOS1)) { uint32_t hash = 0; hash = s1ap_generate_eNB_id(); enb_id = k + (hash & 0xFFFF8); @@ -2374,7 +2374,7 @@ int RCconfig_S1( S1AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS; S1AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS; - if (EPC_MODE_ENABLED) { + if ((!IS_SOFTMODEM_NOS1)) { sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_SCTP_CONFIG); config_get(config_get_if(), SCTPParams, sizeofArray(SCTPParams), aprefix); S1AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[ENB_SCTP_INSTREAMS_IDX].uptr); @@ -2432,7 +2432,7 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) { for (k = 0; k < ENBParamList.numelt; k++) { if (ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr == NULL) { // Calculate a default eNB ID - if (EPC_MODE_ENABLED) { + if ((!IS_SOFTMODEM_NOS1)) { uint32_t hash; hash = s1ap_generate_eNB_id (); enb_id = k + (hash & 0xFFFF8); @@ -2584,7 +2584,7 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) { X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS; X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS; - if (EPC_MODE_ENABLED) { + if ((!IS_SOFTMODEM_NOS1)) { sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_SCTP_CONFIG); config_get(config_get_if(), SCTPParams, sizeofArray(SCTPParams), aprefix); X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[ENB_SCTP_INSTREAMS_IDX].uptr); @@ -2659,7 +2659,7 @@ void RCConfig(void) { /* get global parameters, defined outside any section in the config file */ printf("Getting ENBSParams\n"); config_get(config_get_if(), ENBSParams, sizeofArray(ENBSParams), NULL); - //EPC_MODE_ENABLED = ((*ENBSParams[ENB_NOS1_IDX].uptr) == 0); + //(!IS_SOFTMODEM_NOS1) = ((*ENBSParams[ENB_NOS1_IDX].uptr) == 0); RC.nb_inst = ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt; if (RC.nb_inst > 0) { diff --git a/openair2/F1AP/f1ap_encoder.c b/openair2/F1AP/f1ap_encoder.c index 5de4ba43db..4760168e76 100644 --- a/openair2/F1AP/f1ap_encoder.c +++ b/openair2/F1AP/f1ap_encoder.c @@ -26,7 +26,7 @@ #include "f1ap_common.h" #include "f1ap_encoder.h" -int asn1_encoder_xer_print = 0; +static int asn1_encoder_xer_print = 0; int f1ap_encode_pdu(F1AP_F1AP_PDU_t *pdu, uint8_t **buffer, uint32_t *length) { ssize_t encoded; diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 48fb32de8d..71366105fc 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -41,6 +41,7 @@ #include "common/ran_context.h" #include "intertask_interface.h" #include +#include "common/utils/system.h" extern RAN_CONTEXT_t RC; extern int oai_exit; diff --git a/openair2/LAYER2/MAC/main_ue.c b/openair2/LAYER2/MAC/main_ue.c index e67d85dd36..bed2aa5b09 100644 --- a/openair2/LAYER2/MAC/main_ue.c +++ b/openair2/LAYER2/MAC/main_ue.c @@ -44,6 +44,7 @@ #include "PHY_INTERFACE/phy_stub_UE.h" #include "common/ran_context.h" #include +#include "executables/softmodem-common.h" extern void openair_rrc_top_init_ue( int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active); @@ -51,7 +52,7 @@ void dl_phy_sync_success(module_id_t module_idP, frame_t frameP, unsigned char e LOG_D(MAC, "[UE %d] Frame %d: PHY Sync to eNB_index %d successful \n", module_idP, frameP, eNB_index); - if (first_sync == 1 && !(EPC_MODE_ENABLED)) { + if (first_sync == 1 && IS_SOFTMODEM_NOS1) { //layer2_init_UE(module_idP); openair_rrc_ue_init(module_idP, eNB_index); } else { diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 04304f8b9a..6ce41a30ea 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -427,12 +427,24 @@ typedef struct { #define DL_SCH_LCID_CON_RES_ID 0x3E #define DL_SCH_LCID_PADDING 0x3F -#define UL_SCH_LCID_CCCH1 0x00 +#define UL_SCH_LCID_CCCH_64_BITS 0x00 #define UL_SCH_LCID_SRB1 0x01 #define UL_SCH_LCID_SRB2 0x02 #define UL_SCH_LCID_SRB3 0x03 #define UL_SCH_LCID_DTCH 0x04 -#define UL_SCH_LCID_CCCH 0x34 +#define UL_SCH_LCID_EXTENDED_LCID_2_OCT 0x21 +#define UL_SCH_LCID_EXTENDED_LCID_1_OCT 0x22 +#define UL_SCH_LCID_CCCH_48_BITS_REDCAP 0x23 +#define UL_SCH_LCID_CCCH_64_BITS_REDCAP 0x24 +#define UL_SCH_LCID_TRUNCATED_ENHANCED_BFR 0x2B +#define UL_SCH_LCID_TIMING_ADVANCE_REPORT 0x2C +#define UL_SCH_LCID_TRUNCATED_SIDELINK_BSR 0x2D +#define UL_SCH_LCID_SIDELINK_BSR 0x2E +#define UL_SCH_LCID_LBT_FAILURE_4_OCT 0x30 +#define UL_SCH_LCID_LBT_FAILURE_1_OCT 0x31 +#define UL_SCH_LCID_BFR 0x32 +#define UL_SCH_LCID_TRUNCATED_BFR 0x33 +#define UL_SCH_LCID_CCCH_48_BITS 0x34 #define UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY 0x35 #define UL_SCH_LCID_MULTI_ENTRY_PHR_4_OCT 0x36 #define UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION 0x37 diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 26fcd95757..3eabec0249 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -656,7 +656,7 @@ static uint8_t *fill_msg3_pdu_from_rlc(NR_UE_MAC_INST_t *mac, uint8_t *pdu, int { RA_config_t *ra = &mac->ra; // regular Msg3/MsgA_PUSCH with PDU coming from higher layers - *(NR_MAC_SUBHEADER_FIXED *)pdu = (NR_MAC_SUBHEADER_FIXED){.LCID = UL_SCH_LCID_CCCH}; + *(NR_MAC_SUBHEADER_FIXED *)pdu = (NR_MAC_SUBHEADER_FIXED){.LCID = UL_SCH_LCID_CCCH_48_BITS}; pdu += sizeof(NR_MAC_SUBHEADER_FIXED); tbs_size_t len = mac_rlc_data_req(mac->ue_id, mac->ue_id, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 5376d85ef8..5808cf3dcb 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -301,6 +301,12 @@ int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); mac->get_sib1 = false; mac->get_otherSI = false; + T(T_NRUE_MAC_DL_PDU_WITH_DATA, + T_INT(SI_RNTI), + T_INT(-1 /* frame, unavailable here */), + T_INT(-1 /* slot, unavailable here */), + T_INT(0 /* harq_pid */), + T_BUFFER(pduP, pdu_len)); } else LOG_E(NR_MAC, "Got NACK on NR-BCCH-DL-SCH-Message (%s)\n", mac->get_sib1 ? "SIB1" : "other SI"); @@ -3588,8 +3594,9 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i { frame_t frameP = dl_info->frame; int slot = dl_info->slot; - uint8_t *pduP = (dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu; - int32_t pdu_len = (int32_t)(dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu_length; + fapi_nr_pdsch_pdu_t *pdsch_pdu = &(dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu; + uint8_t *pduP = pdsch_pdu->pdu; + int32_t pdu_len = (int32_t)pdsch_pdu->pdu_length; uint8_t gNB_index = dl_info->gNB_index; uint8_t CC_id = dl_info->cc_id; uint8_t done = 0; @@ -3599,6 +3606,8 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i return; } + T(T_NRUE_MAC_DL_PDU_WITH_DATA, T_INT(mac->crnti), T_INT(frameP), T_INT(slot), T_INT(pdsch_pdu->harq_pid), T_BUFFER(pduP, pdu_len)); + LOG_D(MAC, "[%d.%d]: processing PDU %d (with length %d) of %d total number of PDUs...\n", frameP, @@ -3964,6 +3973,9 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d uint8_t preamble_index = ra->ra_PreambleIndex; uint16_t rnti = mac->ra.ra_rnti; + T(T_NRUE_MAC_DL_RAR_PDU_WITH_DATA, T_INT(rnti), T_INT(frame), T_INT(slot), + T_BUFFER(dlsch_buffer, dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu_length)); + LOG_D(NR_MAC, "[%d.%d]: [UE %d][RAPROC] invoking MAC for received RAR (current preamble %d)\n", frame, slot, mac->ue_id, preamble_index); while (1) { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 65597bd3dd..0e9b26c773 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1599,6 +1599,8 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) pdu->tx_request_body.fapiTxPdu = ulsch_input_buffer; pdu->tx_request_body.pdu_length = TBS_bytes; number_of_pdus++; + T(T_NRUE_MAC_UL_PDU_WITH_DATA, T_INT(mac->crnti), T_INT(frame_tx), T_INT(slot_tx), + T_INT(ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id), T_BUFFER(ulsch_input_buffer, TBS_bytes)); } else { if (ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator && (mac->state == UE_CONNECTED || (ra->ra_state == nrRA_WAIT_RAR && ra->cfra))) { @@ -1626,6 +1628,8 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) pdu->tx_request_body.fapiTxPdu = ulsch_input_buffer; pdu->tx_request_body.pdu_length = TBS_bytes; number_of_pdus++; + T(T_NRUE_MAC_UL_PDU_WITH_DATA, T_INT(mac->crnti), T_INT(frame_tx), T_INT(slot_tx), + T_INT(ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id), T_BUFFER(ulsch_input_buffer, TBS_bytes)); // start or restart dataInactivityTimer if any MAC entity transmits a MAC SDU for DTCH logical channel, // or DCCH logical channel if (mac->data_inactivity_timer) @@ -2965,6 +2969,9 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_fra if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) mac->if_module->scheduled_response(&scheduled_response); + T(T_UE_PHY_INITIATE_RA_PROCEDURE, T_INT(frameP), T_INT(pdu->prach_config_pdu.prach_slot), + T_INT(pdu->prach_config_pdu.ra_PreambleIndex), T_INT(pdu->prach_config_pdu.prach_tx_power)); + if (ra->ra_type == RA_4_STEP) { nr_Msg1_transmitted(mac); } else if (ra->ra_type == RA_2_STEP) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index befe1ec3c7..29e4ea1122 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1693,6 +1693,14 @@ static void nr_generate_Msg2(module_id_t module_idP, LOG_A(NR_MAC, "%d.%d Send RAR to RA-RNTI %04x\n", frameP, slotP, ra->RA_rnti); + tx_req->PDU_index = pduindex; + tx_req->num_TLV = 1; + tx_req->TLVs[0].length = pdsch_pdu_rel15->TBSize[0]; + tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, pdsch_pdu_rel15->TBSize[0]); + TX_req->SFN = frameP; + TX_req->Number_of_PDUs++; + TX_req->Slot = slotP; + T(T_GNB_MAC_DL_RAR_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), @@ -1702,14 +1710,6 @@ static void nr_generate_Msg2(module_id_t module_idP, T_INT(0), T_BUFFER(&tx_req->TLVs[0].value.direct[0], tx_req->TLVs[0].length)); - tx_req->PDU_index = pduindex; - tx_req->num_TLV = 1; - tx_req->TLVs[0].length = pdsch_pdu_rel15->TBSize[0]; - tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, pdsch_pdu_rel15->TBSize[0]); - TX_req->SFN = frameP; - TX_req->Number_of_PDUs++; - TX_req->Slot = slotP; - // Mark the corresponding symbols RBs as used fill_pdcch_vrb_map(nr_mac, CC_id, &ra->sched_pdcch, CCEIndex, aggregation_level, beam.idx); for (int rb = 0; rb < rbSize; rb++) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 4022476ac6..55c86594cd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -593,7 +593,7 @@ static bool allocate_dl_retransmission(module_id_t module_id, return true; } -uint32_t pf_tbs[3][29]; // pre-computed, approximate TBS values for PF coefficient +static uint32_t pf_tbs[3][29]; // pre-computed, approximate TBS values for PF coefficient typedef struct UEsched_s { float coef; NR_UE_info_t * UE; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index ee573e89a1..39f5e2453a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -102,8 +102,8 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac, #define L1_RSRP_HYSTERIS 10 //considering 10 dBm as hysterisis for avoiding frequent SSB Beam Switching. !Fixme provide exact value if any //#define L1_DIFF_RSRP_STEP_SIZE 2 -int ssb_index_sorted[MAX_NUM_SSB] = {0}; -int ssb_rsrp_sorted[MAX_NUM_SSB] = {0}; +static int ssb_index_sorted[MAX_NUM_SSB] = {0}; +static int ssb_rsrp_sorted[MAX_NUM_SSB] = {0}; //Measured RSRP Values Table 10.1.16.1-1 from 36.133 //Stored all the upper limits[Max RSRP Value of corresponding index] diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index e161fa50ab..0900148073 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -40,32 +40,6 @@ //#define SRS_IND_DEBUG -static rnti_t lcid_crnti_lookahead(uint8_t *pdu, uint32_t pdu_len) -{ - uint16_t mac_len = 0; - uint16_t mac_subheader_len = 0; - while (pdu_len >= 3) { - if ((pdu[0] & 0x3F) == UL_SCH_LCID_C_RNTI) { - // Extract C-RNTI value - rnti_t crnti = ((pdu[1] & 0xFF) << 8) | (pdu[2] & 0xFF); - LOG_D(NR_MAC, "Received a MAC CE for C-RNTI with %04x\n", crnti); - return crnti; - } - if (!get_mac_len(pdu, pdu_len, &mac_len, &mac_subheader_len)) { - break; - } - pdu += mac_len + mac_subheader_len; - // if pdu_len can have the value subtracted without underflow, we can subtract - if (pdu_len >= mac_len + mac_subheader_len) { - pdu_len -= mac_len + mac_subheader_len; - } else { - // if not, set to 0 to prevent underflow - pdu_len = 0; - } - } - return 0; -} - int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot) { /* we assume that this function is mutex-protected from outside */ @@ -200,6 +174,92 @@ static int estimate_ul_buffer_long_bsr(const NR_BSR_LONG *bsr) // F: length of L is 0:8 or 1:16 bits wide // R: Reserved bit, set to zero. +// return: length of subPdu header +// 3GPP TS 38.321 Section 6 +uint8_t decode_ul_mac_sub_pdu_header(uint8_t *pduP, uint8_t *lcid, uint16_t *length) +{ + uint16_t mac_subheader_len = 1; + *lcid = pduP[0] & 0x3F; + + switch (*lcid) { + case UL_SCH_LCID_CCCH_64_BITS: + *length = 8; + break; + case UL_SCH_LCID_SRB1: + case UL_SCH_LCID_SRB2: + case UL_SCH_LCID_DTCH ...(UL_SCH_LCID_DTCH + 28): + case UL_SCH_LCID_L_TRUNCATED_BSR: + case UL_SCH_LCID_L_BSR: + if (pduP[0] & 0x40) { // F = 1 + mac_subheader_len = 3; + *length = (pduP[1] << 8) + pduP[2]; + } else { // F = 0 + mac_subheader_len = 2; + *length = pduP[1]; + } + break; + case UL_SCH_LCID_CCCH_48_BITS: + *length = 6; + break; + case UL_SCH_LCID_SINGLE_ENTRY_PHR: + case UL_SCH_LCID_C_RNTI: + *length = 2; + break; + case UL_SCH_LCID_S_TRUNCATED_BSR: + case UL_SCH_LCID_S_BSR: + *length = 1; + break; + case UL_SCH_LCID_PADDING: + // Nothing to do + break; + default: + LOG_E(NR_MAC, "LCID %0x not handled yet!\n", *lcid); + break; + } + + LOG_D(NR_MAC, "Decoded LCID 0x%X, header bytes: %d, payload bytes %d\n", *lcid, mac_subheader_len, *length); + + return mac_subheader_len; +} + +static rnti_t lcid_crnti_lookahead(uint8_t *pdu, uint32_t pdu_len) +{ + while (pdu_len > 0) { + uint16_t mac_len = 0; + uint8_t lcid = 0; + uint16_t mac_subheader_len = decode_ul_mac_sub_pdu_header(pdu, &lcid, &mac_len); + // Check for valid PDU + if (mac_subheader_len + mac_len > pdu_len) { + LOG_E(NR_MAC, + "Invalid PDU! mac_subheader_len: %d, mac_len: %d, remaining pdu_len: %d\n", + mac_subheader_len, + mac_len, + pdu_len); + + LOG_E(NR_MAC, "Residual UL MAC PDU: "); + uint32_t print_len = pdu_len > 30 ? 30 : pdu_len; // Only printf 1st - 30nd bytes + for (int i = 0; i < print_len; i++) + printf("%02x ", pdu[i]); + printf("\n"); + return 0; + } + + if (lcid == UL_SCH_LCID_C_RNTI) { + // Extract C-RNTI value + rnti_t crnti = ((pdu[1] & 0xFF) << 8) | (pdu[2] & 0xFF); + LOG_D(NR_MAC, "Received a MAC CE for C-RNTI with %04x\n", crnti); + return crnti; + } else if (lcid == UL_SCH_LCID_PADDING) { + // End of MAC PDU, can ignore the remaining bytes + return 0; + } + + pdu += mac_len + mac_subheader_len; + pdu_len -= mac_len + mac_subheader_len; + } + return 0; +} + static int nr_process_mac_pdu(instance_t module_idP, NR_UE_info_t *UE, uint8_t CC_id, @@ -209,8 +269,6 @@ static int nr_process_mac_pdu(instance_t module_idP, uint32_t pdu_len, const int8_t harq_pid) { - - uint8_t done = 0; int sdus = 0; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -234,92 +292,160 @@ static int nr_process_mac_pdu(instance_t module_idP, log_dump(NR_MAC, pduP, pdu_len, LOG_DUMP_CHAR, "\n"); #endif - while (!done && pdu_len > 0){ - uint16_t mac_len=0; - uint16_t mac_subheader_len=sizeof(NR_MAC_SUBHEADER_FIXED); - uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID; + while (pdu_len > 0) { + uint16_t mac_len = 0; + uint8_t lcid = 0; - LOG_D(NR_MAC, "In %s: received UL-SCH sub-PDU with LCID 0x%x in %d.%d (remaining PDU length %d)\n", __func__, rx_lcid, frameP, slot, pdu_len); + uint16_t mac_subheader_len = decode_ul_mac_sub_pdu_header(pduP, &lcid, &mac_len); + // Check for valid PDU + if (mac_subheader_len + mac_len > pdu_len) { + LOG_E(NR_MAC, + "Invalid PDU in %d.%d for RNTI %04X! mac_subheader_len: %d, mac_len: %d, remaining pdu_len: %d\n", + frameP, + slot, + UE->rnti, + mac_subheader_len, + mac_len, + pdu_len); + + LOG_E(NR_MAC, "Residual UL MAC PDU: "); + int print_len = pdu_len > 30 ? 30 : pdu_len; // Only printf 1st - 30nd bytes + for (int i = 0; i < print_len; i++) + printf("%02x ", pduP[i]); + printf("\n"); + return 0; + } + + LOG_D(NR_MAC, + "Received UL-SCH sub-PDU with LCID 0x%X in %d.%d for RNTI %04X (remaining PDU length %d)\n", + lcid, + frameP, + slot, + UE->rnti, + pdu_len); unsigned char *ce_ptr; - switch(rx_lcid){ - // MAC CE - /*#ifdef DEBUG_HEADER_PARSING - LOG_D(NR_MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID, pdu_len); - #endif*/ + switch (lcid) { + case UL_SCH_LCID_CCCH_64_BITS: + case UL_SCH_LCID_CCCH_48_BITS: + if (lcid == UL_SCH_LCID_CCCH_64_BITS) { + // Check if it is a valid CCCH1 message, we get all 00's messages very often + bool valid_pdu = false; + for (int i = 0; i < (mac_subheader_len + mac_len); i++) { + if (pduP[i] != 0) { + valid_pdu = true; + break; + } + } + if (!valid_pdu) { + LOG_D(NR_MAC, "%s() Invalid CCCH1 message!, pdu_len: %d\n", __func__, pdu_len); + return 0; + } + } + + LOG_I(MAC, "[RAPROC] Received SDU for CCCH length %d for UE %04x\n", mac_len, UE->rnti); + + if (prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE)) { + mac_rlc_data_ind(module_idP, + UE->rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + 0, + (char *)(pduP + mac_subheader_len), + mac_len, + 1, + NULL); + } else { + LOG_E(NR_MAC, "prepare_initial_ul_rrc_message() returned false, cannot forward CCCH message\n"); + } + break; + + case UL_SCH_LCID_SRB1: + case UL_SCH_LCID_SRB2: + AssertFatal(UE->CellGroup, + "UE %04x %d.%d: Received LCID %d which is not configured (UE has no CellGroup)\n", + UE->rnti, + frameP, + slot, + lcid); + + mac_rlc_data_ind(module_idP, + UE->rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + (char *)(pduP + mac_subheader_len), + mac_len, + 1, + NULL); + + UE->mac_stats.ul.total_sdu_bytes += mac_len; + UE->mac_stats.ul.lc_bytes[lcid] += mac_len; + break; + + case UL_SCH_LCID_DTCH ...(UL_SCH_LCID_DTCH + 28): + LOG_D(NR_MAC, + "[UE %04x] %d.%d : ULSCH -> UL-%s %d (gNB %ld, %d bytes)\n", + UE->rnti, + frameP, + slot, + lcid < 4 ? "DCCH" : "DTCH", + lcid, + module_idP, + mac_len); + UE->mac_stats.ul.lc_bytes[lcid] += mac_len; + + mac_rlc_data_ind(module_idP, + UE->rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + (char *)(pduP + mac_subheader_len), + mac_len, + 1, + NULL); + + sdus += 1; + /* Updated estimated buffer when receiving data */ + if (sched_ctrl->estimated_ul_buffer >= mac_len) + sched_ctrl->estimated_ul_buffer -= mac_len; + else + sched_ctrl->estimated_ul_buffer = 0; + break; + case UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY: // 38.321 Ch6.1.3.20 - mac_len = 2; break; + + case UL_SCH_LCID_MULTI_ENTRY_PHR_4_OCT: + LOG_E(NR_MAC, "Multi entry PHR not supported\n"); + break; + case UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION: // 38.321 Ch6.1.3.7 break; - case UL_SCH_LCID_S_BSR: - case UL_SCH_LCID_S_TRUNCATED_BSR: - //38.321 section 6.1.3.1 - //fixed length - mac_len =1; - if (pdu_len < sizeof(NR_BSR_SHORT)) { - LOG_E(NR_MAC, "pdu_len %d is invalid (prior to cast of size %ld)\n", - pdu_len, sizeof(NR_BSR_SHORT)); - return 0; - } - /* Extract short BSR value */ - ce_ptr = &pduP[mac_subheader_len]; - sched_ctrl->estimated_ul_buffer = estimate_ul_buffer_short_bsr((NR_BSR_SHORT *)ce_ptr); - LOG_D(NR_MAC, "SHORT BSR at %4d.%2d, est buf %d\n", frameP, slot, sched_ctrl->estimated_ul_buffer); - break; - case UL_SCH_LCID_L_BSR: - case UL_SCH_LCID_L_TRUNCATED_BSR: - //38.321 section 6.1.3.1 - //variable length - /* Several checks have been added to this function to - ensure that the casting of the pduP is possible. There seems - to be a partial PDU at the end of this buffer, so here - we gracefully ignore that by returning 0. See: - https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues/534 */ - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) { - LOG_E(NR_MAC, "pdu_len %d is invalid (shorter than MAC PDU header)\n", pdu_len); - return 0; - } - /* Extract long BSR value */ - ce_ptr = &pduP[mac_subheader_len]; - sched_ctrl->estimated_ul_buffer = estimate_ul_buffer_long_bsr((NR_BSR_LONG *)ce_ptr); - LOG_D(NR_MAC, "LONG BSR at %4d.%2d, estim buf %d\n", frameP, slot, sched_ctrl->estimated_ul_buffer); - break; - case UL_SCH_LCID_C_RNTI: - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i]; - if (ra->ra_state == nrRA_gNB_IDLE && ra->rnti == UE->rnti) { - // Extract C-RNTI value - rnti_t crnti = ((pduP[1] & 0xFF) << 8) | (pduP[2] & 0xFF); - AssertFatal(false, - "Received MAC CE for C-RNTI %04x without RA running, procedure exists? Or is it a bug while decoding the " - "MAC PDU?\n", - crnti); - break; - } - } - // 38.321 section 6.1.3.2 - // fixed length - mac_len = 2; + case UL_SCH_LCID_MULTI_ENTRY_PHR_1_OCT: + LOG_E(NR_MAC, "Multi entry PHR not supported\n"); break; case UL_SCH_LCID_SINGLE_ENTRY_PHR: if (harq_pid < 0) { LOG_E(NR_MAC, "Invalid HARQ PID %d\n", harq_pid); - done = 1; - break; + return 0; } - NR_sched_pusch_t *sched_pusch = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch;; - //38.321 section 6.1.3.8 - //fixed length - mac_len = 2; + NR_sched_pusch_t *sched_pusch = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch; + /* Extract SINGLE ENTRY PHR elements for PHR calculation */ ce_ptr = &pduP[mac_subheader_len]; - NR_SINGLE_ENTRY_PHR_MAC_CE *phr = (NR_SINGLE_ENTRY_PHR_MAC_CE *) ce_ptr; + NR_SINGLE_ENTRY_PHR_MAC_CE *phr = (NR_SINGLE_ENTRY_PHR_MAC_CE *)ce_ptr; /* Save the phr info */ int PH; const int PCMAX = phr->PCMAX; @@ -357,178 +483,61 @@ static int nr_process_mac_pdu(instance_t module_idP, sched_ctrl->pcmax); break; - case UL_SCH_LCID_MULTI_ENTRY_PHR_1_OCT: - LOG_E(NR_MAC, "Multi entry PHR not supported\n"); - done = 1; - //38.321 section 6.1.3.9 - // variable length - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) - return 0; - /* Extract MULTI ENTRY PHR elements from single octet bitmap for PHR calculation */ + case UL_SCH_LCID_C_RNTI: + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i]; + if (ra->ra_state == nrRA_gNB_IDLE && ra->rnti == UE->rnti) { + // Extract C-RNTI value + rnti_t crnti = ((pduP[1] & 0xFF) << 8) | (pduP[2] & 0xFF); + AssertFatal(false, + "Received MAC CE for C-RNTI %04x without RA running, procedure exists? Or is it a bug while decoding the " + "MAC PDU?\n", + crnti); + break; + } + } break; - case UL_SCH_LCID_MULTI_ENTRY_PHR_4_OCT: - LOG_E(NR_MAC, "Multi entry PHR not supported\n"); - done = 1; - //38.321 section 6.1.3.9 - // variable length - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) - return 0; - /* Extract MULTI ENTRY PHR elements from four octets bitmap for PHR calculation */ + case UL_SCH_LCID_S_TRUNCATED_BSR: + case UL_SCH_LCID_S_BSR: + /* Extract short BSR value */ + ce_ptr = &pduP[mac_subheader_len]; + sched_ctrl->estimated_ul_buffer = estimate_ul_buffer_short_bsr((NR_BSR_SHORT *)ce_ptr); + LOG_D(NR_MAC, "SHORT BSR at %4d.%2d, est buf %d\n", frameP, slot, sched_ctrl->estimated_ul_buffer); + break; + + case UL_SCH_LCID_L_TRUNCATED_BSR: + case UL_SCH_LCID_L_BSR: + /* Extract long BSR value */ + ce_ptr = &pduP[mac_subheader_len]; + sched_ctrl->estimated_ul_buffer = estimate_ul_buffer_long_bsr((NR_BSR_LONG *)ce_ptr); + LOG_D(NR_MAC, "LONG BSR at %4d.%2d, estim buf %d\n", frameP, slot, sched_ctrl->estimated_ul_buffer); break; case UL_SCH_LCID_PADDING: - done = 1; - // end of MAC PDU, can ignore the rest. - break; - - case UL_SCH_LCID_SRB1: - case UL_SCH_LCID_SRB2: - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) { - LOG_E(NR_MAC, "pdu_len %d is invalid (shorter than MAC PDU header)\n", pdu_len); - return 0; - } - LOG_D(NR_MAC, "UE %04x %d.%d: Received LCID %d bytes %d\n", UE->rnti, frameP, slot, rx_lcid, mac_len); - - AssertFatal(UE->CellGroup, - "UE %04x %d.%d: Received LCID %d which is not configured (UE has no CellGroup)\n", - UE->rnti, - frameP, - slot, - rx_lcid); - - mac_rlc_data_ind(module_idP, - UE->rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcid, - (char *)(pduP + mac_subheader_len), - mac_len, - 1, - NULL); - - UE->mac_stats.ul.total_sdu_bytes += mac_len; - UE->mac_stats.ul.lc_bytes[rx_lcid] += mac_len; - break; - - case UL_SCH_LCID_CCCH: - case UL_SCH_LCID_CCCH1: - // fixed length - mac_subheader_len = 1; - - if (rx_lcid == UL_SCH_LCID_CCCH1) { - // RRCResumeRequest1 message includes the full I-RNTI and has a size of 8 bytes - mac_len = 8; - - // Check if it is a valid CCCH1 message, we get all 00's messages very often - if (pdu_len < mac_subheader_len + mac_len) { - LOG_E(NR_MAC, "pdu_len %d is invalid (prior to cast of size %d)\n", - pdu_len, mac_subheader_len + mac_len); - return 0; - } - int i = 0; - for(i=0; i<(mac_subheader_len+mac_len); i++) { - if(pduP[i] != 0) { - break; - } - } - if (i == (mac_subheader_len+mac_len)) { - LOG_D(NR_MAC, "%s() Invalid CCCH1 message!, pdu_len: %d\n", __func__, pdu_len); - done = 1; - break; - } - } else { - // fixed length of 6 bytes - mac_len = 6; - } - - LOG_I(MAC, "[RAPROC] Received SDU for CCCH length %d for UE %04x\n", mac_len, UE->rnti); - - if (prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE)) { - mac_rlc_data_ind(module_idP, - UE->rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - 0, - (char *) (pduP + mac_subheader_len), - mac_len, - 1, - NULL); - } else { - LOG_E(NR_MAC, "prepare_initial_ul_rrc_message() returned false, cannot forward CCCH message\n"); - } - break; - - case UL_SCH_LCID_DTCH ... (UL_SCH_LCID_DTCH + 28): - // check if LCID is valid at current time. - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) { - LOG_E(NR_MAC, "pdu_len %d is invalid (shorter than MAC PDU header)\n", pdu_len); - return 0; - } - - LOG_D(NR_MAC, "[UE %04x] %d.%d : ULSCH -> UL-%s %d (gNB %ld, %d bytes)\n", - UE->rnti, - frameP, - slot, - rx_lcid<4?"DCCH":"DTCH", - rx_lcid, - module_idP, - mac_len); - UE->mac_stats.ul.lc_bytes[rx_lcid] += mac_len; - - mac_rlc_data_ind(module_idP, - UE->rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcid, - (char *)(pduP + mac_subheader_len), - mac_len, - 1, - NULL); - - sdus += 1; - /* Updated estimated buffer when receiving data */ - if (sched_ctrl->estimated_ul_buffer >= mac_len) - sched_ctrl->estimated_ul_buffer -= mac_len; - else - sched_ctrl->estimated_ul_buffer = 0; - break; + // End of MAC PDU, can ignore the rest. + return 0; default: - LOG_E(NR_MAC, "RNTI %0x [%d.%d], received unknown MAC header (LCID = 0x%02x)\n", UE->rnti, frameP, slot, rx_lcid); + LOG_E(NR_MAC, "RNTI %0x [%d.%d], received unknown MAC header (LCID = 0x%02x)\n", UE->rnti, frameP, slot, lcid); return -1; break; - } + } #ifdef ENABLE_MAC_PAYLOAD_DEBUG - if (rx_lcid < 45 || rx_lcid == 52 || rx_lcid == 63) { - LOG_I(NR_MAC, "In %s: dumping UL MAC SDU sub-header with length %d (LCID = 0x%02x):\n", __func__, mac_subheader_len, rx_lcid); - log_dump(NR_MAC, pduP, mac_subheader_len, LOG_DUMP_CHAR, "\n"); - LOG_I(NR_MAC, "In %s: dumping UL MAC SDU with length %d (LCID = 0x%02x):\n", __func__, mac_len, rx_lcid); - log_dump(NR_MAC, pduP + mac_subheader_len, mac_len, LOG_DUMP_CHAR, "\n"); - } else { - LOG_I(NR_MAC, "In %s: dumping UL MAC CE with length %d (LCID = 0x%02x):\n", __func__, mac_len, rx_lcid); - log_dump(NR_MAC, pduP + mac_subheader_len + mac_len, mac_len, LOG_DUMP_CHAR, "\n"); - } + if (lcid < 45 || lcid == 52 || lcid == 63) { + LOG_I(NR_MAC, "In %s: dumping UL MAC SDU sub-header with length %d (LCID = 0x%02x):\n", __func__, mac_subheader_len, lcid); + log_dump(NR_MAC, pduP, mac_subheader_len, LOG_DUMP_CHAR, "\n"); + LOG_I(NR_MAC, "In %s: dumping UL MAC SDU with length %d (LCID = 0x%02x):\n", __func__, mac_len, lcid); + log_dump(NR_MAC, pduP + mac_subheader_len, mac_len, LOG_DUMP_CHAR, "\n"); + } else { + LOG_I(NR_MAC, "In %s: dumping UL MAC CE with length %d (LCID = 0x%02x):\n", __func__, mac_len, lcid); + log_dump(NR_MAC, pduP + mac_subheader_len + mac_len, mac_len, LOG_DUMP_CHAR, "\n"); + } #endif - pduP += ( mac_subheader_len + mac_len ); - pdu_len -= ( mac_subheader_len + mac_len ); - - if (pdu_len < 0) { - LOG_E(NR_MAC, "In %s: residual UL MAC PDU in %d.%d with length < 0!, pdu_len %d \n", __func__, frameP, slot, pdu_len); - LOG_E(NR_MAC, "MAC PDU "); - for (int i = 0; i < 20; i++) // Only printf 1st - 20nd bytes - printf("%02x ", pduP[i]); - printf("\n"); - return 0; - } + pduP += (mac_subheader_len + mac_len); + pdu_len -= (mac_subheader_len + mac_len); } UE->mac_stats.ul.num_mac_sdu += sdus; @@ -1767,7 +1776,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, return true; } -uint32_t ul_pf_tbs[5][29]; // pre-computed, approximate TBS values for PF coefficient +static uint32_t ul_pf_tbs[5][29]; // pre-computed, approximate TBS values for PF coefficient typedef struct UEsched_s { float coef; NR_UE_info_t * UE; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 218e01fe28..3356889bf7 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -1055,7 +1055,7 @@ bool pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, if (ctxt_pP->enb_flag == ENB_FLAG_NO) { pdcpHead->rb_id = rb_id; - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { /* for the UE compiled in S1 mode, we need 1 here * for the UE compiled in noS1 mode, we need 0 * TODO: be sure of this @@ -1070,12 +1070,12 @@ bool pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, } } // nfapi_mode } else { - if (UE_NAS_USE_TUN) { - pdcpHead->inst = ctxt_pP->module_id; - } else if (ENB_NAS_USE_TUN) { - pdcpHead->inst = 0; - } - } + if (UE_NAS_USE_TUN) { + pdcpHead->inst = ctxt_pP->module_id; + } else if (ENB_NAS_USE_TUN) { + pdcpHead->inst = 0; + } + } } else { pdcpHead->rb_id = rb_id + (ctxt_pP->module_id * LTE_maxDRB); pdcpHead->inst = ctxt_pP->module_id; @@ -1275,7 +1275,7 @@ pdcp_run ( // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer // if (LINK_ENB_PDCP_TO_GTPV1U && ctxt_pP->enb_flag == ENB_FLAG_NO) { - if (!get_softmodem_params()->emulate_l1 && (!EPC_MODE_ENABLED || ctxt_pP->enb_flag == ENB_FLAG_NO)) { + if (!get_softmodem_params()->emulate_l1 && (IS_SOFTMODEM_NOS1 || ctxt_pP->enb_flag == ENB_FLAG_NO)) { pdcp_fifo_read_input_sdus(ctxt_pP); } @@ -1311,125 +1311,9 @@ pdcp_mbms_run ( ) //----------------------------------------------------------------------------- { - // if (ctxt_pP->enb_flag) { - // start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_run); - // } else { - // start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_run); - // } - - // pdcp_enb[ctxt_pP->module_id].sfn++; // range: 0 to 18,446,744,073,709,551,615 - // pdcp_enb[ctxt_pP->module_id].frame=ctxt_pP->frame; // 1023 - // pdcp_enb[ctxt_pP->module_id].subframe= ctxt_pP->subframe; - // pdcp_update_stats(ctxt_pP); - // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN); - // MessageDef *msg_p; - //int result; - //protocol_ctxt_t ctxt; - -// do { -// // Checks if a message has been sent to PDCP sub-task -// itti_poll_msg (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p); -// -// if (msg_p != NULL) { -// switch (ITTI_MSG_ID(msg_p)) { -// case RRC_DCCH_DATA_REQ: -// PROTOCOL_CTXT_SET_BY_MODULE_ID( -// &ctxt, -// RRC_DCCH_DATA_REQ (msg_p).module_id, -// RRC_DCCH_DATA_REQ (msg_p).enb_flag, -// RRC_DCCH_DATA_REQ (msg_p).rnti, -// RRC_DCCH_DATA_REQ (msg_p).frame, -// 0, -// RRC_DCCH_DATA_REQ (msg_p).eNB_index); -// LOG_D(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n", -// PROTOCOL_CTXT_ARGS(&ctxt), -// ITTI_MSG_NAME (msg_p), -// ITTI_MSG_ORIGIN_NAME(msg_p), -// ITTI_MSG_DESTINATION_INSTANCE (msg_p), -// RRC_DCCH_DATA_REQ (msg_p).rb_id, -// RRC_DCCH_DATA_REQ (msg_p).muip, -// RRC_DCCH_DATA_REQ (msg_p).confirmp, -// RRC_DCCH_DATA_REQ (msg_p).mode); -// LOG_D(PDCP, "Before calling pdcp_data_req from pdcp_run! RRC_DCCH_DATA_REQ (msg_p).rb_id: %d \n", RRC_DCCH_DATA_REQ (msg_p).rb_id); -// result = pdcp_data_req (&ctxt, -// SRB_FLAG_YES, -// RRC_DCCH_DATA_REQ (msg_p).rb_id, -// RRC_DCCH_DATA_REQ (msg_p).muip, -// RRC_DCCH_DATA_REQ (msg_p).confirmp, -// RRC_DCCH_DATA_REQ (msg_p).sdu_size, -// RRC_DCCH_DATA_REQ (msg_p).sdu_p, -// RRC_DCCH_DATA_REQ (msg_p).mode, -// NULL, NULL -// ); -// -// if (result != true) -// LOG_E(PDCP, "PDCP data request failed!\n"); -// -// // Message buffer has been processed, free it now. -// result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ (msg_p).sdu_p); -// AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); -// break; -// -// case RRC_PCCH_DATA_REQ: { -// sdu_size_t sdu_buffer_sizeP; -// sdu_buffer_sizeP = RRC_PCCH_DATA_REQ(msg_p).sdu_size; -// uint8_t CC_id = RRC_PCCH_DATA_REQ(msg_p).CC_id; -// uint8_t ue_index = RRC_PCCH_DATA_REQ(msg_p).ue_index; -// RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_paging[ue_index] = sdu_buffer_sizeP; -// -// if (sdu_buffer_sizeP > 0) { -// memcpy(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].paging[ue_index], RRC_PCCH_DATA_REQ(msg_p).sdu_p, sdu_buffer_sizeP); -// } -// -// //paging pdcp log -// LOG_D(PDCP, "PDCP Received RRC_PCCH_DATA_REQ CC_id %d length %d \n", CC_id, sdu_buffer_sizeP); -// } -// break; -// -// default: -// LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p)); -// break; -// } -// -// result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); -// AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); -// } -// } while(msg_p != NULL); -// - // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer - // if (LINK_ENB_PDCP_TO_GTPV1U && ctxt_pP->enb_flag == ENB_FLAG_NO) { - //if (EPC_MODE_ENABLED || ctxt_pP->enb_flag == ENB_FLAG_NO ) { - - pdcp_fifo_read_input_mbms_sdus_fromtun(ctxt_pP); - //} - - // PDCP -> NAS/IP traffic: RX -// if (ctxt_pP->enb_flag) { -// start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip); -// } else { -// start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip); -// } -// - - //pdcp_fifo_flush_mbms_sdus(ctxt_pP); - -// if (ctxt_pP->enb_flag) { -// stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip); -// } else { -// stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip); -// } -// -// if (ctxt_pP->enb_flag) { -// stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_run); -// } else { -// stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_run); -// } -// -// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT); + pdcp_fifo_read_input_mbms_sdus_fromtun(ctxt_pP); } - - void pdcp_init_stats_UE(module_id_t mod, uint16_t uid) { Pdcp_stats_tx_window_ms[mod][uid] = 100; Pdcp_stats_rx_window_ms[mod][uid] = 100; diff --git a/openair2/MCE_APP/mce_app.c b/openair2/MCE_APP/mce_app.c index 53194d4899..7e9d45d99f 100644 --- a/openair2/MCE_APP/mce_app.c +++ b/openair2/MCE_APP/mce_app.c @@ -330,9 +330,9 @@ void *MCE_app_task(void *args_p) { itti_mark_task_ready (TASK_MCE_APP); /* Try to register each MCE */ - if ( EPC_MODE_ENABLED && RC.rrc == NULL ) - LOG_E(RRC, "inconsistent global variables\n"); - if (EPC_MODE_ENABLED && RC.rrc ) { + if (!IS_SOFTMODEM_NOS1 && RC.rrc == NULL) + LOG_E(RRC, "inconsistent global variables\n"); + if (!IS_SOFTMODEM_NOS1 && RC.rrc) { register_mce_pending = MCE_app_register(mce_id_start, mce_id_end); } @@ -478,10 +478,13 @@ void *MCE_app_task(void *args_p) { break; case M3AP_DEREGISTERED_MCE_IND: - if (EPC_MODE_ENABLED) { - LOG_W(MCE_APP, "[MCE %ld] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), - M3AP_DEREGISTERED_MCE_IND(msg_p).nb_mme); - /* TODO handle recovering of registration */ + if ((!IS_SOFTMODEM_NOS1)) { + LOG_W(MCE_APP, + "[MCE %ld] Received %s: associated MME %d\n", + instance, + ITTI_MSG_NAME(msg_p), + M3AP_DEREGISTERED_MCE_IND(msg_p).nb_mme); + /* TODO handle recovering of registration */ } break; diff --git a/openair2/PHY_INTERFACE/IF_Module.h b/openair2/PHY_INTERFACE/IF_Module.h index 3fe38a2731..27eea78fc6 100644 --- a/openair2/PHY_INTERFACE/IF_Module.h +++ b/openair2/PHY_INTERFACE/IF_Module.h @@ -37,7 +37,6 @@ //#include "openair1/PHY/LTE_TRANSPORT/transport_eNB.h" #include "nfapi_interface.h" #include "common/platform_types.h" -#include #include #define MAX_NUM_DL_PDU 100 diff --git a/openair2/RRC/LTE/extern_NB_IoT.h b/openair2/RRC/LTE/extern_NB_IoT.h index 773acf9d4f..fcaa48cea3 100644 --- a/openair2/RRC/LTE/extern_NB_IoT.h +++ b/openair2/RRC/LTE/extern_NB_IoT.h @@ -46,7 +46,6 @@ extern UE_RRC_INST_NB_IoT *UE_rrc_inst_NB_IoT; extern eNB_RRC_INST_NB_IoT *eNB_rrc_inst_NB_IoT; extern PHY_Config_NB_IoT_t *config_INFO; -extern uint8_t DRB2LCHAN_NB_IoT[2]; extern LTE_LogicalChannelConfig_NB_r13_t SRB1bis_logicalChannelConfig_defaultValue_NB_IoT; extern LTE_LogicalChannelConfig_NB_r13_t SRB1_logicalChannelConfig_defaultValue_NB_IoT; diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 2079b84438..105153ed87 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -238,7 +238,7 @@ static int rrc_set_state (module_id_t ue_mod_idP, Rrc_State_t state) { //----------------------------------------------------------------------------- static int rrc_set_sub_state( module_id_t ue_mod_idP, Rrc_Sub_State_t subState ) { - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { switch (UE_rrc_inst[ue_mod_idP].RrcState) { case RRC_STATE_INACTIVE: AssertFatal ((RRC_SUB_STATE_INACTIVE_FIRST <= subState) && (subState <= RRC_SUB_STATE_INACTIVE_LAST), @@ -546,7 +546,7 @@ static void rrc_ue_generate_RRCConnectionSetupComplete(const protocol_ctxt_t *co const char *nas_msg; int nas_msg_length; - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { nas_msg = (char *)UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.nas_data; nas_msg_length = UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.length; } else { @@ -760,7 +760,7 @@ rrc_ue_establish_drb( LOG_I(RRC,"[UE %d] Frame %d: processing RRCConnectionReconfiguration: reconfiguring DRB %ld/LCID %d\n", ue_mod_idP, frameP, DRB_config->drb_Identity, (int)*DRB_config->logicalChannelIdentity); - if(!EPC_MODE_ENABLED) { + if (IS_SOFTMODEM_NOS1) { ip_addr_offset3 = 0; ip_addr_offset4 = 1; LOG_I(OIP,"[UE %d] trying to bring up the OAI interface %d, IP X.Y.%d.%d\n", ue_mod_idP, ip_addr_offset3+ue_mod_idP, @@ -781,7 +781,7 @@ rrc_ue_establish_drb( AssertFatal(false, "not implemented\n"); LOG_D(RRC,"[UE %d] State = Attached (eNB %d)\n",ue_mod_idP,eNB_index); } - } // !EPC_MODE_ENABLED + } return(0); } @@ -2919,7 +2919,7 @@ int decode_BCCH_DLSCH_Message( } if (rrc_get_sub_state(ctxt_pP->module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE) { - if ((UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.nas_data != NULL) || (!EPC_MODE_ENABLED)) { + if ((UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.nas_data != NULL) || IS_SOFTMODEM_NOS1) { rrc_ue_generate_RRCConnectionRequest(ctxt_pP, 0); rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_CONNECTING ); } @@ -3092,65 +3092,6 @@ int decode_SIB1_MBMS( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_in UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus_MBMS = 1; UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIB1systemInfoValueTag_MBMS = sib1_MBMS->systemInfoValueTag_r14; - /* - if (EPC_MODE_ENABLED) - { - int cell_valid = 0; - - if (sib1->cellAccessRelatedInfo.cellBarred == LTE_SystemInformationBlockType1__cellAccessRelatedInfo__cellBarred_notBarred) { - int plmn; - int plmn_number; - plmn_number = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count; - - for (plmn = 0; plmn < plmn_number; plmn++) { - LTE_PLMN_Identity_t *plmn_Identity; - plmn_Identity = &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[plmn]->plmn_Identity; - - if ( - ( - (plmn_Identity->mcc == NULL) - || - ( - (UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit1 == *(plmn_Identity->mcc->list.array[0])) && - (UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit2 == *(plmn_Identity->mcc->list.array[1])) && - (UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit3 == *(plmn_Identity->mcc->list.array[2])) - ) - ) - && - (UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit1 == *(plmn_Identity->mnc.list.array[0])) - && - (UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit2 == *(plmn_Identity->mnc.list.array[1])) - && - ( - ((UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == 0xf) && (plmn_Identity->mnc.list.count == 2)) - || - (UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == *(plmn_Identity->mnc.list.array[2])) - ) - ) { - MessageDef *msg_p; - msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, NAS_CELL_SELECTION_CNF); - NAS_CELL_SELECTION_CNF (msg_p).errCode = AS_SUCCESS; - NAS_CELL_SELECTION_CNF (msg_p).cellID = BIT_STRING_to_uint32(&sib1->cellAccessRelatedInfo.cellIdentity); - NAS_CELL_SELECTION_CNF (msg_p).tac = BIT_STRING_to_uint16(&sib1->cellAccessRelatedInfo.trackingAreaCode); - NAS_CELL_SELECTION_CNF (msg_p).rat = 0xFF; - NAS_CELL_SELECTION_CNF (msg_p).rsrq = rsrq; - NAS_CELL_SELECTION_CNF (msg_p).rsrp = rsrp; - itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); - cell_valid = 1; - break; - } - } - } - - if (cell_valid == 0) { - MessageDef *msg_p; - msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, PHY_FIND_NEXT_CELL_REQ); - itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p); - LOG_E(RRC, "Synched with a cell, but PLMN doesn't match our SIM, the message PHY_FIND_NEXT_CELL_REQ is sent but lost in current UE implementation! \n"); - } - } - } - */ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_OUT ); return 0; } @@ -3300,7 +3241,7 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus = 1; UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIB1systemInfoValueTag = sib1->systemInfoValueTag; - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { int cell_valid = 0; if (sib1->cellAccessRelatedInfo.cellBarred == LTE_SystemInformationBlockType1__cellAccessRelatedInfo__cellBarred_notBarred) { @@ -3962,7 +3903,7 @@ int decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index ) { // After SI is received, prepare RRCConnectionRequest if (UE_rrc_inst[ctxt_pP->module_id].MBMS_flag < 3) // see -Q option - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { rrc_ue_generate_RRCConnectionRequest( ctxt_pP, eNB_index ); } diff --git a/openair2/RRC/LTE/rrc_common.c b/openair2/RRC/LTE/rrc_common.c index 230e0d409b..2448ec9bbe 100644 --- a/openair2/RRC/LTE/rrc_common.c +++ b/openair2/RRC/LTE/rrc_common.c @@ -59,12 +59,6 @@ rrc_init_global_param( DCCH_LCHAN_DESC.transport_block_size = 4; DCCH_LCHAN_DESC.max_transport_blocks = 16; DCCH_LCHAN_DESC.Delay_class = 1; - DTCH_DL_LCHAN_DESC.transport_block_size = 52; - DTCH_DL_LCHAN_DESC.max_transport_blocks = 20; - DTCH_DL_LCHAN_DESC.Delay_class = 1; - DTCH_UL_LCHAN_DESC.transport_block_size = 52; - DTCH_UL_LCHAN_DESC.max_transport_blocks = 20; - DTCH_UL_LCHAN_DESC.Delay_class = 1; return 0; } diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index c26a57cd44..bfe07c86ca 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -124,6 +124,7 @@ extern struct rrc_eNB_ue_context_s *get_first_ue_context(eNB_RRC_INST *rrc_insta pthread_mutex_t rrc_release_freelist; RRC_release_list_t rrc_release_info; pthread_mutex_t lock_ue_freelist; +static uint8_t DRB2LCHAN[8]; void openair_rrc_on( @@ -846,7 +847,7 @@ rrc_eNB_free_UE( return; } - if(EPC_MODE_ENABLED) { + if ((!IS_SOFTMODEM_NOS1)) { if ((ue_context_pP->ue_context.ul_failure_timer >= 20000) && (mac_eNB_get_rrc_status(enb_mod_idP, rnti) >= RRC_CONNECTED)) { LOG_I(RRC, "[eNB %d] S1AP_UE_CONTEXT_RELEASE_REQ sent for RNTI %x, cause 21, radio connection with ue lost\n", enb_mod_idP, rnti); rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, @@ -1031,7 +1032,7 @@ rrc_eNB_process_RRCConnectionSetupComplete( ue_context_pP->ue_context.ue_rrc_inactivity_timer = 1; // set rrc inactivity timer when UE goes into RRC_CONNECTED T(T_ENB_RRC_CONNECTION_SETUP_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rntiMaybeUEid)); - if (EPC_MODE_ENABLED == 1) { + if ((!IS_SOFTMODEM_NOS1) == 1) { // Forward message to S1AP layer rrc_eNB_send_S1AP_NAS_FIRST_REQ(ctxt_pP, ue_context_pP, rrcConnectionSetupComplete); } else { @@ -1374,7 +1375,7 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete( ue_context_pP->ue_context.Srb1.Active = 1; //ue_context_pP->ue_context.Srb2.Srb_info.Srb_id = 2; - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { hashtable_rc_t h_rc; int j; rrc_ue_s1ap_ids_t *rrc_ue_s1ap_ids_p = NULL; @@ -1450,13 +1451,13 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete( put_UE_in_freelist(ctxt_pP->module_id, ctxt_pP->rntiMaybeUEid, 0); return; } - } /* EPC_MODE_ENABLED */ + } /* (!IS_SOFTMODEM_NOS1) */ /* Update RNTI in ue_context */ ue_context_pP->ue_id_rnti = ctxt_pP->rntiMaybeUEid; // here ue_id_rnti is just a key, may be something else ue_context_pP->ue_context.rnti = ctxt_pP->rntiMaybeUEid; - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { uint8_t send_security_mode_command = false; rrc_pdcp_config_security( ctxt_pP, @@ -5109,7 +5110,7 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s *ue_context_p, protoc rrc_rlc_config_asn1_req(ctxt_pP, ue_context_p->ue_context.SRB_configList, (LTE_DRB_ToAddModList_t *)NULL, (LTE_DRB_ToReleaseList_t *)NULL, (LTE_PMCH_InfoList_r9_t *)NULL, 0, 0); - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { rrc_eNB_process_security ( ctxt_pP, ue_context_p, @@ -5257,7 +5258,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( LOG_D(RRC, "[eNB %d] Frame %d: Establish RLC UM Bidirectional, DRB %d Active\n", ctxt_pP->module_id, ctxt_pP->frame, (int)DRB_configList->list.array[i]->drb_Identity); - if (!EPC_MODE_ENABLED && !ENB_NAS_USE_TUN) { + if (IS_SOFTMODEM_NOS1 && !ENB_NAS_USE_TUN) { LOG_I(OIP, "[eNB %d] trying to bring up the OAI interface oai%d\n", ctxt_pP->module_id, ctxt_pP->module_id); @@ -5276,7 +5277,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( LOG_D(RRC, "[eNB %d] State = Attached (UE rnti %x module id %u)\n", ctxt_pP->module_id, ue_context_pP->ue_context.rnti, ue_module_id); } /* oip_ifup */ - } /* !EPC_MODE_ENABLED && ENB_NAS_USE_TUN*/ + } /* !(!IS_SOFTMODEM_NOS1) && ENB_NAS_USE_TUN*/ LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RRC_eNB --- MAC_CONFIG_REQ (DRB) ---> MAC_eNB\n", @@ -6365,7 +6366,7 @@ rrc_eNB_decode_dcch( /*NN: revise the condition */ /*FK: left the condition as is for the case MME is used (S1 mode) but setting dedicated_DRB = 1 otherwise (noS1 mode) so that no second RRCReconfiguration message activationg more DRB is sent as this causes problems with the nasmesh driver.*/ - if (EPC_MODE_ENABLED || get_softmodem_params()->emulate_l1) { + if (!IS_SOFTMODEM_NOS1 || get_softmodem_params()->emulate_l1) { if (ue_context_p->ue_context.StatusRrc == RRC_RECONFIGURED) { dedicated_DRB = 1; LOG_I(RRC, @@ -6461,7 +6462,7 @@ rrc_eNB_decode_dcch( ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier); } - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { if (dedicated_DRB == 1) { // rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(ctxt_pP, // ue_context_p, @@ -6538,7 +6539,7 @@ rrc_eNB_decode_dcch( LOG_I(RRC,"issue rrc_eNB_send_PATH_SWITCH_REQ \n"); rrc_eNB_send_PATH_SWITCH_REQ(ctxt_pP,ue_context_p); } - } /* EPC_MODE_ENABLED */ + } /* (!IS_SOFTMODEM_NOS1) */ break; @@ -6837,7 +6838,7 @@ rrc_eNB_decode_dcch( ue_context_p->ue_context.does_nr = 0; } - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP, ue_context_p, ul_dcch_msg); @@ -6875,7 +6876,7 @@ rrc_eNB_decode_dcch( LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP, "[MSG] RRC UL Information Transfer \n"); - if (EPC_MODE_ENABLED == 1) { + if (!IS_SOFTMODEM_NOS1) { rrc_eNB_send_S1AP_UPLINK_NAS(ctxt_pP, ue_context_p, ul_dcch_msg); @@ -7264,7 +7265,7 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { ue_context_p->ue_context.rnti, ue_context_p->ue_context.ue_release_timer_thres_s1); - if (EPC_MODE_ENABLED) + if (!IS_SOFTMODEM_NOS1) rrc_eNB_generate_RRCConnectionRelease(ctxt_pP, ue_context_p); else removed_ue_count = add_ue_to_remove(ue_to_be_removed, removed_ue_count, ue_context_p); @@ -7318,7 +7319,7 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { ue_context_p->ue_context.ue_release_timer_rrc = 1; ue_context_p->ue_context.ue_release_timer_thres_rrc = 100; - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { if (rrc_release_info.RRC_release_ctrl[release_num].flag == 4) { // if timer_s1 == 0 rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_CPLT(ctxt_pP->module_id, ue_context_p->ue_context.eNB_ue_s1ap_id); @@ -7343,7 +7344,7 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { if (rrc_ue_s1ap_ids != NULL) { rrc_eNB_S1AP_remove_ue_ids(RC.rrc[ctxt_pP->module_id], rrc_ue_s1ap_ids); } - } /* EPC_MODE_ENABLED */ + } /* (!IS_SOFTMODEM_NOS1) */ rrc_release_info.RRC_release_ctrl[release_num].flag = 0; rrc_release_info.num_UEs--; diff --git a/openair2/RRC/LTE/rrc_extern.h b/openair2/RRC/LTE/rrc_extern.h index 199e5df52c..7dc4c51fbc 100644 --- a/openair2/RRC/LTE/rrc_extern.h +++ b/openair2/RRC/LTE/rrc_extern.h @@ -38,22 +38,12 @@ extern UE_RRC_INST *UE_rrc_inst; - -extern uint8_t DRB2LCHAN[8]; - extern LTE_LogicalChannelConfig_t SRB1_logicalChannelConfig_defaultValue; extern LTE_LogicalChannelConfig_t SRB2_logicalChannelConfig_defaultValue; extern int NB_UE_INST; extern void* bigphys_malloc(int); - - -//uint8_t RACH_TIME_ALLOC; -extern uint16_t RACH_FREQ_ALLOC; -//uint8_t NB_RACH; -extern LCHAN_DESC BCCH_LCHAN_DESC,CCCH_LCHAN_DESC,DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; -extern MAC_MEAS_T BCCH_MEAS_TRIGGER,CCCH_MEAS_TRIGGER,DCCH_MEAS_TRIGGER,DTCH_MEAS_TRIGGER; -extern MAC_AVG_T BCCH_MEAS_AVG,CCCH_MEAS_AVG,DCCH_MEAS_AVG, DTCH_MEAS_AVG; +extern LCHAN_DESC CCCH_LCHAN_DESC, DCCH_LCHAN_DESC; extern UE_PF_PO_t UE_PF_PO[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; extern pthread_mutex_t ue_pf_po_mutex; diff --git a/openair2/RRC/LTE/rrc_vars.h b/openair2/RRC/LTE/rrc_vars.h index 0b1db9ab34..5574708e44 100644 --- a/openair2/RRC/LTE/rrc_vars.h +++ b/openair2/RRC/LTE/rrc_vars.h @@ -43,8 +43,6 @@ UE_RRC_INST *UE_rrc_inst = NULL; #include "LAYER2/MAC/mac_extern.h" extern uint16_t ue_id_g; -uint8_t DRB2LCHAN[8]; - long logicalChannelGroup0 = 0; long logicalChannelSR_Mask_r9=0; @@ -75,11 +73,7 @@ const LTE_LogicalChannelConfig_t SRB2_logicalChannelConfig_defaultValue = {.ul_S .ext1 = &logicalChannelSR_Mask_r9_ext1}; //CONSTANTS -uint16_t RACH_FREQ_ALLOC; -//uint8_t NB_RACH; -LCHAN_DESC BCCH_LCHAN_DESC,CCCH_LCHAN_DESC,DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; -MAC_MEAS_T BCCH_MEAS_TRIGGER,CCCH_MEAS_TRIGGER,DCCH_MEAS_TRIGGER,DTCH_MEAS_TRIGGER; -MAC_AVG_T BCCH_MEAS_AVG, CCCH_MEAS_AVG,DCCH_MEAS_AVG, DTCH_MEAS_AVG; +LCHAN_DESC CCCH_LCHAN_DESC, DCCH_LCHAN_DESC; // only used for RRC connection re-establishment procedure TS36.331 5.3.7 // [0]: current C-RNTI, [1]: prior C-RNTI diff --git a/openair2/UTIL/OPT/probe.c b/openair2/UTIL/OPT/probe.c index a4994421c2..25d1b6b1ec 100644 --- a/openair2/UTIL/OPT/probe.c +++ b/openair2/UTIL/OPT/probe.c @@ -93,7 +93,7 @@ int opt_enabled=0; //static unsigned char g_PDUBuffer[1600]; //static unsigned int g_PDUOffset; -FILE *file_fd = NULL; +static FILE *file_fd = NULL; const pcap_hdr_t file_header = { 0xa1b2c3d4, /* magic number */ 2, @@ -120,7 +120,7 @@ typedef struct { struct sockaddr_in address; } opt_listener_t; -opt_listener_t opt_listener; +static opt_listener_t opt_listener; unsigned short checksum(unsigned short *ptr, int length) { int sum = 0; diff --git a/openair2/X2AP/x2ap_eNB_management_procedures.c b/openair2/X2AP/x2ap_eNB_management_procedures.c index 465949a58e..442adbd045 100644 --- a/openair2/X2AP/x2ap_eNB_management_procedures.c +++ b/openair2/X2AP/x2ap_eNB_management_procedures.c @@ -49,8 +49,7 @@ static int indent = 0; - -x2ap_eNB_internal_data_t x2ap_eNB_internal_data; +static x2ap_eNB_internal_data_t x2ap_eNB_internal_data; RB_GENERATE(x2ap_enb_map, x2ap_eNB_data_s, entry, x2ap_eNB_compare_assoc_id); diff --git a/openair3/CMakeLists.txt b/openair3/CMakeLists.txt index 555ca7cbc8..f638abbaaa 100644 --- a/openair3/CMakeLists.txt +++ b/openair3/CMakeLists.txt @@ -3,3 +3,4 @@ add_subdirectory(M3AP) add_subdirectory(S1AP) add_subdirectory(NGAP) add_subdirectory(NRPPA) +add_subdirectory(NAS) diff --git a/openair3/MME_APP/mme_app.c b/openair3/MME_APP/mme_app.c index 61ec0641e3..f0d7519d82 100644 --- a/openair3/MME_APP/mme_app.c +++ b/openair3/MME_APP/mme_app.c @@ -60,93 +60,6 @@ extern RAN_CONTEXT_t RC; #include "executables/lte-softmodem.h" - - - -/*------------------------------------------------------------------------------*/ - -//static uint32_t MCE_app_register(ngran_node_t node_type,uint32_t mce_id_start, uint32_t mce_id_end) { -// uint32_t mce_id; -// MessageDef *msg_p; -// uint32_t register_mce_pending = 0; -// -// for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) { -// { -// // M3AP registration -// /* note: there is an implicit relationship between the data structure and the message name */ -// msg_p = itti_alloc_new_message (TASK_MME_APP, 0, M3AP_REGISTER_MCE_REQ); -// //RCconfig_S1(msg_p, mce_id); -// -// //if (mce_id == 0) -// //RCconfig_gtpu(); -// -// //LOG_I(MME_APP,"default drx %d\n",((M3AP_REGISTER_MCE_REQ(msg_p)).default_drx)); -// -// LOG_I(ENB_APP,"[MCE %d] MCE_app_register via M3AP for instance %d\n", mce_id, ENB_MODULE_ID_TO_INSTANCE(mce_id)); -// itti_send_msg_to_task (TASK_M3AP, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p); -// -// //{ // S1AP registration -// // /* note: there is an implicit relationship between the data structure and the message name */ -// // msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, S1AP_REGISTER_ENB_REQ); -// // RCconfig_S1(msg_p, enb_id); -// -// // if (enb_id == 0) RCconfig_gtpu(); -// -// // LOG_I(ENB_APP,"default drx %d\n",((S1AP_REGISTER_ENB_REQ(msg_p)).default_drx)); -// -// // LOG_I(ENB_APP,"[eNB %d] eNB_app_register via S1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id)); -// // itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); -// //} -// -// register_mce_pending++; -// } -// } -// -// return register_mce_pending; -//} - - -/*------------------------------------------------------------------------------*/ -//static uint32_t MCE_app_register_x2(uint32_t mce_id_start, uint32_t mce_id_end) { -// uint32_t mce_id; -// MessageDef *msg_p; -// uint32_t register_mce_m2_pending = 0; -// -// for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) { -// { -// msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, X2AP_REGISTER_ENB_REQ); -// RCconfig_X2(msg_p, mce_id); -// itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p); -// register_mce_x2_pending++; -// } -// } -// -// return register_mce_x2_pending; -//} - -/*------------------------------------------------------------------------------*/ -//static uint32_t MCE_app_register_m2(uint32_t mce_id_start, uint32_t mce_id_end) { -// uint32_t mce_id; -// MessageDef *msg_p; -// uint32_t register_mce_m2_pending = 0; -// -// LOG_W(MME_APP,"Register ..."); -// for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) { -// { -// // LOG_W(MME_APP,"Register commes inside ...\n"); -// msg_p = itti_alloc_new_message (TASK_MME_APP, 0, M2AP_REGISTER_MCE_REQ); -// //RCconfig_M2_MCE(msg_p, mce_id); -// itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p); -// // LOG_W(MME_APP,"Register sent ...\n"); -// register_mce_m2_pending++; -// } -// } -// -// return register_mce_m2_pending; -//} -// -// -// static uint32_t MME_app_handle_m3ap_setup_req(instance_t instance){ //uint32_t mce_id=0; @@ -156,31 +69,13 @@ static uint32_t MME_app_handle_m3ap_setup_req(instance_t instance){ return 0; } + static uint32_t MME_app_handle_m3ap_session_start_resp(instance_t instance){ return 0; } -// -//static uint32_t MME_app_handle_m3ap_session_stop_resp(instance_t instance){ -// -// -// return 0; -//} - - -// -//static uint32_t MCE_app_send_m2ap_mbms_scheduling_information(instance_t instance){ -// -// uint32_t mce_id=0; -// MessageDef *msg_p; -// msg_p = itti_alloc_new_message (TASK_MME_APP, 0, M2AP_MBMS_SCHEDULING_INFORMATION); -// itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); -// -// return 0; -//} -// static uint32_t MME_app_send_m3ap_session_start_req(instance_t instance){ //uint32_t mce_id=0; @@ -190,15 +85,7 @@ static uint32_t MME_app_send_m3ap_session_start_req(instance_t instance){ return 0; } -//static uint32_t MME_app_send_m3ap_session_stop_req(instance_t instance){ -// -// //uint32_t mce_id=0; -// MessageDef *msg_p; -// msg_p = itti_alloc_new_message (TASK_MME_APP, 0, M3AP_MBMS_SESSION_STOP_REQ); -// itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); -// -// return 0; -//} + static uint32_t MME_app_send_m3ap_session_update_req(instance_t instance){ //uint32_t mce_id=0; @@ -209,19 +96,8 @@ static uint32_t MME_app_send_m3ap_session_update_req(instance_t instance){ return 0; } /*------------------------------------------------------------------------------*/ -void *MME_app_task(void *args_p) { - //uint32_t mce_nb = RC.nb_inst; - //uint32_t mce_id_start = 0; - //uint32_t mce_id_end = mce_id_start + mce_nb; - //uint32_t register_mce_pending=0; - //uint32_t registered_mce=0; - //long mce_register_retry_timer_id; - //uint32_t m2_register_mce_pending = 0; - // uint32_t x2_registered_mce = 0; - // long x2_mce_register_retry_timer_id; - // uint32_t m2_register_mce_pending = 0; - // uint32_t m2_registered_mce = 0; - // long m2_mce_register_retry_timer_id; +void *MME_app_task(void *args_p) +{ long m3_mme_register_session_start_timer_id; MessageDef *msg_p = NULL; instance_t instance; @@ -232,7 +108,7 @@ void *MME_app_task(void *args_p) { /* Try to register each MCE */ // This assumes that node_type of all RRC instances is the same - if (EPC_MODE_ENABLED) { + if (!IS_SOFTMODEM_NOS1) { //register_mce_pending = MCE_app_register(RC.rrc[0]->node_type, mce_id_start, mce_id_end); } @@ -264,200 +140,26 @@ void *MME_app_task(void *args_p) { break; case M3AP_REGISTER_MCE_CNF: //M3AP_REGISTER_MCE_CNF deberÃa - //AssertFatal(!NODE_IS_DU(RC.rrc[0]->node_type), "Should not have received S1AP_REGISTER_ENB_CNF\n"); - // if (EPC_MODE_ENABLED) { - // LOG_I(MME_APP, "[MCE %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), - // M3AP_REGISTER_MCE_CNF(msg_p).nb_mme); - // DevAssert(register_mce_pending > 0); - // register_mce_pending--; - - // /* Check if at least MCE is registered with one MME */ - // if (M3AP_REGISTER_MCE_CNF(msg_p).nb_mme > 0) { - // registered_mce++; - // } - - // /* Check if all register MCE requests have been processed */ - // if (register_mce_pending == 0) { - // if (registered_mce == mce_nb) { - // /* If all MCE are registered, start L2L1 task */ - // // MessageDef *msg_init_p; - // // msg_init_p = itti_alloc_new_message (TASK_ENB_APP, 0, INITIALIZE_MESSAGE); - // // itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); - // } else { - // LOG_W(MME_APP, " %d MCE not associated with a MME, retrying registration in %d seconds ...\n", - // mce_nb - registered_mce, MCE_REGISTER_RETRY_DELAY); - - // /* Restart the MCE registration process in MCE_REGISTER_RETRY_DELAY seconds */ - // if (timer_setup (MCE_REGISTER_RETRY_DELAY, 0, TASK_MME_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT, - // NULL, &mce_register_retry_timer_id) < 0) { - // LOG_E(MME_APP, " Can not start MCE register retry timer, use \"sleep\" instead!\n"); - // sleep(MCE_REGISTER_RETRY_DELAY); - // /* Restart the registration process */ - // registered_mce = 0; - // register_mce_pending = MCE_app_register (RC.rrc[0]->node_type,mce_id_start, mce_id_end); - // } - // } - // } - // } /* if (EPC_MODE_ENABLED) */ - break; - // case M3AP_SETUP_RESP: - - // //LOG_I(MME_APP, "Received %s: associated ngran_MCE_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p), - // - // handle_m3ap_setup_resp(&M3AP_SETUP_RESP(msg_p)); - - // DevAssert(register_mce_pending > 0); - // register_mce_pending--; - - // /* Check if at least MCE is registered with one MME */ - // //if (M3AP_SETUP_RESP(msg_p).num_cells_to_activate > 0) { - // // registered_enb++; - // //} - - // /* Check if all register MCE requests have been processed */ - // if (register_mce_pending == 0) { - // if (registered_mce == mce_nb) { - // /* If all MCE cells are registered, start L2L1 task */ - // MessageDef *msg_init_p; - - // //msg_init_p = itti_alloc_new_message (TASK_MME_APP, 0, INITIALIZE_MESSAGE); - // //itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); - - // } else { - // LOG_W(MME_APP, " %d MCE not associated with a MME, retrying registration in %d seconds ...\n", - // mce_nb - registered_mce, MCE_REGISTER_RETRY_DELAY); - - // /* Restart the MCE registration process in MCE_REGISTER_RETRY_DELAY seconds */ - // if (timer_setup (MCE_REGISTER_RETRY_DELAY, 0, TASK_MME_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT, - // NULL, &mce_register_retry_timer_id) < 0) { - // LOG_E(ENB_APP, " Can not start MCE register retry timer, use \"sleep\" instead!\n"); - - // sleep(MCE_REGISTER_RETRY_DELAY); - // /* Restart the registration process */ - // registered_mce = 0; - // register_mce_pending = MCE_app_register (RC.rrc[0]->node_type,mce_id_start, mce_id_end);//, enb_properties_p); - // } - // } - // } - - // break; - case M3AP_DEREGISTERED_MCE_IND: //M3AP_DEREGISTERED_MCE_IND deberÃa - if (EPC_MODE_ENABLED) { - LOG_W(MME_APP, "[MCE %ld] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), - M3AP_DEREGISTERED_MCE_IND(msg_p).nb_mme); - /* TODO handle recovering of registration */ + if (!IS_SOFTMODEM_NOS1) { + LOG_W(MME_APP, + "[MCE %ld] Received %s: associated MME %d\n", + instance, + ITTI_MSG_NAME(msg_p), + M3AP_DEREGISTERED_MCE_IND(msg_p).nb_mme); + /* TODO handle recovering of registration */ } break; case TIMER_HAS_EXPIRED: - //if (EPC_MODE_ENABLED) { - // LOG_I(MME_APP, " Received %s: timer_id %ld\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id); - - // if (TIMER_HAS_EXPIRED (msg_p).timer_id == mce_register_retry_timer_id) { - // /* Restart the registration process */ - // registered_mce = 0; - // //register_mce_pending = MCE_app_register (RC.rrc[0]->node_type, mce_id_start, mce_id_end); - // } - - // //if (TIMER_HAS_EXPIRED (msg_p).timer_id == x2_mce_register_retry_timer_id) { - // // /* Restart the registration process */ - // // x2_registered_mce = 0; - // // x2_register_mce_pending = MCE_app_register_x2 (mce_id_start, mce_id_end); - // //} - //} /* if (EPC_MODE_ENABLED) */ - if(TIMER_HAS_EXPIRED(msg_p).timer_id == m3_mme_register_session_start_timer_id){ - MME_app_send_m3ap_session_start_req(0); + if (TIMER_HAS_EXPIRED(msg_p).timer_id == m3_mme_register_session_start_timer_id) { + MME_app_send_m3ap_session_start_req(0); } break; - - // case X2AP_DEREGISTERED_ENB_IND: - // LOG_W(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p), - // X2AP_DEREGISTERED_ENB_IND(msg_p).nb_x2); - // /* TODO handle recovering of registration */ - // break; - - // case X2AP_REGISTER_ENB_CNF: - // LOG_I(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p), - // X2AP_REGISTER_ENB_CNF(msg_p).nb_x2); - // DevAssert(x2_register_enb_pending > 0); - // x2_register_enb_pending--; - - // /* Check if at least MCE is registered with one target MCE */ - // if (X2AP_REGISTER_ENB_CNF(msg_p).nb_x2 > 0) { - // x2_registered_enb++; - // } - - // /* Check if all register MCE requests have been processed */ - // if (x2_register_enb_pending == 0) { - // if (x2_registered_enb == enb_nb) { - // /* If all MCE are registered, start RRC HO task */ - // } else { - // uint32_t x2_not_associated = enb_nb - x2_registered_enb; - // LOG_W(ENB_APP, " %d MCE %s not associated with the target\n", - // x2_not_associated, x2_not_associated > 1 ? "are" : "is"); - - // // timer to retry - // /* Restart the MCE registration process in ENB_REGISTER_RETRY_DELAY seconds */ - // if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP, - // INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL, - // &x2_enb_register_retry_timer_id) < 0) { - // LOG_E(ENB_APP, " Can not start MCE X2AP register: retry timer, use \"sleep\" instead!\n"); - // sleep(X2AP_ENB_REGISTER_RETRY_DELAY); - // /* Restart the registration process */ - // x2_registered_enb = 0; - // x2_register_enb_pending = MCE_app_register_x2 (enb_id_start, enb_id_end); - // } - // } - // } - - // break; - - // case M2AP_DEREGISTERED_ENB_IND: - // LOG_W(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p), - // M2AP_DEREGISTERED_ENB_IND(msg_p).nb_m2); - // /* TODO handle recovering of registration */ - // break; - - // case M2AP_REGISTER_ENB_CNF: - // LOG_I(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p), - // M2AP_REGISTER_ENB_CNF(msg_p).nb_m2); - // DevAssert(m2_register_enb_pending > 0); - // m2_register_enb_pending--; - - // /* Check if at least MCE is registered with one target MCE */ - // if (M2AP_REGISTER_ENB_CNF(msg_p).nb_m2 > 0) { - // m2_registered_enb++; - // } - - // /* Check if all register MCE requests have been processed */ - // if (m2_register_enb_pending == 0) { - // if (m2_registered_enb == enb_nb) { - // /* If all MCE are registered, start RRC HO task */ - // } else { - // uint32_t m2_not_associated = enb_nb - m2_registered_enb; - // LOG_W(ENB_APP, " %d MCE %s not associated with the target\n", - // m2_not_associated, m2_not_associated > 1 ? "are" : "is"); - - // // timer to retry - // /* Restart the MCE registration process in ENB_REGISTER_RETRY_DELAY seconds */ - // //if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP, - // // INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL, - // // &x2_enb_register_retry_timer_id) < 0) { - // // LOG_E(ENB_APP, " Can not start MCE X2AP register: retry timer, use \"sleep\" instead!\n"); - // // sleep(X2AP_ENB_REGISTER_RETRY_DELAY); - // // /* Restart the registration process */ - // // x2_registered_enb = 0; - // // x2_register_enb_pending = MCE_app_register_x2 (enb_id_start, enb_id_end); - // //} - // } - // } - - // break; case M3AP_RESET: LOG_I(MME_APP,"Received M3AP_RESET message %s\n",ITTI_MSG_NAME(msg_p)); break; diff --git a/openair3/NAS/CMakeLists.txt b/openair3/NAS/CMakeLists.txt new file mode 100644 index 0000000000..50cbedd280 --- /dev/null +++ b/openair3/NAS/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(COMMON) diff --git a/openair3/NAS/COMMON/CMakeLists.txt b/openair3/NAS/COMMON/CMakeLists.txt new file mode 100644 index 0000000000..21de73f92f --- /dev/null +++ b/openair3/NAS/COMMON/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(IES) +add_subdirectory(EMM) diff --git a/openair3/NAS/COMMON/EMM/CMakeLists.txt b/openair3/NAS/COMMON/EMM/CMakeLists.txt new file mode 100644 index 0000000000..1da5bad152 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(MSG) + +if(ENABLE_TESTS) + add_subdirectory(tests) +endif() diff --git a/openair3/NAS/COMMON/EMM/MSG/AttachRequest.c b/openair3/NAS/COMMON/EMM/MSG/AttachRequest.c index 7448a33419..8edac423c3 100644 --- a/openair3/NAS/COMMON/EMM/MSG/AttachRequest.c +++ b/openair3/NAS/COMMON/EMM/MSG/AttachRequest.c @@ -47,7 +47,7 @@ int decode_attach_request(attach_request_msg *attach_request, uint8_t *buffer, u LOG_FUNC_RETURN(decoded_result); } - if ((decoded_result = decode_u8_nas_key_set_identifier(&attach_request->naskeysetidentifier, 0, *(buffer + decoded) >> 4, len - decoded)) < 0) { + if ((decoded_result = decode_nas_key_set_identifier(&attach_request->naskeysetidentifier, 0, *(buffer + decoded) >> 4)) < 0) { // return decoded_result; LOG_FUNC_RETURN(decoded_result); } @@ -299,7 +299,8 @@ int encode_attach_request(attach_request_msg *attach_request, uint8_t *buffer, u /* Checking IEI and pointer */ CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, ATTACH_REQUEST_MINIMUM_LENGTH, len); - *(buffer + encoded) = ((encode_u8_nas_key_set_identifier(&attach_request->naskeysetidentifier) & 0x0f) << 4) | (encode_u8_eps_attach_type(&attach_request->epsattachtype) & 0x0f); + *(buffer + encoded) = ((encode_nas_key_set_identifier(&attach_request->naskeysetidentifier, 0) & 0x0f) << 4) + | (encode_u8_eps_attach_type(&attach_request->epsattachtype) & 0x0f); encoded++; if ((encode_result = diff --git a/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c b/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c index 0914353478..71477f3aeb 100644 --- a/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c +++ b/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c @@ -38,7 +38,8 @@ int decode_authentication_request(authentication_request_msg *authentication_req CHECK_PDU_POINTER_AND_LENGTH_DECODER(buffer, AUTHENTICATION_REQUEST_MINIMUM_LENGTH, len); /* Decoding mandatory fields */ - if ((decoded_result = decode_u8_nas_key_set_identifier(&authentication_request->naskeysetidentifierasme, 0, *(buffer + decoded), len - decoded)) < 0) + if ((decoded_result = decode_nas_key_set_identifier(&authentication_request->naskeysetidentifierasme, 0, *(buffer + decoded))) + < 0) return decoded_result; decoded++; @@ -64,7 +65,7 @@ int encode_authentication_request(authentication_request_msg *authentication_req /* Checking IEI and pointer */ CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, AUTHENTICATION_REQUEST_MINIMUM_LENGTH, len); - *(buffer + encoded) = ((encode_u8_nas_key_set_identifier(&authentication_request->naskeysetidentifierasme) & 0x0f) << 4) | 0x00; + *(buffer + encoded) = ((encode_nas_key_set_identifier(&authentication_request->naskeysetidentifierasme, 0) & 0x0f) << 4) | 0x00; encoded++; if ((encode_result = diff --git a/openair3/NAS/COMMON/EMM/MSG/CMakeLists.txt b/openair3/NAS/COMMON/EMM/MSG/CMakeLists.txt new file mode 100644 index 0000000000..fed78e453d --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/CMakeLists.txt @@ -0,0 +1,10 @@ +add_library(fgs_lib OBJECT + fgs_service_request.c +) + +target_link_libraries(fgs_lib PUBLIC fgs_ies_lib) + +target_include_directories(fgs_lib PUBLIC + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/openair3/NAS/COMMON/EMM/MSG/DetachRequest.c b/openair3/NAS/COMMON/EMM/MSG/DetachRequest.c index 1697ea17e2..8a63ea71c8 100644 --- a/openair3/NAS/COMMON/EMM/MSG/DetachRequest.c +++ b/openair3/NAS/COMMON/EMM/MSG/DetachRequest.c @@ -41,7 +41,7 @@ int decode_detach_request(detach_request_msg *detach_request, uint8_t *buffer, u if ((decoded_result = decode_u8_detach_type(&detach_request->detachtype, 0, *(buffer + decoded) & 0x0f, len - decoded)) < 0) return decoded_result; - if ((decoded_result = decode_u8_nas_key_set_identifier(&detach_request->naskeysetidentifier, 0, *(buffer + decoded) >> 4, len - decoded)) < 0) + if ((decoded_result = decode_nas_key_set_identifier(&detach_request->naskeysetidentifier, 0, *(buffer + decoded) >> 4)) < 0) return decoded_result; decoded++; @@ -62,7 +62,8 @@ int encode_detach_request(detach_request_msg *detach_request, uint8_t *buffer, u /* Checking IEI and pointer */ CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, DETACH_REQUEST_MINIMUM_LENGTH, len); - *(buffer + encoded) = ((encode_u8_nas_key_set_identifier(&detach_request->naskeysetidentifier) << 4) | (encode_u8_detach_type(&detach_request->detachtype) & 0x0f)); + *(buffer + encoded) = ((encode_nas_key_set_identifier(&detach_request->naskeysetidentifier, 0) << 4) + | (encode_u8_detach_type(&detach_request->detachtype) & 0x0f)); encoded++; if ((encode_result = encode_eps_mobile_identity(&detach_request->gutiorimsi, diff --git a/openair3/NAS/COMMON/EMM/MSG/ExtendedServiceRequest.c b/openair3/NAS/COMMON/EMM/MSG/ExtendedServiceRequest.c index a7ff89245b..99a556c7f3 100644 --- a/openair3/NAS/COMMON/EMM/MSG/ExtendedServiceRequest.c +++ b/openair3/NAS/COMMON/EMM/MSG/ExtendedServiceRequest.c @@ -41,7 +41,9 @@ int decode_extended_service_request(extended_service_request_msg *extended_servi if ((decoded_result = decode_u8_service_type(&extended_service_request->servicetype, 0, *(buffer + decoded) >> 4, len - decoded)) < 0) return decoded_result; - if ((decoded_result = decode_u8_nas_key_set_identifier(&extended_service_request->naskeysetidentifier, 0, *(buffer + decoded) & 0x0f, len - decoded)) < 0) + if ((decoded_result = + decode_nas_key_set_identifier(&extended_service_request->naskeysetidentifier, 0, *(buffer + decoded) & 0x0f)) + < 0) return decoded_result; decoded++; @@ -62,7 +64,8 @@ int encode_extended_service_request(extended_service_request_msg *extended_servi /* Checking IEI and pointer */ CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, EXTENDED_SERVICE_REQUEST_MINIMUM_LENGTH, len); - *(buffer + encoded) = ((encode_u8_service_type(&extended_service_request->servicetype) & 0x0f) << 4) | (encode_u8_nas_key_set_identifier(&extended_service_request->naskeysetidentifier) & 0x0f); + *(buffer + encoded) = ((encode_u8_service_type(&extended_service_request->servicetype) & 0x0f) << 4) + | (encode_nas_key_set_identifier(&extended_service_request->naskeysetidentifier, 0) & 0x0f); encoded++; if ((encode_result = diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c b/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c index 0d9a4bbac2..af8dfd8c20 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c +++ b/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c @@ -33,6 +33,7 @@ #include #include "FGSDeregistrationRequestUEOriginating.h" +#include "NR_NAS_defs.h" int encode_fgs_deregistration_request_ue_originating(fgs_deregistration_request_ue_originating_msg *drr, uint8_t *buffer, @@ -45,7 +46,7 @@ int encode_fgs_deregistration_request_ue_originating(fgs_deregistration_request_ | ((dt->access_type & 0x3) << 4); int encode_result; - if ((encode_result = encode_nas_key_set_identifier(&drr->naskeysetidentifier, 0, buffer + encoded, len - encoded)) < 0) + if ((encode_result = encode_nas_key_set_identifier(&drr->naskeysetidentifier, IEI_NULL)) < 0) return encode_result; encoded++; diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.c b/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.c index 3d177c396a..cf18e46ca2 100644 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.c +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.c @@ -35,6 +35,7 @@ #include "nas_log.h" #include "RegistrationRequest.h" +#include "NR_NAS_defs.h" int decode_registration_request(registration_request_msg *registration_request, uint8_t *buffer, uint32_t len) { @@ -51,7 +52,8 @@ int decode_registration_request(registration_request_msg *registration_request, LOG_FUNC_RETURN(decoded_result); } - if ((decoded_result = decode_u8_nas_key_set_identifier(®istration_request->naskeysetidentifier, 0, *(buffer + decoded) >> 4, len - decoded)) < 0) { + if ((decoded_result = decode_nas_key_set_identifier(®istration_request->naskeysetidentifier, IEI_NULL, *(buffer + decoded) >> 4)) + < 0) { // return decoded_result; LOG_FUNC_RETURN(decoded_result); } @@ -75,7 +77,8 @@ int encode_registration_request(registration_request_msg *registration_request, int encoded = 0; int encode_result = 0; - *(buffer + encoded) = ((encode_u8_nas_key_set_identifier(®istration_request->naskeysetidentifier) & 0x0f) << 4) | (encode_5gs_registration_type(®istration_request->fgsregistrationtype) & 0x0f); + *(buffer + encoded) = ((encode_nas_key_set_identifier(®istration_request->naskeysetidentifier, IEI_NULL) & 0x0f) << 4) + | (encode_5gs_registration_type(®istration_request->fgsregistrationtype) & 0x0f); encoded++; if ((encode_result = diff --git a/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c b/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c index 25181d8e79..2e936e6a94 100644 --- a/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c +++ b/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c @@ -43,7 +43,8 @@ int decode_security_mode_command(security_mode_command_msg *security_mode_comman else decoded += decoded_result; - if ((decoded_result = decode_u8_nas_key_set_identifier(&security_mode_command->naskeysetidentifier, 0, *(buffer + decoded) & 0x0f, len - decoded)) < 0) + if ((decoded_result = decode_nas_key_set_identifier(&security_mode_command->naskeysetidentifier, 0, *(buffer + decoded) & 0x0f)) + < 0) return decoded_result; decoded++; @@ -124,7 +125,7 @@ int encode_security_mode_command(security_mode_command_msg *security_mode_comman else encoded += encode_result; - *(buffer + encoded) = (encode_u8_nas_key_set_identifier(&security_mode_command->naskeysetidentifier) & 0x0f); + *(buffer + encoded) = (encode_nas_key_set_identifier(&security_mode_command->naskeysetidentifier, 0) & 0x0f); encoded++; if ((encode_result = diff --git a/openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateRequest.c b/openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateRequest.c index 49632057c0..83968bc2c6 100644 --- a/openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateRequest.c +++ b/openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateRequest.c @@ -41,7 +41,9 @@ int decode_tracking_area_update_request(tracking_area_update_request_msg *tracki if ((decoded_result = decode_u8_eps_update_type(&tracking_area_update_request->epsupdatetype, 0, *(buffer + decoded) >> 4, len - decoded)) < 0) return decoded_result; - if ((decoded_result = decode_u8_nas_key_set_identifier(&tracking_area_update_request->naskeysetidentifier, 0, *(buffer + decoded) & 0x0f, len - decoded)) < 0) + if ((decoded_result = + decode_nas_key_set_identifier(&tracking_area_update_request->naskeysetidentifier, 0, *(buffer + decoded) & 0x0f)) + < 0) return decoded_result; decoded++; @@ -61,10 +63,10 @@ int decode_tracking_area_update_request(tracking_area_update_request_msg *tracki switch(ieiDecoded) { case TRACKING_AREA_UPDATE_REQUEST_NONCURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_IEI: - if ((decoded_result = - decode_nas_key_set_identifier(&tracking_area_update_request->noncurrentnativenaskeysetidentifier, - TRACKING_AREA_UPDATE_REQUEST_NONCURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_IEI, - buffer + decoded, len - decoded)) <= 0) + if ((decoded_result = decode_nas_key_set_identifier(&tracking_area_update_request->noncurrentnativenaskeysetidentifier, + TRACKING_AREA_UPDATE_REQUEST_NONCURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_IEI, + *(buffer + decoded))) + <= 0) return decoded_result; decoded += decoded_result; @@ -293,8 +295,8 @@ int encode_tracking_area_update_request(tracking_area_update_request_msg *tracki /* Checking IEI and pointer */ CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, TRACKING_AREA_UPDATE_REQUEST_MINIMUM_LENGTH, len); - *(buffer + encoded) = ((encode_u8_eps_update_type(&tracking_area_update_request->epsupdatetype) & 0x0f) << 4) | (encode_u8_nas_key_set_identifier( - &tracking_area_update_request->naskeysetidentifier) & 0x0f); + *(buffer + encoded) = ((encode_u8_eps_update_type(&tracking_area_update_request->epsupdatetype) & 0x0f) << 4) + | (encode_nas_key_set_identifier(&tracking_area_update_request->naskeysetidentifier, 0) & 0x0f); encoded++; if ((encode_result = @@ -306,10 +308,9 @@ int encode_tracking_area_update_request(tracking_area_update_request_msg *tracki if ((tracking_area_update_request->presencemask & TRACKING_AREA_UPDATE_REQUEST_NONCURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_PRESENT) == TRACKING_AREA_UPDATE_REQUEST_NONCURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_PRESENT) { - if ((encode_result = - encode_nas_key_set_identifier(&tracking_area_update_request->noncurrentnativenaskeysetidentifier, - TRACKING_AREA_UPDATE_REQUEST_NONCURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_IEI, - buffer + encoded, len - encoded)) < 0) + if ((encode_result = encode_nas_key_set_identifier(&tracking_area_update_request->noncurrentnativenaskeysetidentifier, + TRACKING_AREA_UPDATE_REQUEST_NONCURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_IEI)) + < 0) // Return in case of error return encode_result; else diff --git a/openair3/NAS/COMMON/EMM/MSG/fgs_service_request.c b/openair3/NAS/COMMON/EMM/MSG/fgs_service_request.c new file mode 100644 index 0000000000..85e67498a5 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/fgs_service_request.c @@ -0,0 +1,90 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include +#include + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "fgs_service_request.h" +#include "FGSMobileIdentity.h" +#include "NasKeySetIdentifier.h" +#include "ServiceType.h" +#include "NR_NAS_defs.h" + +#define LEN_FGS_MOBILE_ID_CONTENTS_SIZE 2 // octets +#define MIN_LEN_FGS_SERVICE_REQUEST 10 // octets + +/** + * @brief Encode 5GMM NAS Service Request message (8.2.16 of 3GPP TS 24.501) + */ +int encode_fgs_service_request(uint8_t *buffer, fgs_service_request_msg_t *service_request, uint32_t len) +{ + // Return if buffer is shorter than min length + if (len < MIN_LEN_FGS_SERVICE_REQUEST) + return -1; + + int encoded = 0; + + // ngKSI + Service type (1 octet) (M) + *buffer = ((encode_nas_key_set_identifier(&service_request->naskeysetidentifier, IEI_NULL) & 0x0f) << 4) + | (service_request->serviceType & 0x0f); + encoded++; + len -= encoded; + + // 5GS Mobile Identity (M) type 5G-S-TMSI (9 octets) + encoded += LEN_FGS_MOBILE_ID_CONTENTS_SIZE; // skip "Length of 5GS mobile identity contents" IE + len -= encoded; + encoded += encode_stmsi_5gs_mobile_identity(buffer + encoded, &service_request->fiveg_s_tmsi, len); + // encode length of 5GS mobile identity contents + uint16_t tmp = htons(encoded - LEN_FGS_MOBILE_ID_CONTENTS_SIZE - 1); + memcpy(buffer + 1, &tmp, sizeof(tmp)); + + return encoded; +} + +/** + * @brief Decode 5GMM NAS Service Request message (8.2.16 of 3GPP TS 24.501) + */ +int decode_fgs_service_request(fgs_service_request_msg_t *sr, const uint8_t *buffer, uint32_t len) +{ + uint32_t decoded = 0; + int decoded_rc = 0; + + // Service type (1/2 octet) (M) + sr->serviceType = *buffer & 0x0f; + // KSI (1/2 octet) (M) + if ((decoded_rc = decode_nas_key_set_identifier(&sr->naskeysetidentifier, IEI_NULL, *buffer >> 4)) < 0) { + return decoded_rc; + } + decoded++; + + // 5GS Mobile Identity (M) type 5G-S-TMSI (9 octets) (M) + decoded += LEN_FGS_MOBILE_ID_CONTENTS_SIZE; // skip "Length of 5GS mobile identity contents" IE + if ((decoded_rc = decode_stmsi_5gs_mobile_identity(&sr->fiveg_s_tmsi, buffer + decoded, len - decoded)) < 0) { + return decoded_rc; + } + decoded += decoded_rc; + + return decoded; +} diff --git a/openair3/NAS/COMMON/EMM/MSG/fgs_service_request.h b/openair3/NAS/COMMON/EMM/MSG/fgs_service_request.h new file mode 100644 index 0000000000..eecd1ee34a --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/fgs_service_request.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.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include + +#include "ProtocolDiscriminator.h" +#include "SecurityHeaderType.h" +#include "NasKeySetIdentifier.h" +#include "ServiceType.h" +#include "ExtendedProtocolDiscriminator.h" +#include "FGCNasMessageContainer.h" +//#include "PDUSessionStatus.h" +#include "MessageType.h" +#include "SpareHalfOctet.h" +#include "FGSMobileIdentity.h" + +#ifndef FGS_SERVICE_REQUEST_H_ +#define FGS_SERVICE_REQUEST_H_ + +/** + * Message name: Service request (8.2.16 of 3GPP TS 24.501) + * Description: The SERVICE REQUEST message is sent by the UE to the AMF + * in order to request the establishment of an N1 NAS signalling + * connection and/or to request the establishment of user-plane + * resources for PDU sessions which are established without + * user-plane resources + * Direction: UE to network + */ + +typedef struct { + /* Mandatory fields */ + NasKeySetIdentifier naskeysetidentifier; + ServiceType serviceType: 4; + Stmsi5GSMobileIdentity_t fiveg_s_tmsi; + /* Optional fields */ + FGCNasMessageContainer *fgsnasmessagecontainer; +} fgs_service_request_msg_t; + +int encode_fgs_service_request(uint8_t *buffer, fgs_service_request_msg_t *servicerequest, uint32_t len); +int decode_fgs_service_request(fgs_service_request_msg_t *sr, const uint8_t *buffer, uint32_t len); + +#endif /* ! defined(FGS_SERVICE_REQUEST_H_) */ diff --git a/openair3/NAS/COMMON/EMM/tests/CMakeLists.txt b/openair3/NAS/COMMON/EMM/tests/CMakeLists.txt new file mode 100644 index 0000000000..3f960c5562 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/tests/CMakeLists.txt @@ -0,0 +1,13 @@ +message(STATUS "Add test nas_lib_test") + +add_executable(nas_lib_test nas_lib_test.c) + +add_dependencies(tests nas_lib_test) +add_test(NAME nas_lib_test COMMAND nas_lib_test) + +target_link_libraries(nas_lib_test PRIVATE fgs_lib fgs_ies_lib) + +target_include_directories(nas_lib_test PRIVATE + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/openair3/NAS/COMMON/EMM/tests/nas_lib_test.c b/openair3/NAS/COMMON/EMM/tests/nas_lib_test.c new file mode 100644 index 0000000000..41865051cd --- /dev/null +++ b/openair3/NAS/COMMON/EMM/tests/nas_lib_test.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include "fgs_service_request.h" +#include "nr_nas_msg.h" + +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + printf("detected error at %s:%d:%s: %s\n", file, line, function, s); + abort(); +} + +/** + * @brief Equality check for NAS Service Request enc/dec + */ +static bool eq_service_request(const fgs_service_request_msg_t *a, const fgs_service_request_msg_t *b) +{ + bool result = true; + result &= memcmp(&a->naskeysetidentifier, &b->naskeysetidentifier, sizeof(NasKeySetIdentifier)) == 0; + result &= a->serviceType == b->serviceType; + result &= memcmp(&a->fiveg_s_tmsi, &b->fiveg_s_tmsi, sizeof(Stmsi5GSMobileIdentity_t)) == 0; + return result; +} + +/** + * @brief Test NAS Service Request enc/dec + */ +static void test_service_request(void) +{ + // Dummy NAS Service Request message + uint16_t amf_set_id = 0x48; + uint16_t amf_pointer = 0x34; + uint32_t tmsi = 0x56789ABC; + fgs_service_request_msg_t original_msg = { + .naskeysetidentifier = {.tsc = NAS_KEY_SET_IDENTIFIER_NATIVE, .naskeysetidentifier = NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE}, + .serviceType = SERVICE_TYPE_DATA, + .fiveg_s_tmsi = {.spare = 0, + .typeofidentity = FGS_MOBILE_IDENTITY_5GS_TMSI, + .amfsetid = amf_set_id, + .amfpointer = amf_pointer, + .tmsi = tmsi}}; + + uint8_t expected_encoded_data[] = {0x71, + 0x00, + 0x00, + 0xF4, + (amf_set_id >> 2) & 0xFF, + (amf_set_id << 6) | (amf_pointer & 0x3F), + (tmsi >> 24) & 0xFF, + (tmsi >> 16) & 0xFF, + (tmsi >> 8) & 0xFF, + tmsi & 0xFF}; + uint16_t tmp = htons(7); // length of 5GS mobile identity IE for 5G-S-TMSI (bytes) + memcpy(expected_encoded_data + 1, &tmp, sizeof(tmp)); + + // Buffer + uint8_t buffer[64]; + memset(buffer, 0, sizeof(buffer)); + + // Encode NAS Service Request + int encoded_length = encode_fgs_service_request(buffer, &original_msg, sizeof(buffer)); + AssertFatal(encoded_length >= 0, "encode_fgs_service_request() failed\n"); + + // Compare the raw encoded buffer with expected encoded data + AssertFatal(memcmp(buffer, expected_encoded_data, encoded_length) == 0, "Encoding mismatch!\n"); + + // Decode NAS Service Request + fgs_service_request_msg_t decoded_service_request = {0}; + int decoded_length = decode_fgs_service_request(&decoded_service_request, buffer, sizeof(buffer)); + AssertFatal(decoded_length >= 0, "decode_fgs_service_request() failed\n"); + + // Compare original and decoded messages + AssertFatal(eq_service_request(&original_msg, &decoded_service_request) == 0, + "test_service_request() failed: original and decoded messages do not match\n"); +} + +int main() +{ + test_service_request(); + return 0; +} diff --git a/openair3/NAS/COMMON/IES/CMakeLists.txt b/openair3/NAS/COMMON/IES/CMakeLists.txt new file mode 100644 index 0000000000..99df08e7b0 --- /dev/null +++ b/openair3/NAS/COMMON/IES/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(fgs_ies_lib OBJECT + NasKeySetIdentifier.c + FGSMobileIdentity.c +) + +target_include_directories(fgs_ies_lib PUBLIC + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/openair3/NAS/COMMON/IES/FGSMobileIdentity.c b/openair3/NAS/COMMON/IES/FGSMobileIdentity.c index c0b60f101f..f70dfc66ed 100644 --- a/openair3/NAS/COMMON/IES/FGSMobileIdentity.c +++ b/openair3/NAS/COMMON/IES/FGSMobileIdentity.c @@ -31,18 +31,71 @@ #include #include #include - +#include #include "TLVEncoder.h" #include "TLVDecoder.h" #include "FGSMobileIdentity.h" +#define MIN_LEN_FGS_MOBILE_ID_IE 3 // type of identity "No identity" +#define LEN_5G_FGS_TMSI_IE 9 + static int decode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, const uint8_t *buffer); static int encode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_t *buffer); static int encode_suci_5gs_mobile_identity(Suci5GSMobileIdentity_t *suci, uint8_t *buffer); static int encode_imeisv_5gs_mobile_identity(Imeisv5GSMobileIdentity_t *imeisv, uint8_t *buffer); +int encode_stmsi_5gs_mobile_identity(uint8_t *buffer, Stmsi5GSMobileIdentity_t *stmsi, uint32_t len) +{ + // Return if buffer is shorter than min length + if (len < LEN_5G_FGS_TMSI_IE) + return -1; + + uint32_t encoded = 0; + // octet 4 + *(buffer + encoded) = (DIGIT1 << 4) | ((stmsi->spare & 0x1) << 3) | (stmsi->typeofidentity & 0x7); + encoded++; + // octet 5-6 + uint16_t temp = 0x00 | ((stmsi->amfsetid) << 6) | (stmsi->amfpointer & 0x3f); + IES_ENCODE_U16(buffer, encoded, temp); + // octet 7 + IES_ENCODE_U32(buffer, encoded, stmsi->tmsi); + return encoded; +} + +int decode_stmsi_5gs_mobile_identity(Stmsi5GSMobileIdentity_t *stmsi, const uint8_t *buffer, uint32_t len) +{ + int decoded = 0; + uint16_t temp; + + // Return if buffer is shorter than min length + if (len < LEN_5G_FGS_TMSI_IE) + return -1; + + // Octet 4: spare (bit 3) and type of identity (bits 0-2) + stmsi->digit1 = DIGIT1; + stmsi->spare = (*(buffer + decoded) >> 3) & 0x1; + stmsi->typeofidentity = *(buffer + decoded) & 0x7; + + // Validate type of identity + if (stmsi->typeofidentity != FGS_MOBILE_IDENTITY_5GS_TMSI) { + return -1; + } + + decoded++; + + // Octet 5-6: AMF Set ID (bits 6-15) and AMF Pointer (bits 0-5) + IES_DECODE_U16(buffer, decoded, temp); + stmsi->amfsetid = (temp >> 6) & 0x03ff; + stmsi->amfpointer = temp & 0x3f; + + // Octet 7-10: 32-bit TMSI + IES_DECODE_U32(buffer, decoded, stmsi->tmsi); + + return decoded; +} + int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, const uint8_t *buffer, uint32_t len) { int decoded_rc = TLV_DECODE_VALUE_DOESNT_MATCH; @@ -77,6 +130,10 @@ int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len) { + // Return if buffer is shorter than min length + if (len < MIN_LEN_FGS_MOBILE_ID_IE) + return -1; + int encoded_rc = TLV_ENCODE_VALUE_DOESNT_MATCH; uint32_t encoded = 0; @@ -86,6 +143,7 @@ int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei } encoded = encoded + 2; + len -= encoded; if (fgsmobileidentity->guti.typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI) { encoded_rc = encode_guti_5gs_mobile_identity(&fgsmobileidentity->guti, @@ -102,6 +160,10 @@ int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei buffer + encoded); } + if (fgsmobileidentity->stmsi.typeofidentity == FGS_MOBILE_IDENTITY_5GS_TMSI) { + encoded_rc = encode_stmsi_5gs_mobile_identity(buffer + encoded, &fgsmobileidentity->stmsi, len); + } + if (encoded_rc < 0) { return encoded_rc; } diff --git a/openair3/NAS/COMMON/IES/FGSMobileIdentity.h b/openair3/NAS/COMMON/IES/FGSMobileIdentity.h index 9356a46eff..e4747461e9 100644 --- a/openair3/NAS/COMMON/IES/FGSMobileIdentity.h +++ b/openair3/NAS/COMMON/IES/FGSMobileIdentity.h @@ -37,6 +37,8 @@ #ifndef FGS_MOBILE_IDENTITY_H_ #define FGS_MOBILE_IDENTITY_H_ +// 4x 1bit according to 9.11.3.4 5GS mobile identity (type 5G-S-TMSI) +#define DIGIT1 0xF typedef struct { uint8_t spare:5; @@ -151,5 +153,8 @@ int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, const uint8_t *buffer, uint32_t len); +int encode_stmsi_5gs_mobile_identity(uint8_t *buffer, Stmsi5GSMobileIdentity_t *stmsi, uint32_t len); +int decode_stmsi_5gs_mobile_identity(Stmsi5GSMobileIdentity_t *stmsi, const uint8_t *buffer, uint32_t len); + #endif /* FGS MOBILE IDENTITY_H_ */ diff --git a/openair3/NAS/COMMON/IES/NasKeySetIdentifier.c b/openair3/NAS/COMMON/IES/NasKeySetIdentifier.c index a547675675..82fe69d79e 100644 --- a/openair3/NAS/COMMON/IES/NasKeySetIdentifier.c +++ b/openair3/NAS/COMMON/IES/NasKeySetIdentifier.c @@ -28,67 +28,34 @@ #include "TLVDecoder.h" #include "NasKeySetIdentifier.h" -int decode_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei, uint8_t *buffer, uint32_t len) +/** + * @brief Decode the NAS key set identifier from one byte + */ +int decode_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei, uint8_t value) { - int decoded = 0; - CHECK_PDU_POINTER_AND_LENGTH_DECODER(buffer, NAS_KEY_SET_IDENTIFIER_MINIMUM_LENGTH, len); - if (iei > 0) { - CHECK_IEI_DECODER((*buffer & 0xf0), iei); + CHECK_IEI_DECODER((value & 0xf0), iei); } - naskeysetidentifier->tsc = (*(buffer + decoded) >> 3) & 0x1; - naskeysetidentifier->naskeysetidentifier = *(buffer + decoded) & 0x7; - decoded++; + naskeysetidentifier->tsc = (value >> 3) & 0x1; + naskeysetidentifier->naskeysetidentifier = value & 0x7; + +#if defined(NAS_DEBUG) + dump_nas_key_set_identifier_xml(naskeysetidentifier, iei); +#endif + + return 1; // 1 octet +} + +/** + * @brief Encode the NAS key set identifier in one byte + */ +uint8_t encode_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei) +{ #if defined (NAS_DEBUG) dump_nas_key_set_identifier_xml(naskeysetidentifier, iei); #endif - return decoded; -} - -int decode_u8_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei, uint8_t value, uint32_t len) -{ - int decoded = 0; - uint8_t *buffer = &value; - naskeysetidentifier->tsc = (*(buffer + decoded) >> 3) & 0x1; - naskeysetidentifier->naskeysetidentifier = *(buffer + decoded) & 0x7; - decoded++; -#if defined (NAS_DEBUG) - dump_nas_key_set_identifier_xml(naskeysetidentifier, iei); -#endif - return decoded; -} - -int encode_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei, uint8_t *buffer, uint32_t len) -{ - uint8_t encoded = 0; - /* Checking length and pointer */ - CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, NAS_KEY_SET_IDENTIFIER_MINIMUM_LENGTH, len); -#if defined (NAS_DEBUG) - dump_nas_key_set_identifier_xml(naskeysetidentifier, iei); -#endif - *(buffer + encoded) = 0x00 | (iei & 0xf0) | - ((naskeysetidentifier->tsc & 0x1) << 3) | - (naskeysetidentifier->naskeysetidentifier & 0x7); - encoded++; - return encoded; -} - -uint8_t encode_u8_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier) -{ - uint8_t bufferReturn; - uint8_t *buffer = &bufferReturn; - uint8_t encoded = 0; - uint8_t iei = 0; -#if defined (NAS_DEBUG) - dump_nas_key_set_identifier_xml(naskeysetidentifier, 0); -#endif - *(buffer + encoded) = 0x00 | (iei & 0xf0) | - ((naskeysetidentifier->tsc & 0x1) << 3) | - (naskeysetidentifier->naskeysetidentifier & 0x7); - encoded++; - - return bufferReturn; + return ((iei & 0xf0) | (naskeysetidentifier->tsc & 0x1) << 3) | (naskeysetidentifier->naskeysetidentifier & 0x7); } void dump_nas_key_set_identifier_xml(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei) diff --git a/openair3/NAS/COMMON/IES/NasKeySetIdentifier.h b/openair3/NAS/COMMON/IES/NasKeySetIdentifier.h index 09daf13a56..5f6b445fc4 100644 --- a/openair3/NAS/COMMON/IES/NasKeySetIdentifier.h +++ b/openair3/NAS/COMMON/IES/NasKeySetIdentifier.h @@ -39,15 +39,11 @@ typedef struct NasKeySetIdentifier_tag { uint8_t naskeysetidentifier:3; } NasKeySetIdentifier; -int encode_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei, uint8_t *buffer, uint32_t len); +uint8_t encode_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei); void dump_nas_key_set_identifier_xml(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei); -uint8_t encode_u8_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier); - -int decode_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei, uint8_t *buffer, uint32_t len); - -int decode_u8_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei, uint8_t value, uint32_t len); +int decode_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei, uint8_t value); #endif /* NAS KEY SET IDENTIFIER_H_ */ diff --git a/openair3/NAS/COMMON/NR_NAS_defs.h b/openair3/NAS/COMMON/NR_NAS_defs.h index f49852f62c..f5510e5392 100644 --- a/openair3/NAS/COMMON/NR_NAS_defs.h +++ b/openair3/NAS/COMMON/NR_NAS_defs.h @@ -25,7 +25,6 @@ #include #include -#include /* TS 24.007 possible L3 formats: Table 11.1: Formats of information elements @@ -72,9 +71,9 @@ typedef enum { TYPE_DEF(FGS_DEREGISTRATION_ACCEPT_UE_ORIGINATING, 0x46) \ TYPE_DEF(DeregistrationrequestUEterminated, 0x47) \ TYPE_DEF(DeregistrationacceptUEterminated, 0x48) \ - TYPE_DEF(Servicerequest, 0x4c) \ - TYPE_DEF(Servicereject, 0x4d) \ - TYPE_DEF(Serviceaccept, 0x4e) \ + TYPE_DEF(FGS_SERVICE_REQUEST, 0x4c) \ + TYPE_DEF(FGS_SERVICE_REJECT, 0x4d) \ + TYPE_DEF(FGS_SERVICE_ACCEPT, 0x4e) \ TYPE_DEF(Controlplaneservicerequest, 0x4f) \ TYPE_DEF(Networkslicespecificauthenticationcommand, 0x50) \ TYPE_DEF(Networkslicespecificauthenticationcomplete, 0x51) \ @@ -257,6 +256,7 @@ typedef enum { } cause_secu_id_t; // IEI (information element identifier) are spread in each message definition +#define IEI_NULL 0x00 #define IEI_RAND 0x21 #define IEI_AUTN 0x20 #define IEI_EAP 0x78 @@ -381,18 +381,6 @@ int resToresStar(uint8_t *msg, const uicc_t* uicc); int identityResponse(void **msg, nr_user_nas_t *UE); int authenticationResponse(void **msg, nr_user_nas_t *UE); -void UEprocessNAS(void *msg,nr_user_nas_t *UE); -void SGSabortUE(void *msg, NRUEcontext_t *UE) ; -void SGSregistrationReq(void *msg, NRUEcontext_t *UE); -void SGSderegistrationUEReq(void *msg, NRUEcontext_t *UE); -void SGSauthenticationResp(void *msg, NRUEcontext_t *UE); -void SGSidentityResp(void *msg, NRUEcontext_t *UE); -void SGSsecurityModeComplete(void *msg, NRUEcontext_t *UE); -void SGSregistrationComplete(void *msg, NRUEcontext_t *UE); -void processNAS(void *msg, NRUEcontext_t *UE); -int identityRequest(void **msg, NRUEcontext_t *UE); -int authenticationRequest(void **msg, NRUEcontext_t *UE); -int securityModeCommand(void **msg, NRUEcontext_t *UE); void servingNetworkName(uint8_t *msg, char * imsiStr, int nmc_size); #endif diff --git a/openair3/NAS/COMMON/UTIL/TLVDecoder.c b/openair3/NAS/COMMON/UTIL/TLVDecoder.c index 0ed4b6f456..625176319e 100644 --- a/openair3/NAS/COMMON/UTIL/TLVDecoder.c +++ b/openair3/NAS/COMMON/UTIL/TLVDecoder.c @@ -23,28 +23,4 @@ #include #include -#include "TLVDecoder.h" - int errorCodeDecoder = 0; - -static const char* const errorCodeStringDecoder[] = { - "No error", - "Buffer NULL", - "Buffer too short", - "Unexpected IEI", - "Mandatory field not present", - "Wrong message type", - "EXT value doesn't match", - "Protocol not supported", -}; - -void tlv_decode_perror(void) -{ - if (errorCodeDecoder >= 0) - // No error or TLV_DECODE_ERR_OK - return; - - printf("TLV decoder error: (%d, %s)\n", errorCodeDecoder, errorCodeStringDecoder[errorCodeDecoder * -1]); -} - - diff --git a/openair3/NAS/COMMON/UTIL/TLVDecoder.h b/openair3/NAS/COMMON/UTIL/TLVDecoder.h index 1f93d7a554..90b95cd6bb 100644 --- a/openair3/NAS/COMMON/UTIL/TLVDecoder.h +++ b/openair3/NAS/COMMON/UTIL/TLVDecoder.h @@ -95,48 +95,56 @@ typedef enum { extern int errorCodeDecoder; -void tlv_decode_perror(void); +#ifdef ENABLE_TESTS +#define TLV_DEC_ERROR(...) fprintf(stderr, "TLV Decoder: " __VA_ARGS__) +#else +#define TLV_DEC_ERROR(...) // Do nothing +#endif -#define CHECK_PDU_POINTER_AND_LENGTH_DECODER(bUFFER, mINIMUMlENGTH, lENGTH) \ - if (bUFFER == NULL) \ - { \ - printf("(%s:%d) Got NULL pointer for the payload\n", \ - __FILE__, __LINE__); \ - errorCodeDecoder = TLV_DECODE_BUFFER_NULL; \ - LOG_FUNC_RETURN(TLV_DECODE_BUFFER_NULL); \ - } \ - if (lENGTH < mINIMUMlENGTH) \ - { \ - printf("(%s:%d) Expecting at least %d bytes, got %u\n", \ - __FILE__, __LINE__, mINIMUMlENGTH, lENGTH); \ - errorCodeDecoder = TLV_DECODE_BUFFER_TOO_SHORT; \ - LOG_FUNC_RETURN(TLV_DECODE_BUFFER_TOO_SHORT); \ - } +#define CHECK_PDU_POINTER_AND_LENGTH_DECODER(bUFFER, mINIMUMlENGTH, lENGTH) \ + do { \ + if ((bUFFER) == NULL) { \ + TLV_DEC_ERROR("(%s:%d) Got NULL pointer for the payload\n", __FILE__, __LINE__); \ + return TLV_DECODE_BUFFER_NULL; \ + } \ + if ((lENGTH) < (mINIMUMlENGTH)) { \ + TLV_DEC_ERROR("(%s:%d) Expecting at least %d bytes, got %u\n", __FILE__, __LINE__, (mINIMUMlENGTH), (lENGTH)); \ + return TLV_DECODE_BUFFER_TOO_SHORT; \ + } \ + } while (0) -#define CHECK_LENGTH_DECODER(bUFFERlENGTH, lENGTH) \ - if (bUFFERlENGTH < lENGTH) \ - { \ - errorCodeDecoder = TLV_DECODE_BUFFER_TOO_SHORT; \ - LOG_FUNC_RETURN(TLV_DECODE_BUFFER_TOO_SHORT); \ - } +#define CHECK_LENGTH_DECODER(bUFFERlENGTH, lENGTH) \ + do { \ + if ((bUFFERlENGTH) < (lENGTH)) { \ + TLV_DEC_ERROR("(%s:%d) Buffer is too short, length (%u) is less than the required length (%u)\n", \ + __FILE__, \ + __LINE__, \ + (bUFFERlENGTH), \ + (lENGTH)); \ + return TLV_DECODE_BUFFER_TOO_SHORT; \ + } \ + } while (0) -#define CHECK_MESSAGE_TYPE(mESSAGE_tYPE, bUFFER) \ - { \ - if (mESSAGE_tYPE != bUFFER) \ - { \ - errorCodeDecoder = TLV_DECODE_WRONG_MESSAGE_TYPE; \ - LOG_FUNC_RETURN(errorCodeDecoder); \ - } \ - } +#define CHECK_MESSAGE_TYPE(mESSAGE_TYPE, BUFFER) \ + do { \ + if ((MESSAGE_TYPE) != (BUFFER)) { \ + TLV_DEC_ERROR("(%s:%d) Wrong message type: Got: %u, Expected: %u\n", __FILE__, __LINE__, (BUFFER), (MESSAGE_TYPE)); \ + return TLV_DECODE_WRONG_MESSAGE_TYPE; \ + } \ + } while (0) -#define CHECK_IEI_DECODER(iEI, bUFFER) \ - if(iEI != bUFFER) \ - { \ - printf("IEI is different than the one expected." \ - "(Got: 0x%x, expecting: 0x%x)\n", bUFFER, iEI); \ - errorCodeDecoder = TLV_DECODE_UNEXPECTED_IEI; \ - LOG_FUNC_RETURN(TLV_DECODE_UNEXPECTED_IEI); \ - } +#define CHECK_IEI_DECODER(iEI, bUFFER) \ + do { \ + if ((iEI) != (bUFFER)) { \ + TLV_DEC_ERROR( \ + "IEI check failure: %s:%d: IEI is different than the one expected: " \ + "(Got: 0x%x, expecting: 0x%x)\n", \ + __FILE__, \ + __LINE__, \ + (bUFFER), \ + (iEI)); \ + return TLV_DECODE_UNEXPECTED_IEI; \ + } \ + } while (0) #endif /* define (TLV_DECODER_H_) */ - diff --git a/openair3/NAS/COMMON/UTIL/TLVEncoder.h b/openair3/NAS/COMMON/UTIL/TLVEncoder.h index 8b85185361..a400d9e388 100644 --- a/openair3/NAS/COMMON/UTIL/TLVEncoder.h +++ b/openair3/NAS/COMMON/UTIL/TLVEncoder.h @@ -84,32 +84,32 @@ typedef enum { * it cannot be further processed */ #define TLV_ENCODE_FATAL_ERROR (TLV_ENCODE_VALUE_DOESNT_MATCH) -extern int errorCodeEncoder; +#ifdef ENABLE_TESTS +#define TLV_ENC_ERROR(...) fprintf(stderr, "TLV Encoder: " __VA_ARGS__) +#else +#define TLV_ENC_ERROR(...) // Do nothing +#endif -void tlv_encode_perror(void); +#define CHECK_PDU_POINTER_AND_LENGTH_ENCODER(bUFFER, mINIMUMlENGTH, lENGTH) \ + do { \ + if ((bUFFER) == NULL) { \ + TLV_ENC_ERROR("Got NULL pointer for the payload\n"); \ + return TLV_ENCODE_BUFFER_NULL; \ + } \ + if ((lENGTH) < (mINIMUMlENGTH)) { \ + TLV_ENC_ERROR("(%s:%d) Expecting at least %d bytes, got %u\n", __FILE__, __LINE__, (mINIMUMlENGTH), (lENGTH)); \ + return TLV_ENCODE_BUFFER_TOO_SHORT; \ + } \ + } while (0) -#define CHECK_PDU_POINTER_AND_LENGTH_ENCODER(bUFFER, mINIMUMlENGTH, lENGTH) \ - if (bUFFER == NULL) \ - { \ - printf("Got NULL pointer for the payload\n"); \ - errorCodeEncoder = TLV_ENCODE_BUFFER_NULL; \ - return TLV_ENCODE_BUFFER_NULL; \ - } \ - if (lENGTH < mINIMUMlENGTH) \ - { \ - printf("(%s:%d) Expecting at least %d bytes, got %u\n", \ - __FILE__, __LINE__, mINIMUMlENGTH, lENGTH); \ - errorCodeEncoder = TLV_ENCODE_BUFFER_TOO_SHORT; \ - return TLV_ENCODE_BUFFER_TOO_SHORT; \ - } - -#define CHECK_PDU_POINTER_ENCODER(bUFFER) \ - if (bUFFER == NULL) \ - { \ - printf("Got NULL pointer for the payload\n"); \ - errorCodeEncoder = TLV_ENCODE_BUFFER_NULL; \ - return TLV_ENCODE_BUFFER_NULL; \ - } +#define CHECK_PDU_POINTER_ENCODER(bUFFER) \ + do { \ + if ((bUFFER) == NULL) { \ + TLV_ENC_ERROR("Got NULL pointer for the payload\n"); \ + errorCodeEncoder = TLV_ENCODE_BUFFER_NULL; \ + return TLV_ENCODE_BUFFER_NULL; \ + } \ + } while (0) #endif /* define (TLV_ENCODER_H_) */ diff --git a/openair3/NAS/COMMON/nr_common.c b/openair3/NAS/COMMON/nr_common.c index 0a7aae2a17..6c935df4f1 100644 --- a/openair3/NAS/COMMON/nr_common.c +++ b/openair3/NAS/COMMON/nr_common.c @@ -21,6 +21,7 @@ * contact@openairinterface.org */ +#include #include #include #include diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 1199aad94b..5e9ce65194 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -194,6 +194,18 @@ static int fill_guti(FGSMobileIdentity *mi, const Guti5GSMobileIdentity_t *guti) return 13; } +static int fill_fgstmsi(Stmsi5GSMobileIdentity_t *stmsi, const Guti5GSMobileIdentity_t *guti) +{ + AssertFatal(guti != NULL, "UE has no GUTI\n"); + stmsi->amfpointer = guti->amfpointer; + stmsi->amfsetid = guti->amfsetid; + stmsi->tmsi = guti->tmsi; + stmsi->digit1 = DIGIT1; + stmsi->spare = 0; + stmsi->typeofidentity = FGS_MOBILE_IDENTITY_5GS_TMSI; + return 10; +} + static int fill_imeisv(FGSMobileIdentity *mi, const uicc_t *uicc) { int i = 0; @@ -260,6 +272,9 @@ int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) encode_result = encode_fgs_deregistration_request_ue_originating(&mm_msg->fgs_deregistration_request_ue_originating, buffer, len); break; + case FGS_SERVICE_REQUEST: + encode_result = encode_fgs_service_request(buffer, &mm_msg->service_request, len); + break; default: LOG_TRACE(ERROR, "EMM-MSG - Unexpected message type: 0x%x", mm_msg->header.message_type); encode_result = TLV_ENCODE_WRONG_MESSAGE_TYPE; @@ -550,6 +565,84 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) nas->registration_request_len = initialNasMsg->length; } +void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) +{ + LOG_I(NAS, "Generate initial NAS message: Service Request\n"); + int size = 0; + fgs_nas_message_t nas_msg = {0}; + memset(&nas_msg, 0, sizeof(nas_msg)); + // NAS is security protected if has valid security contexts + bool security_protected = nas->security_container->ciphering_context && nas->security_container->integrity_context; + MM_msg *mm_msg; + + if (security_protected) { + /* Set security protected 5GS NAS message header (see 9.1.1 of 3GPP TS 24.501) */ + nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + nas_msg.header.security_header_type = INTEGRITY_PROTECTED; + nas_msg.header.sequence_number = nas->security.nas_count_ul & 0xff; + size += sizeof(fgs_nas_message_security_header_t); + mm_msg = &nas_msg.security_protected.plain.mm_msg; + } else { + // Set Mobility Management plain message header + mm_msg = &nas_msg.plain.mm_msg; + } + // Fill MM plain message header + mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_msg->header.security_header_type = PLAIN_5GS_MSG; + mm_msg->header.message_type = FGS_SERVICE_REQUEST; + size += sizeof(mm_msg_header_t); + + // Fill Service Request + // Service Type + mm_msg->service_request.serviceType = SERVICE_TYPE_DATA; + // NAS key set identifier + mm_msg->service_request.naskeysetidentifier.naskeysetidentifier = NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE; + mm_msg->service_request.naskeysetidentifier.tsc = NAS_KEY_SET_IDENTIFIER_NATIVE; + size += 1; + // 5G-S-TMSI + size += fill_fgstmsi(&mm_msg->service_request.fiveg_s_tmsi, nas->guti); + + /* message encoding */ + initialNasMsg->nas_data = (Byte_t *)malloc(size * sizeof(Byte_t)); + if (security_protected) { + // security protected encoding + int security_header_len = nas_protected_security_header_encode((char *)(initialNasMsg->nas_data), &(nas_msg.header), size); + initialNasMsg->length = + security_header_len + + mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); + /* ciphering */ + uint8_t buf[initialNasMsg->length - 7]; + nas_stream_cipher_t stream_cipher; + stream_cipher.context = nas->security_container->ciphering_context; + AssertFatal(nas->security.nas_count_ul <= 0xffffff, "fatal: NAS COUNT UL too big (todo: fix that)\n"); + stream_cipher.count = nas->security.nas_count_ul; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->nas_data + 7); + /* length in bits */ + stream_cipher.blength = (initialNasMsg->length - 7) << 3; + stream_compute_encrypt(nas->security_container->ciphering_algorithm, &stream_cipher, buf); + memcpy(stream_cipher.message, buf, initialNasMsg->length - 7); + /* integrity protection */ + uint8_t mac[4]; + stream_cipher.context = nas->security_container->integrity_context; + stream_cipher.count = nas->security.nas_count_ul++; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->nas_data + 6); + /* length in bits */ + stream_cipher.blength = (initialNasMsg->length - 6) << 3; + stream_compute_integrity(nas->security_container->integrity_algorithm, &stream_cipher, mac); + printf("Integrity protected initial NAS message: mac = %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); + for (int i = 0; i < 4; i++) + initialNasMsg->nas_data[2 + i] = mac[i]; + } else { + // plain encoding + initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->nas_data), size); + LOG_I(NAS, "PLAIN_5GS_MSG initial NAS message: Service Request with length %d \n", initialNasMsg->length); + } +} + void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype, uicc_t *uicc) { int size = sizeof(mm_msg_header_t); diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index e10ac54b0f..0e324052ad 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -36,6 +36,7 @@ #include "FGSNASSecurityModeComplete.h" #include "FGSDeregistrationRequestUEOriginating.h" #include "RegistrationComplete.h" +#include "EMM/MSG/fgs_service_request.h" #include "as_message.h" #include "FGSUplinkNasTransport.h" #include @@ -48,6 +49,9 @@ #define PAYLOAD_CONTAINER_LENGTH_MIN 3 #define PAYLOAD_CONTAINER_LENGTH_MAX 65537 +/* 3GPP TS 24.501: 9.11.3.50 Service type */ +#define SERVICE_TYPE_DATA 0x1 + /* List of allowed NSSAI from NAS messaging. */ typedef struct { int sst; @@ -106,6 +110,7 @@ typedef struct { typedef union { mm_msg_header_t header; registration_request_msg registration_request; + fgs_service_request_msg_t service_request; fgs_identiy_response_msg fgs_identity_response; fgs_authentication_response_msg fgs_auth_response; fgs_deregistration_request_ue_originating_msg fgs_deregistration_request_ue_originating; @@ -158,6 +163,7 @@ typedef struct { nr_ue_nas_t *get_ue_nas_info(module_id_t module_id); void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas); +void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas); void *nas_nrue_task(void *args_p); void *nas_nrue(void *args_p); void nas_init_nrue(int num_ues); diff --git a/openair3/NGAP/ngap_gNB_management_procedures.c b/openair3/NGAP/ngap_gNB_management_procedures.c index 0c6c513af4..9615dc6b2a 100644 --- a/openair3/NGAP/ngap_gNB_management_procedures.c +++ b/openair3/NGAP/ngap_gNB_management_procedures.c @@ -39,7 +39,7 @@ #include "queue.h" #include "tree.h" -ngap_gNB_internal_data_t ngap_gNB_internal_data; +static ngap_gNB_internal_data_t ngap_gNB_internal_data; RB_GENERATE(ngap_amf_map, ngap_gNB_amf_data_s, entry, ngap_gNB_compare_assoc_id); diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index 2baf315599..3676ecc88d 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -63,8 +63,6 @@ #include "oaisim_mme_test_s1c.h" #endif -s1ap_eNB_config_t s1ap_config; - static int s1ap_eNB_generate_s1_setup_request( s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p); diff --git a/openair3/S1AP/s1ap_eNB.h b/openair3/S1AP/s1ap_eNB.h index 203dbc790e..7858d20d81 100644 --- a/openair3/S1AP/s1ap_eNB.h +++ b/openair3/S1AP/s1ap_eNB.h @@ -46,15 +46,6 @@ typedef enum s1ap_timer_type_s { S1AP_TIMER_TYPE_MAX, } s1ap_timer_type_t; -typedef struct s1ap_eNB_config_s { - // MME related params - unsigned char mme_enabled; ///< MME enabled ? -} s1ap_eNB_config_t; - -extern s1ap_eNB_config_t s1ap_config; - -#define EPC_MODE_ENABLED s1ap_config.mme_enabled - void *s1ap_eNB_process_itti_msg(void*); void s1ap_eNB_init(void); void *s1ap_eNB_task(void *arg); diff --git a/openair3/S1AP/s1ap_eNB_management_procedures.c b/openair3/S1AP/s1ap_eNB_management_procedures.c index e9effa7824..6ad1828620 100644 --- a/openair3/S1AP/s1ap_eNB_management_procedures.c +++ b/openair3/S1AP/s1ap_eNB_management_procedures.c @@ -41,7 +41,7 @@ #include "s1ap_eNB_defs.h" #include "s1ap_eNB.h" -s1ap_eNB_internal_data_t s1ap_eNB_internal_data; +static s1ap_eNB_internal_data_t s1ap_eNB_internal_data; RB_GENERATE(s1ap_mme_map, s1ap_eNB_mme_data_s, entry, s1ap_eNB_compare_assoc_id); diff --git a/openair3/TEST/test5Gnas.c b/openair3/TEST/test5Gnas.c deleted file mode 100644 index 86b4326f94..0000000000 --- a/openair3/TEST/test5Gnas.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -volatile int oai_exit; -configmodule_interface_t *uniqCfg = NULL; - -int main(int argc, char **argv) { - if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == NULL) { - exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); - } - - logInit(); - char *resp; - nr_user_nas_t UErrc= {0}; - NRUEcontext_t UEnas= {0}; - // Network generate identity request after a sucessfull radio attach - int size=identityRequest((void **)&resp, &UEnas); - log_dump(NAS, resp, size, LOG_DUMP_CHAR," identity Request:\n" ); - // UE process the message that it has received from phy layer in a "DL transfer" message - UEprocessNAS(resp, &UErrc); - // UE Scheduler should later call the response - size=identityResponse((void **)&resp, &UErrc); - log_dump(NAS, resp, size, LOG_DUMP_CHAR," identity Response:\n" ); - // Now the gNB process the identity response - processNAS(resp, &UEnas); - // gNB scheduler should call the next query - size=authenticationRequest((void **)&resp, &UEnas); - log_dump(NAS, resp, size, LOG_DUMP_CHAR," authentication request:\n" ); - // as above - UEprocessNAS(resp, &UErrc); - size=authenticationResponse((void **)&resp, &UErrc); - log_dump(NAS, resp, size, LOG_DUMP_CHAR," authentication response:\n" ); - processNAS(resp, &UEnas); - return 0; -} diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 9fb8f159fe..b9ffea6531 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -155,7 +155,7 @@ class gtpEndPoints { } }; -gtpEndPoints globGtp; +static gtpEndPoints globGtp; // note TEid 0 is reserved for specific usage: echo req/resp, error and supported extensions static teid_t gtpv1uNewTeid(void) { diff --git a/radio/COMMON/common_lib.h b/radio/COMMON/common_lib.h index 272f376d50..a33e65c150 100644 --- a/radio/COMMON/common_lib.h +++ b/radio/COMMON/common_lib.h @@ -37,7 +37,7 @@ #include #include #include "record_player.h" -#include +#include "common/utils/threadPool/notified_fifo.h" /* default name of shared library implementing the radio front end */ #define OAI_RF_LIBNAME "oai_device" diff --git a/radio/ETHERNET/eth_udp.c b/radio/ETHERNET/eth_udp.c index 6d41a783ab..2f937eaabf 100644 --- a/radio/ETHERNET/eth_udp.c +++ b/radio/ETHERNET/eth_udp.c @@ -50,7 +50,6 @@ #include "common_lib.h" #include "ethernet_lib.h" #include "openair1/PHY/sse_intrin.h" -#include "common/utils/threadPool/thread-pool.h" //#define DEBUG 1 diff --git a/radio/ETHERNET/ethernet_lib.h b/radio/ETHERNET/ethernet_lib.h index 3ec8b93d9d..2a5f2db4ca 100644 --- a/radio/ETHERNET/ethernet_lib.h +++ b/radio/ETHERNET/ethernet_lib.h @@ -41,7 +41,6 @@ #include #include #include -#include #define MAX_INST 4 #define DEFAULT_IF "lo" diff --git a/radio/USRP/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp index 34edcc9b8f..8fbb561149 100644 --- a/radio/USRP/usrp_lib.cpp +++ b/radio/USRP/usrp_lib.cpp @@ -49,6 +49,7 @@ #include "common/utils/LOG/log.h" #include "common_lib.h" #include "assertions.h" +#include "system.h" #include "common/utils/LOG/vcd_signal_dumper.h" diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index 2f1b0a356e..00f7ef97e0 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -9,12 +9,6 @@ endif() pkg_check_modules(dpdk REQUIRED libdpdk) pkg_check_modules(numa REQUIRED numa) -find_package(xran 5.1.4 EXACT REQUIRED) # E release -> 5 - -# Ignore xran-specific warning: we don't care/can't change the following warning, so suppress -# alignment 1 of 'struct XYZ' is less than 2 -add_compile_options(-Wno-packed-not-aligned) - add_library(oran_fhlib_5g MODULE oran_isolate.c oaioran.c @@ -22,6 +16,19 @@ add_library(oran_fhlib_5g MODULE oran-init.c ) +find_package(xran REQUIRED) +if(xran_VERSION VERSION_EQUAL 5.1.4) + target_compile_definitions(oran_fhlib_5g PRIVATE E_RELEASE) +elseif(xran_VERSION VERSION_EQUAL 6.1.1) + target_compile_definitions(oran_fhlib_5g PRIVATE F_RELEASE) +else() + message(FATAL_ERROR "Found xran version ${xran_VERSION} but needed 5.1.4 (E release) or 6.1.1 (F release)") +endif() + +# Ignore xran-specific warning: we don't care/can't change the following warning, so suppress +# alignment 1 of 'struct XYZ' is less than 2 +add_compile_options(-Wno-packed-not-aligned) + set_target_properties(oran_fhlib_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -march=native") target_link_libraries(oran_fhlib_5g PRIVATE xran::xran) target_link_libraries(oran_fhlib_5g PRIVATE ${dpdk_LINK_LIBRARIES}) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 300a6869cf..02487e9300 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -90,7 +90,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) tti = xran_get_slot_idx_from_tti(rx_tti, &frame, &subframe, &slot, &second); - rx_sym = callback_tag->symbol; + rx_sym = callback_tag->symbol & 0xFF; uint32_t ru_id = callback_tag->oXuId; LOG_D(NR_PHY, @@ -101,7 +101,23 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) (unsigned long long)second, rx_sym, ru_id); - if (rx_sym == 7) { + if (rx_sym == 7) { // in F release this value is defined as XRAN_FULL_CB_SYM (full slot (offset + 7)) +#ifdef F_RELEASE + int32_t nCellIdx = callback_tag->cellId; + int32_t ntti = (rx_tti + XRAN_N_FE_BUF_LEN - 1) % XRAN_N_FE_BUF_LEN; + + for(uint32_t ant_id = 0; ant_id < fh_config->neAxc; ant_id++) { + struct xran_prb_map *pRbMap = (struct xran_prb_map *)xran_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[ntti][nCellIdx][ant_id].sBufferList.pBuffers->pData; + AssertFatal(pRbMap != NULL, "(%d:%d:%d)pRbMap == NULL. Aborting.\n", nCellIdx, ntti, ant_id); + + for (uint32_t sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) { + for (uint32_t idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++ ) { + struct xran_prb_elm *pRbElm = &pRbMap->prbMap[idxElm]; + pRbElm->nSecDesc[sym_id] = 0; // number of section descriptors per symbol; M-plane info + } + } + } +#endif if (first_call_set) { if (!first_rx_set) { LOG_I(NR_PHY, "first_rx is set (num_ports %d), first_read_set %d\n", num_ports, first_read_set); @@ -332,7 +348,11 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; struct xran_prb_elm *pRbElm = &pPrbMap->prbMap[0]; +#ifdef E_RELEASE struct xran_section_desc *p_sec_desc = pRbElm->p_sec_desc[sym_idx][0]; +#elif defined F_RELEASE + struct xran_section_desc *p_sec_desc = &pRbElm->sec_desc[sym_idx][0]; +#endif uint32_t one_rb_size = (((pRbElm->iqWidth == 0) || (pRbElm->iqWidth == 16)) ? (N_SC_PER_PRB * 2 * 2) : (3 * pRbElm->iqWidth + 1)); if (fh_init->mtu < pRbElm->nRBSize * one_rb_size) @@ -486,9 +506,12 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { struct xran_section_desc *p_sec_desc = NULL; p_prbMapElm = &pRbMap->prbMap[idxElm]; - p_sec_desc = - // assumes one fragment per symbol - p_prbMapElm->p_sec_desc[sym_id][0]; + // assumes one fragment per symbol +#ifdef E_RELEASE + p_sec_desc = p_prbMapElm->p_sec_desc[sym_id][0]; +#elif F_RELEASE + p_sec_desc = &p_prbMapElm->sec_desc[sym_id][0]; +#endif dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index 4f828b8a1a..f165044429 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -59,55 +59,6 @@ static void print_fh_eowd_cmn(unsigned index, const struct xran_ecpri_del_meas_c eowd_cmn->owdm_PlLength); } -static void print_fh_eowd_port(unsigned index, unsigned vf, const struct xran_ecpri_del_meas_port *eowd_port) -{ - printf("\ - eowd_port[%u][%u]:\n\ - t1 %ld\n\ - t2 %ld\n\ - tr %ld\n\ - delta %ld\n\ - portid %d\n\ - runMeas %d\n\ - currentMeasID %d\n\ - msState %d\n\ - numMeas %d\n\ - txDone %d\n\ - rspTimerIdx %ld\n\ - delaySamples [%ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld]\n\ - delayAvg %ld\n", - index, - vf, - eowd_port->t1, - eowd_port->t2, - eowd_port->tr, - eowd_port->delta, - eowd_port->portid, - eowd_port->runMeas, - eowd_port->currentMeasID, - eowd_port->msState, - eowd_port->numMeas, - eowd_port->txDone, - eowd_port->rspTimerIdx, - eowd_port->delaySamples[0], - eowd_port->delaySamples[1], - eowd_port->delaySamples[2], - eowd_port->delaySamples[3], - eowd_port->delaySamples[4], - eowd_port->delaySamples[5], - eowd_port->delaySamples[6], - eowd_port->delaySamples[7], - eowd_port->delaySamples[8], - eowd_port->delaySamples[9], - eowd_port->delaySamples[10], - eowd_port->delaySamples[11], - eowd_port->delaySamples[12], - eowd_port->delaySamples[13], - eowd_port->delaySamples[14], - eowd_port->delaySamples[15], - eowd_port->delayAvg); -} - static void print_fh_init_io_cfg(const struct xran_io_cfg *io_cfg) { printf("\ @@ -152,7 +103,7 @@ static void print_fh_init_io_cfg(const struct xran_io_cfg *io_cfg) pkt_proc_core_64_127 %016lx\n\ pkt_aux_core %d\n\ timing_core %d\n\ - port [%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, ]\n\ + port (filled within xran library)\n\ io_sleep %d\n\ nEthLinePerPort %d\n\ nEthLineSpeed %d\n\ @@ -163,31 +114,17 @@ static void print_fh_init_io_cfg(const struct xran_io_cfg *io_cfg) io_cfg->pkt_proc_core_64_127, io_cfg->pkt_aux_core, io_cfg->timing_core, - io_cfg->port[XRAN_UP_VF], - io_cfg->port[XRAN_CP_VF], - io_cfg->port[XRAN_UP_VF1], - io_cfg->port[XRAN_CP_VF1], - io_cfg->port[XRAN_UP_VF2], - io_cfg->port[XRAN_CP_VF2], - io_cfg->port[XRAN_UP_VF3], - io_cfg->port[XRAN_CP_VF3], - io_cfg->port[XRAN_UP_VF4], - io_cfg->port[XRAN_CP_VF4], - io_cfg->port[XRAN_UP_VF5], - io_cfg->port[XRAN_CP_VF5], - io_cfg->port[XRAN_UP_VF6], - io_cfg->port[XRAN_CP_VF6], - io_cfg->port[XRAN_UP_VF7], - io_cfg->port[XRAN_CP_VF7], io_cfg->io_sleep, io_cfg->nEthLinePerPort, io_cfg->nEthLineSpeed, io_cfg->one_vf_cu_plane); - print_fh_eowd_cmn(0, &io_cfg->eowd_cmn[0]); - print_fh_eowd_cmn(1, &io_cfg->eowd_cmn[1]); - for (int i = 0; i < 2; ++i) - for (int v = 0; v < io_cfg->num_vfs; ++v) - print_fh_eowd_port(i, v, &io_cfg->eowd_port[i][v]); + print_fh_eowd_cmn(io_cfg->id, &io_cfg->eowd_cmn[io_cfg->id]); + printf("eowd_port (filled within xran library)\n"); +#ifdef F_RELEASE + printf("\ + bbu_offload %d\n", + io_cfg->bbu_offload); +#endif } static void print_fh_init_eaxcid_conf(const struct xran_eaxcid_config *eaxcid_conf) @@ -247,6 +184,13 @@ void print_fh_init(const struct xran_fh_init *fh_init) printf("\ totalBfWeights %d\n", fh_init->totalBfWeights); +#ifdef F_RELEASE + printf("\ + mlogxranenable %d\n\ + dlCpProcBurst %d\n", + fh_init->mlogxranenable, + fh_init->dlCpProcBurst); +#endif } static void print_prach_config(const struct xran_prach_config *prach_conf) @@ -283,6 +227,11 @@ static void print_prach_config(const struct xran_prach_config *prach_conf) prach_conf->timeOffset, prach_conf->freqOffset, prach_conf->eAxC_offset); +#ifdef F_RELEASE + printf("\ + nPrachConfIdxLTE %d\n", + prach_conf->nPrachConfIdxLTE); +#endif } static void print_srs_config(const struct xran_srs_config *srs_conf) @@ -442,6 +391,14 @@ void print_fh_config(const struct xran_fh_config *fh_config) fh_config->GPS_Alpha, fh_config->GPS_Beta); +#ifdef F_RELEASE + printf("\ + srsEnableCp %d\n\ + SrsDelaySym %d\n", + fh_config->srsEnableCp, + fh_config->SrsDelaySym); +#endif + print_prach_config(&fh_config->prach_conf); print_srs_config(&fh_config->srs_conf); print_frame_config(&fh_config->frame_conf); @@ -466,6 +423,17 @@ void print_fh_config(const struct xran_fh_config *fh_config) fh_config->log_level, fh_config->max_sections_per_slot, fh_config->max_sections_per_symbol); + +#ifdef F_RELEASE + printf("\ + RunSlotPrbMapBySymbolEnable %d\n\ + dssEnable %d\n\ + dssPeriod %d\n\ + technology[XRAN_MAX_DSS_PERIODICITY] (not filled as DSS disabled)\n", + fh_config->RunSlotPrbMapBySymbolEnable, + fh_config->dssEnable, + fh_config->dssPeriod); +#endif } static const paramdef_t *gpd(const paramdef_t *pd, int num, const char *name) @@ -522,9 +490,32 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in io_cfg->nEthLineSpeed = *gpd(fhip, nump, ORAN_CONFIG_NETHSPEED)->uptr; // 10G,25G,40G,100G speed of Physical connection on O-RU io_cfg->one_vf_cu_plane = (io_cfg->num_vfs == num_rus); // C-plane and U-plane use one VF - /* use owdm to calculate T12 and T34 -> CUS specification, section 2.3.3.3 */ - // io_cfg->eowd_cmn[2] // ecpri one-way delay measurements common settings for O-DU and O-RU - // io_cfg->eowd_port[2][XRAN_VF_MAX] // ecpri owd measurements per port variables for O-DU and O-RU + /* eCPRI One-Way Delay Measurements common settings for O-DU and O-RU; + use owdm to calculate T12 and T34 -> CUS specification, section 2.3.3.3; + this is an optional feature that RU might or might not support; + to verify if RU supports, please check in the official RU documentation or + via M-plane the o-ran-ecpri-delay@.yang capability; + this functionality is improved in F release */ + /* if RU does support, io_cfg->eowd_cmn[0] should only be filled as id = O_DU; io_cfg->eowd_cmn[1] only used if id = O_RU */ + const uint16_t owdm_enable = *gpd(fhip, nump, ORAN_CONFIG_ECPRI_OWDM)->uptr; + if (owdm_enable) { + io_cfg->eowd_cmn[0].initiator_en = 1; // 1 -> initiator (always O-DU), 0 -> recipient (always O-RU) + io_cfg->eowd_cmn[0].numberOfSamples = 8; // total number of samples to be collected and averaged per port + io_cfg->eowd_cmn[0].filterType = 0; // 0 -> simple average based on number of measurements; not used in xran in both E and F releases + io_cfg->eowd_cmn[0].responseTo = 10000000; // response timeout in [ns] + io_cfg->eowd_cmn[0].measVf = 0; // VF using the OWD transmitter; within xran, the measurements are calculated per each supported VF, but starts from measVf + io_cfg->eowd_cmn[0].measState = 0; // the state of the OWD transmitter; 0 -> OWDMTX_INIT (enum xran_owdm_tx_state) + io_cfg->eowd_cmn[0].measId = 0; // measurement ID to be used by the transmitter + io_cfg->eowd_cmn[0].measMethod = 0; // measurement method; 0 -> XRAN_REQUEST (enum xran_owd_meas_method) + io_cfg->eowd_cmn[0].owdm_enable = 1; // 1 -> enabled; 0 -> disabled + io_cfg->eowd_cmn[0].owdm_PlLength = 40; // payload in the measurement packet; 40 <= PlLength <= 1400 + } + /* eCPRI OWDM per port variables for O-DU; this parameter is filled within xran library */ + // eowd_port[0][XRAN_VF_MAX] + +#ifdef F_RELEASE + io_cfg->bbu_offload = 0; // enable packet handling on BBU cores +#endif return true; } @@ -620,7 +611,7 @@ static bool set_fh_init(struct xran_fh_init *fh_init, enum xran_category xran_ca fh_init->dpdkBasebandFecMode = 0; // DPDK Baseband FEC device mode (0-SW, 1-HW); not used in xran fh_init->dpdkBasebandDevice = NULL; // DPDK Baseband device address; not used in xran /* used to specify a unique prefix for shared memory, and files created by multiple DPDK processes; - is it necessary */ + it is necessary */ fh_init->filePrefix = strdup(*gpd(fhip, nump, ORAN_CONFIG_FILE_PREFIX)->strptr); /* maximum transmission unit (MTU) is the size of the largest protocol data unit (PDU) that can be communicated in a single xRAN network layer transaction. Supported 1500 bytes and 9600 bytes (Jumbo Frame); @@ -643,6 +634,12 @@ static bool set_fh_init(struct xran_fh_init *fh_init, enum xran_category xran_ca fh_init->totalBfWeights = 0; // only used if id = O_RU (for emulation); C-plane extension types; section 5.4.6 of CUS spec +#ifdef F_RELEASE + fh_init->mlogxranenable = 0; // enable mlog; 0 -> disabled + fh_init->dlCpProcBurst = 0; /* 1 -> DL CP processing will be done on single symbol, + 0 -> DL CP processing will be spread across all allowed symbols and multiple cores to reduce burstiness */ +#endif + return true; } @@ -680,10 +677,15 @@ static bool set_fh_prach_config(const openair0_config_t *oai0, prach_config->numPrbc = 0; prach_config->timeOffset = 0; prach_config->freqOffset = 0; +#ifdef F_RELEASE + prach_config->nPrachConfIdxLTE = 0; // used only if DSS enabled and technology is XRAN_RAN_LTE +#endif /* xran defines PDSCH eAxC IDs as [0...Ntx-1]; xran defines PUSCH eAxC IDs as [0...Nrx-1]; - PRACH offset must be >= max(Ntx, Nrx) */ + xran assumes PRACH offset >= max(Ntx, Nrx). However, we made a workaround that xran supports PRACH eAxC IDs same as PUSCH eAxC IDs. + This is achieved with is_prach and filter_id parameters in the patch. + Please note that this approach only applies to the RUs that support this functionality, e.g. LITEON RU. */ uint8_t offset = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET)->u8ptr; prach_config->eAxC_offset = (offset != 0) ? offset : max_num_ant; @@ -804,41 +806,39 @@ static bool set_fh_config(int ru_idx, int num_rus, enum xran_category xran_cat, fh_config->nAntElmTRx = 0; // number of antenna elements for TX and RX = SRS; used only if XRAN_CATEGORY_B fh_config->nDLFftSize = 0; // DL FFT size; not used in xran fh_config->nULFftSize = 0; // UL FFT size; not used in xran - fh_config->nDLRBs = oai0->num_rb_dl; // DL PRB - fh_config->nULRBs = oai0->num_rb_dl; // UL PRB; in xran not used as id = O_DU, but used in oaioran.c/oran-init.c + fh_config->nDLRBs = oai0->num_rb_dl; // DL PRB; used in oaioran.c/oran-init.c; not used in xran, neither in E nor in F release + fh_config->nULRBs = oai0->num_rb_dl; // UL PRB; used in oaioran.c/oran-init.c; in xran E release not used so the patch fixes it, but in xran F release this value is properly used fh_config->nDLAbsFrePointA = 0; // Abs Freq Point A of the Carrier Center Frequency for in KHz Value; not used in xran fh_config->nULAbsFrePointA = 0; // Abs Freq Point A of the Carrier Center Frequency for in KHz Value; not used in xran fh_config->nDLCenterFreqARFCN = 0; // center frequency for DL in NR-ARFCN; not used in xran fh_config->nULCenterFreqARFCN = 0; // center frequency for UL in NR-ARFCN; not used in xran fh_config->ttiCb = NULL; // check tti_to_phy_cb(), tx_cp_dl_cb() and tx_cp_ul_cb => first_call fh_config->ttiCbParam = NULL; // check tti_to_phy_cb(), tx_cp_dl_cb() and tx_cp_ul_cb => first_call - fh_config->Tadv_cp_dl = *gpd(fhp, nfh, ORAN_FH_CONFIG_TADV_CP_DL)->uptr; // not used in xran - if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T2A_CP_DL, &fh_config->T2a_min_cp_dl, &fh_config->T2a_max_cp_dl)) // not used in xran + + /* DU delay profile */ + if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_CP_DL, &fh_config->T1a_min_cp_dl, &fh_config->T1a_max_cp_dl)) // E - min not used in xran, max yes; F - both min and max are used in xran return false; - if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T2A_CP_UL, &fh_config->T2a_min_cp_ul, &fh_config->T2a_max_cp_ul)) // not used in xran + if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_CP_UL, &fh_config->T1a_min_cp_ul, &fh_config->T1a_max_cp_ul)) // both E and F - min not used in xran, max yes return false; - if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T2A_UP, &fh_config->T2a_min_up, &fh_config->T2a_max_up)) // not used in xran + if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_UP, &fh_config->T1a_min_up, &fh_config->T1a_max_up)) // both E and F - min not used in xran, max yes return false; - if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_TA3, &fh_config->Ta3_min, &fh_config->Ta3_max)) // not used in xran - return false; - if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_CP_DL, &fh_config->T1a_min_cp_dl, &fh_config->T1a_max_cp_dl)) - return false; - if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_CP_UL, &fh_config->T1a_min_cp_ul, &fh_config->T1a_max_cp_ul)) - return false; - if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_UP, &fh_config->T1a_min_up, &fh_config->T1a_max_up)) - return false; - if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_TA4, &fh_config->Ta4_min, &fh_config->Ta4_max)) + if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_TA4, &fh_config->Ta4_min, &fh_config->Ta4_max)) // both E and F - min not used in xran, max yes return false; + fh_config->enableCP = 1; // enable C-plane fh_config->prachEnable = 1; // enable PRACH fh_config->srsEnable = 0; // enable SRS; used only if XRAN_CATEGORY_B +#ifdef F_RELEASE + fh_config->srsEnableCp = 0; // enable SRS CP; used only if XRAN_CATEGORY_B + fh_config->SrsDelaySym = 0; // number of SRS delay symbols; used only if XRAN_CATEGORY_B +#endif fh_config->puschMaskEnable = 0; // enable PUSCH mask; only used if id = O_RU fh_config->puschMaskSlot = 0; // specific which slot PUSCH channel masked; only used if id = O_RU fh_config->cp_vlan_tag = *gpd(fhp, nfh, ORAN_FH_CONFIG_CP_VLAN_TAG)->uptr; // C-plane VLAN tag; not used in xran; needed for M-plane fh_config->up_vlan_tag = *gpd(fhp, nfh, ORAN_FH_CONFIG_UP_VLAN_TAG)->uptr; // U-plane VLAN tag; not used in xran; needed for M-plane - fh_config->debugStop = 0; // enable auto stop; not used in xran + fh_config->debugStop = 0; // enable auto stop; only used if id = O_RU fh_config->debugStopCount = 0; // enable auto stop after number of Tx packets; not used in xran - fh_config->DynamicSectionEna = 0; // enable dynamic C-Plane section allocation; not used in xran + fh_config->DynamicSectionEna = 0; // enable dynamic C-Plane section allocation fh_config->GPS_Alpha = 0; // refers to alpha as defined in section 9.7.2 of ORAN spec. this value should be alpha*(1/1.2288ns), range 0 - 1e7 (ns); offset_nsec = (pConf->GPS_Beta - offset_sec * 100) * 1e7 + pConf->GPS_Alpha fh_config->GPS_Beta = 0; // beta value as defined in section 9.7.2 of ORAN spec. range -32767 ~ +32767; offset_sec = pConf->GPS_Beta / 100 @@ -873,6 +873,14 @@ static bool set_fh_config(int ru_idx, int num_rus, enum xran_category xran_cat, fh_config->max_sections_per_slot = 0; // not used in xran fh_config->max_sections_per_symbol = 0; // not used in xran +#ifdef F_RELEASE + fh_config->RunSlotPrbMapBySymbolEnable = 0; // enable PRB mapping by symbol with multisection + + fh_config->dssEnable = 0; // enable DSS (extension-9) + fh_config->dssPeriod = 0; // DSS pattern period for LTE/NR + // fh_config->technology[XRAN_MAX_DSS_PERIODICITY] // technology array represents slot is LTE(0)/NR(1); used only if DSS enabled +#endif + return true; } diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c index e290db561b..8072c5852e 100644 --- a/radio/fhi_72/oran-init.c +++ b/radio/fhi_72/oran-init.c @@ -29,6 +29,7 @@ #include "oaioran.h" #include "common/utils/assertions.h" +#include "common/utils/LOG/log.h" #include "common_lib.h" /* PRACH data samples are 32 bits wide (16bits for I/Q). Each packet contains @@ -140,10 +141,10 @@ static uint32_t oran_allocate_uplane_buffers( { xran_status_t status; uint32_t pool; - // we need at least XRAN_N_FE_BUF_LEN * ant * XRAN_NUM_OF_SYMBOL_PER_SLOT - // buffers, but xran_bm_init() uses rte_pktmbuf_pool_create() which - // recommends to use a power of two for the buffers - uint32_t numBufs = next_power_2(XRAN_N_FE_BUF_LEN * ant * XRAN_NUM_OF_SYMBOL_PER_SLOT); + /* xran_bm_init() uses rte_pktmbuf_pool_create() which recommends to use a power of two for the buffers; + the E release sample app didn't take this into account, but we introduced it ourselves; + the F release sample app took this into account, so we can proudly say we assumed correctly */ + uint32_t numBufs = next_power_2(XRAN_N_FE_BUF_LEN * ant * XRAN_NUM_OF_SYMBOL_PER_SLOT) - 1; status = xran_bm_init(instHandle, &pool, numBufs, bufSize); AssertFatal(XRAN_STATUS_SUCCESS == status, "Failed at xran_bm_init(), status %d\n", status); printf("xran_bm_init() hInstance %p poolIdx %u elements %u size %u\n", instHandle, pool, numBufs, bufSize); @@ -217,26 +218,33 @@ static void oran_allocate_cplane_buffers(void *instHandle, struct xran_flat_buffer buf[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN], uint32_t ant, uint32_t sect, + #ifdef F_RELEASE + uint32_t mtu, + const struct xran_fh_config *fh_config, + #endif uint32_t size_of_prb_map, - const oran_cplane_prb_config *prb_conf) + oran_cplane_prb_config *prb_conf) { xran_status_t status; + uint32_t count1 = 0; + +#ifdef E_RELEASE + uint32_t count2 = 0; uint32_t poolSec; uint32_t numBufsSec = next_power_2(XRAN_N_FE_BUF_LEN * ant * XRAN_NUM_OF_SYMBOL_PER_SLOT * sect * XRAN_MAX_FRAGMENT); uint32_t bufSizeSec = sizeof(struct xran_section_desc); status = xran_bm_init(instHandle, &poolSec, numBufsSec, bufSizeSec); AssertFatal(XRAN_STATUS_SUCCESS == status, "Failed at xran_bm_init(), status %d\n", status); printf("xran_bm_init() hInstance %p poolIdx %u elements %u size %u\n", instHandle, poolSec, numBufsSec, bufSizeSec); +#endif uint32_t poolPrb; - uint32_t numBufsPrb = next_power_2(XRAN_N_FE_BUF_LEN * ant * XRAN_NUM_OF_SYMBOL_PER_SLOT); + uint32_t numBufsPrb = next_power_2(XRAN_N_FE_BUF_LEN * ant * XRAN_NUM_OF_SYMBOL_PER_SLOT) - 1; uint32_t bufSizePrb = size_of_prb_map; status = xran_bm_init(instHandle, &poolPrb, numBufsPrb, bufSizePrb); AssertFatal(XRAN_STATUS_SUCCESS == status, "Failed at xran_bm_init(), status %d\n", status); printf("xran_bm_init() hInstance %p poolIdx %u elements %u size %u\n", instHandle, poolPrb, numBufsPrb, bufSizePrb); - uint32_t count1 = 0; - uint32_t count2 = 0; for (uint32_t a = 0; a < ant; a++) { for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) { list[a][j].pBuffers = &buf[a][j]; @@ -254,13 +262,15 @@ static void oran_allocate_cplane_buffers(void *instHandle, fb->pData = ptr; fb->pCtrl = mb; - // the original sample app code copies up to size_of_prb_map, but I think - // this is wrong because the way it is computed leads to a number larger - // than sizeof(map) - struct xran_prb_map *p_rb_map = (struct xran_prb_map *)ptr; - const struct xran_prb_map *src = &prb_conf->slotMap; + struct xran_prb_map *src = &prb_conf->slotMap; if ((j % prb_conf->nTddPeriod) == prb_conf->mixed_slot_index) src = &prb_conf->mixedSlotMap; +#ifdef E_RELEASE + /* as per E release sample app, the memory is copied up to size_of_prb_map + which translates to >= sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm)*5, + but we assume that RB allocation is done as 1 RE/UE so the total memory size is sizeof(struct xran_prb_map); + this is improved in F release */ + struct xran_prb_map *p_rb_map = (struct xran_prb_map *)ptr; memcpy(p_rb_map, src, sizeof(*src)); for (uint32_t elm_id = 0; elm_id < p_rb_map->nPrbElm; ++elm_id) { @@ -282,10 +292,19 @@ static void oran_allocate_cplane_buffers(void *instHandle, } } } +#elif defined F_RELEASE + if (fh_config->RunSlotPrbMapBySymbolEnable) { + xran_init_PrbMap_by_symbol_from_cfg(src, ptr, mtu, fh_config->nDLRBs); + } else { + xran_init_PrbMap_from_cfg(src, ptr, mtu); + } +#endif } } printf("xran_bm_allocate_buffer() hInstance %p poolIdx %u count %u\n", instHandle, poolPrb, count1); +#ifdef E_RELEASE printf("xran_bm_allocate_buffer() hInstance %p poolIdx %u count %u\n", instHandle, poolSec, count2); +#endif } /* callback not actively used */ @@ -298,6 +317,9 @@ static void oran_allocate_buffers(void *handle, int xran_inst, int num_sectors, oran_port_instance_t *portInstances, + #ifdef F_RELEASE + uint32_t mtu, + #endif const struct xran_fh_config *fh_config) { AssertFatal(num_sectors == 1, "only support one sector at the moment\n"); @@ -305,7 +327,6 @@ static void oran_allocate_buffers(void *handle, AssertFatal(handle != NULL, "no handle provided\n"); uint32_t xran_max_antenna_nr = RTE_MAX(fh_config->neAxc, fh_config->neAxcUl); uint32_t xran_max_sections_per_slot = RTE_MAX(fh_config->max_sections_per_slot, XRAN_MIN_SECTIONS_PER_SLOT); - uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (xran_max_sections_per_slot - 1); pi->buf_list = _mm_malloc(sizeof(*pi->buf_list), 256); AssertFatal(pi->buf_list != NULL, "out of memory\n"); @@ -331,11 +352,23 @@ static void oran_allocate_buffers(void *handle, .slotMap = dlPm, .mixedSlotMap = dlPmMixed, }; + +#ifdef E_RELEASE + uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (xran_max_sections_per_slot - 1); +#elif defined F_RELEASE + uint32_t numPrbElm = xran_get_num_prb_elm(&dlPmMixed, mtu); + uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm); +#endif + oran_allocate_cplane_buffers(pi->instanceHandle, bl->srccp, bl->bufs.tx_prbmap, xran_max_antenna_nr, xran_max_sections_per_slot, + #ifdef F_RELEASE + mtu, + fh_config, + #endif size_of_prb_map, &dlConf); @@ -357,6 +390,10 @@ static void oran_allocate_buffers(void *handle, bl->bufs.rx_prbmap, xran_max_antenna_nr, xran_max_sections_per_slot, + #ifdef F_RELEASE + mtu, + fh_config, + #endif size_of_prb_map, &ulConf); @@ -422,7 +459,12 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi struct xran_cb_tag tag = {.cellId = sector, .oXuId = o_xu_id}; pi->prach_tag = tag; pi->pusch_tag = tag; +#ifdef E_RELEASE + LOG_W(PHY, "Please be aware that E release support will be removed by the end of January 2025. Instead, F release will be mandatory.\n"); oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, &xran_fh_config[o_xu_id]); +#elif defined F_RELEASE + oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, xran_fh_init->mtu, &xran_fh_config[o_xu_id]); +#endif if ((xret = xran_reg_physide_cb(gxran_handle, oai_physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI)) != XRAN_STATUS_SUCCESS) { printf("xran_reg_physide_cb failed %d\n", xret); diff --git a/radio/fhi_72/oran-params.h b/radio/fhi_72/oran-params.h index e9de03660c..d7eaf47a3b 100644 --- a/radio/fhi_72/oran-params.h +++ b/radio/fhi_72/oran-params.h @@ -37,6 +37,7 @@ #define ORAN_CONFIG_NETHPERPORT "eth_lines" #define ORAN_CONFIG_NETHSPEED "eth_speed" #define ORAN_CONFIG_DPDK_MEM_SIZE "dpdk_mem_size" +#define ORAN_CONFIG_ECPRI_OWDM "owdm_enable" // clang-format off // TODO: PCI addr check @@ -52,16 +53,12 @@ {ORAN_CONFIG_NETHPERPORT, "number of links per port\n", 0, .uptr=NULL, .defuintval=1, TYPE_UINT, 0}, \ {ORAN_CONFIG_NETHSPEED, "ethernet speed link\n", 0, .uptr=NULL, .defuintval=10, TYPE_UINT, 0}, \ {ORAN_CONFIG_DPDK_MEM_SIZE, "DPDK huge page pre-allocation in MiB\n", 0, .uptr=NULL, .defuintval=8192, TYPE_UINT, 0}, \ + {ORAN_CONFIG_ECPRI_OWDM, "eCPRI One-Way Delay Measurements\n", PARAMFLAG_BOOL, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ } // clang-format on #define CONFIG_STRING_ORAN_FH "fh_config" -#define ORAN_FH_CONFIG_TADV_CP_DL "Tadv_cp_dl" -#define ORAN_FH_CONFIG_T2A_CP_DL "T2a_cp_dl" -#define ORAN_FH_CONFIG_T2A_CP_UL "T2a_cp_ul" -#define ORAN_FH_CONFIG_T2A_UP "T2a_up" -#define ORAN_FH_CONFIG_TA3 "Ta3" #define ORAN_FH_CONFIG_T1A_CP_DL "T1a_cp_dl" #define ORAN_FH_CONFIG_T1A_CP_UL "T1a_cp_ul" #define ORAN_FH_CONFIG_T1A_UP "T1a_up" @@ -73,11 +70,6 @@ // clang-format off #define ORAN_FH_DESC { \ - {ORAN_FH_CONFIG_TADV_CP_DL, "Tadv parameter of RU\n", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ - {ORAN_FH_CONFIG_T2A_CP_DL, "T2a_cp_dl" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ - {ORAN_FH_CONFIG_T2A_CP_UL, "T2a_cp_ul" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ - {ORAN_FH_CONFIG_T2A_UP, "T2a_up" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ - {ORAN_FH_CONFIG_TA3, "Ta3" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ {ORAN_FH_CONFIG_T1A_CP_DL, "T1a_cp_dl" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ {ORAN_FH_CONFIG_T1A_CP_UL, "T1a_cp_ul" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ {ORAN_FH_CONFIG_T1A_UP, "T1a_up" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index 8f81337855..cb48569989 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -31,7 +31,6 @@ #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "openair1/PHY/defs_gNB.h" -#include "common/utils/threadPool/thread-pool.h" #include "oaioran.h" #include "oran-config.h" diff --git a/radio/rfsimulator/README.md b/radio/rfsimulator/README.md index 39e34ce651..dac8b155ad 100644 --- a/radio/rfsimulator/README.md +++ b/radio/rfsimulator/README.md @@ -114,19 +114,37 @@ $OPENAIR_DIR/cmake_targets/ran_build/build/conf2uedata -c $OPENAIR_DIR/openair3/ Similarly as for 4G, first launch the gNB, here in an example for the phytest: -```bash -sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --gNBs.[0].min_rxtxtime 6 --phy-test --rfsim --rfsimulator.serveraddr server -``` +run gNB: -`--gNBs.[0].min_rxtxtime 6` is due to the UE not being able to handle shorter + ```bash + sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --gNBs.[0].min_rxtxtime 6 --phy-test --rfsim --rfsimulator.serveraddr server + ``` + +where `--gNBs.[0].min_rxtxtime 6` is due to the UE not being able to handle shorter RX/TX times. As in the 4G case above, you can define an `rfsimulator` section in the config file. -Then, launch the UE: +and run UE: -```bash -sudo ./nr-uesoftmodem --rfsim --phy-test --rfsimulator.serveraddr -``` + ```bash + sudo ./nr-uesoftmodem --rfsim --phy-test --rfsimulator.serveraddr + ``` + +To run OAI RFSimulator for SA mode, gNB: + + ```bash + sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --rfsim --rfsimulator.serveraddr server + ``` + +and UE: + + ```bash + sudo ./nr-uesoftmodem --rfsim --rfsimulator.serveraddr + ``` + +In the commands for the UE, `TARGET_GNB_IP_ADDRESS` can be 127.0.0.1 if both UE and gNB run on the same machine. + +If necessary the user can provide a custom UICC configuration file to the UE with command line option `-O ue.conf`. In case of a multi-UE scenario, the user shall provide a different IMSI to each UE with the command line option `--uicc0.imsi` followed by the IMSI, e.g. `--uicc0.imsi 001010000000001`. Notes: diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf index 5072dc32bb..10decbaf1d 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf @@ -253,11 +253,6 @@ fhi_72 = { ru_addr = ("8c:1f:64:d1:10:46","8c:1f:64:d1:10:46"); mtu = 9600; fh_config = ({ - Tadv_cp_dl = 125; - T2a_cp_dl = (259, 500); - T2a_cp_ul = (25, 500); - T2a_up = (134, 375); - Ta3 = (152, 160); T1a_cp_dl = (419, 470); T1a_cp_ul = (285, 336); T1a_up = (294, 345); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf index fa54c07424..79c6e02f30 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf @@ -255,11 +255,6 @@ fhi_72 = { fh_config = ( # RAN650 #1 { - Tadv_cp_dl = 125; - T2a_cp_dl = (259, 500); - T2a_cp_ul = (25, 500); - T2a_up = (134, 375); - Ta3 = (152, 160); T1a_cp_dl = (419, 470); T1a_cp_ul = (285, 336); T1a_up = (294, 345); @@ -271,11 +266,6 @@ fhi_72 = { }, # RAN650 #2 { - Tadv_cp_dl = 125; - T2a_cp_dl = (259, 500); - T2a_cp_ul = (25, 500); - T2a_up = (134, 375); - Ta3 = (152, 160); T1a_cp_dl = (419, 470); T1a_cp_ul = (285, 336); T1a_up = (294, 345); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf index 8f9d6460c7..c92bf1d0ce 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf @@ -269,11 +269,6 @@ fhi_72 = { ru_addr = ("98:ae:71:01:c5:eb", "98:ae:71:01:c5:eb"); mtu = 9600; fh_config = ({ - Tadv_cp_dl = 125; - T2a_cp_dl = (285, 429); - T2a_cp_ul = (285, 429); - T2a_up = (125, 428); - Ta3 = (130, 170); T1a_cp_dl = (285, 470); T1a_cp_ul = (285, 429); T1a_up = (125, 350); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf index ab97c214e2..d4ce05b5d5 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf @@ -266,11 +266,6 @@ fhi_72 = { ru_addr = ("98:ae:71:01:c5:eb", "98:ae:71:01:c5:eb"); mtu = 9600; fh_config = ({ - Tadv_cp_dl = 125; - T2a_cp_dl = (285, 429); - T2a_cp_ul = (285, 429); - T2a_up = (125, 428); - Ta3 = (130, 170); T1a_cp_dl = (285, 470); T1a_cp_ul = (285, 429); T1a_up = (125, 350); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf index 2954e6e096..86079fd7c4 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf @@ -268,11 +268,6 @@ fhi_72 = { ru_addr = ("98:ae:71:01:c5:eb", "98:ae:71:01:c5:eb"); mtu = 9600; fh_config = ({ - Tadv_cp_dl = 125; - T2a_cp_dl = (285, 429); - T2a_cp_ul = (285, 429); - T2a_up = (125, 428); - Ta3 = (130, 170); T1a_cp_dl = (285, 470); T1a_cp_ul = (285, 429); T1a_up = (125, 350); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf index 2c25a63348..a159cd5f9b 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf @@ -268,11 +268,6 @@ fhi_72 = { ru_addr = ("70:b3:d5:e1:5b:81", "70:b3:d5:e1:5b:81"); mtu = 9600; fh_config = ({ - Tadv_cp_dl = 125; - T2a_cp_dl = (259, 500); - T2a_cp_ul = (25, 500); - T2a_up = (134, 375); - Ta3 = (152, 160); T1a_cp_dl = (419, 470); T1a_cp_ul = (285, 336); T1a_up = (294, 345); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf index ba96da73ce..23da52e1f9 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf @@ -270,11 +270,6 @@ fhi_72 = { ru_addr = ("70:b3:d5:e1:5b:81", "70:b3:d5:e1:5b:81"); mtu = 9600; fh_config = ({ - Tadv_cp_dl = 125; - T2a_cp_dl = (259, 500); - T2a_cp_ul = (25, 500); - T2a_up = (134, 375); - Ta3 = (152, 160); T1a_cp_dl = (419, 470); T1a_cp_ul = (285, 336); T1a_up = (294, 345); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf index f1698391a0..cd994b246a 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf @@ -266,11 +266,6 @@ fhi_72 = { worker_cores = (2); ru_addr = ("e8:c7:4f:1e:c7:11", "e8:c7:4f:1e:c7:11"); fh_config = ({ - Tadv_cp_dl = 125; - T2a_cp_dl = (285, 429); - T2a_cp_ul = (285, 429); - T2a_up = (125, 428); - Ta3 = (130, 170); T1a_cp_dl = (285, 429); T1a_cp_ul = (285, 429); T1a_up = (96, 196); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf index cf3e429709..00ca853c6d 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf @@ -252,11 +252,6 @@ fhi_72 = { ru_addr = ("00:e0:0c:00:ae:06", "00:e0:0c:00:ae:06"); mtu = 9000; fh_config = ({ - Tadv_cp_dl = 125; - T2a_cp_dl = (285, 429); - T2a_cp_ul = (285, 429); - T2a_up = (125, 428); - Ta3 = (130, 170); T1a_cp_dl = (285, 470); T1a_cp_ul = (285, 429); T1a_up = (125, 350); diff --git a/tools/scripts/multi-ue.sh b/tools/scripts/multi-ue.sh new file mode 100644 index 0000000000..b495012de6 --- /dev/null +++ b/tools/scripts/multi-ue.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +ue_id=-1 + +create_namespace() { + ue_id=$1 + local name="ue$ue_id" + echo "creating namespace for UE ID ${ue_id} name ${name}" + ip netns add $name + ip link add v-eth$ue_id type veth peer name v-ue$ue_id + ip link set v-ue$ue_id netns $name + BASE_IP=$((200+ue_id)) + ip addr add 10.$BASE_IP.1.100/24 dev v-eth$ue_id + ip link set v-eth$ue_id up + iptables -t nat -A POSTROUTING -s 10.$BASE_IP.1.0/255.255.255.0 -o lo -j MASQUERADE + iptables -A FORWARD -i lo -o v-eth$ue_id -j ACCEPT + iptables -A FORWARD -o lo -i v-eth$ue_id -j ACCEPT + ip netns exec $name ip link set dev lo up + ip netns exec $name ip addr add 10.$BASE_IP.1.$ue_id/24 dev v-ue$ue_id + ip netns exec $name ip link set v-ue$ue_id up +} + +delete_namespace() { + local ue_id=$1 + local name="ue$ue_id" + echo "deleting namespace for UE ID ${ue_id} name ${name}" + ip link delete v-eth$ue_id + ip netns delete $name +} + +list_namespaces() { + ip netns list +} + +open_namespace() { + if [[ $ue_id -lt 1 ]]; then echo "error: no last UE processed"; exit 1; fi + local name="ue$ue_id" + echo "opening shell in namespace ${name}" + echo "type 'ip netns exec $name bash' in additional terminals" + ip netns exec $name bash +} + +usage () { + echo "$1 -c : create namespace \"ue\"" + echo "$1 -d : delete namespace \"ue\"" + echo "$1 -e : execute shell in last processed namespace" + echo "$1 -l : list namespaces" + echo "$1 -o : open shell in namespace \"ue\"" +} + +prog_name=$(basename $0) + +if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root"; exit 1; fi +if [[ $# -eq 0 ]]; then echo "error: no parameters given"; usage $prog_name; exit 1; fi + +while getopts c:d:ehlo: cmd +do + case "${cmd}" in + c) create_namespace ${OPTARG};; + d) delete_namespace ${OPTARG};; + e) open_namespace; exit;; + h) usage ${prog_name}; exit;; + l) list_namespaces;; + o) ue_id=${OPTARG}; open_namespace;; + /?) echo "Invalid option"; usage ${prog_name}; exit;; + esac +done