Merge branch 'integration_2023_w34' into 'develop'
integration_2023_w34 See merge request oai/openairinterface5g!2316 * !2283 going back to sync mode when cell is barred in MIB * !2290 fix gtp delete. we should not delete all bearer in case of dedicaded bearer release * !2299 fix-mem-overflow_64qam * !2288 NR UE avoid crashes upon renewal of SIB1 * !2279 web server enhancement and doc link fix * !2302 Tutorials: update links for Open Cells SIM Card programming tool and Ubuntu 22.04 LTS * !2303 NR gNB limit on PUCCH bits to be scheduled * !2207 Use F1 internally: UE Context Modification Required * !2315 Fix LCID to RB association, allow more than 8 LCIDs in the UE
This commit is contained in:
+3
-6
@@ -1403,9 +1403,6 @@ if(E2_AGENT)
|
||||
endif()
|
||||
|
||||
|
||||
add_library(MAC_NR ${MAC_NR_SRC})
|
||||
target_link_libraries(MAC_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
|
||||
add_library(MAC_UE_NR ${MAC_NR_SRC_UE})
|
||||
target_link_libraries(MAC_UE_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
|
||||
@@ -2233,7 +2230,7 @@ add_executable(nr_dlsim
|
||||
${PHY_INTERFACE_DIR}/queue_t.c
|
||||
)
|
||||
target_link_libraries(nr_dlsim PRIVATE
|
||||
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
|
||||
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
|
||||
m pthread ${T_LIB} ITTI dl shlib_loader
|
||||
)
|
||||
target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
@@ -2277,7 +2274,7 @@ if (ENABLE_LDPC_T1)
|
||||
endif()
|
||||
|
||||
target_link_libraries(nr_ulsim PRIVATE
|
||||
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
|
||||
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
|
||||
m pthread ${T_LIB} ITTI dl shlib_loader
|
||||
)
|
||||
target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
@@ -2339,7 +2336,7 @@ if (${T_TRACER})
|
||||
NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
|
||||
MISC_NFAPI_LTE_LIB MISC_NFAPI_NR_LIB
|
||||
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
|
||||
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_NR MAC_UE_NR ngap
|
||||
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_UE_NR ngap
|
||||
CN_UTILS GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE NB_IoT SIMU SIMU_ETH OPENAIR0_LIB
|
||||
ldpc_orig ldpc_optim ldpc_optim8seg ldpc dfts)
|
||||
if (TARGET ${i})
|
||||
|
||||
@@ -43,7 +43,7 @@ services:
|
||||
container_name: sa-du-b200-gnb
|
||||
environment:
|
||||
USE_B2XX: 'yes'
|
||||
USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 14 --RUs.[0].att_tx 14
|
||||
USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 18 --RUs.[0].att_tx 18
|
||||
volumes:
|
||||
- ../../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf
|
||||
- /dev:/dev
|
||||
|
||||
@@ -26,7 +26,7 @@ services:
|
||||
container_name: sa-du-b200-gnb
|
||||
environment:
|
||||
USE_B2XX: 'yes'
|
||||
USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --telnetsrv --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 14 --RUs.[0].att_tx 14
|
||||
USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --telnetsrv --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 18 --RUs.[0].att_tx 18
|
||||
volumes:
|
||||
- ../../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf
|
||||
- /dev:/dev
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
The oai web server is an optional monitoring and debugging tool. Purpose is to give access to oai softmodems functionalities via a web interface. In this first release interface to the telnet server commands and to the softscope are delivered.
|
||||
The oai web server is an optional monitoring and debugging tool. Purpose is to give access to oai softmodems functionalities via a web interface. In this release interface to the telnet server commands and to the softscope are delivered.
|
||||
|
||||
* [Using the web server](webserverusage.md)
|
||||
* [enhancing the webserver](webserverdevcmd.md)
|
||||
* [web server architecture ](webserverarch.md)
|
||||
* [Using the web server](websrvuse.md)
|
||||
* [enhancing the webserver](websrvdev.md)
|
||||
* [web server architecture ](websrvarch.md)
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
# web server interface principles
|
||||
|
||||
The web server interface is implemented in two parts: a back-end, included in the softmodem process and a front-end which is a browser application.
|
||||
The web server interface is implemented in two parts: a back-end, included in the softmodem process and a front-end which is a browser application.
|
||||
|
||||
The oai web server back-end is implemented in a shared library to be loaded by the [oai shared library loader](loader) when `--websrv` option is specified on the command line. `libwebsrv.so ` code is common to all oai softmodem executables, the current release has been tested with the nr UE and the gNB.
|
||||
The oai web server back-end is implemented in a shared library to be loaded by the [oai shared library loader](../../DOC/loader.md) when `--websrv` option is specified on the command line. `libwebsrv.so` code is common to all oai softmodem executables,
|
||||
the current release has been tested with the nr UE and the gNB.
|
||||
|
||||
The front-end is an [angular](https://angular.io/docs) application. After being built and installed it is delivered to browsers by the back-end at connection time.
|
||||
|
||||
Front-end and back-end communicate via http request - http response transactions, including `json` body. these `json` interfaces are defined in the [frontend/src/app/api/XXXX.api.ts](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/websrv/src/frontend/src/app/api/) files. Back-end decapsulates the http requests it receives, looking for the `json`body to determine the requested information or command. Then the back-end builds a http response, with a `json`body encapsulating the requested information or the requested command result.
|
||||
Front-end and back-end communicate via http request - http response transactions, including `json` body. these `json` interfaces are defined in the [frontend/src/app/api/XXXX.api.ts](../frontend/src/app/api/) files.
|
||||
Back-end uses a callback machanism to map received http requests to dedicated functions. Typically a callback function decapsulates the http requests it receives, looking for the `json`body to determine the requested information or command. Then the back-end builds a
|
||||
http response, with a `json`body encapsulating the requested information or the requested command result.
|
||||
|
||||
When unsolicited communication, from back-end to front-end is necessary, a [websocket](https://www.rfc-editor.org/rfc/rfc6455) link is opened. This is the case for the softscope interface.
|
||||
|
||||
# web server interface source files
|
||||
|
||||
web server source files are located in [common/utils/websrv](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/websrv)
|
||||
web server source files are located in [common/utils/websrv](..)
|
||||
|
||||
1. back-end files are directly located in the `websrv` repository
|
||||
1. The [frontend/src](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/websrv/src/frontend) sub-directory contains the angular front-end source tree.
|
||||
1. [common/utils/websrv/helpfiles](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/websrv/helpfiles) contains files delivered to the front-end to respond to help requests.
|
||||
1. The [frontend/src](../frontend/src) sub-directory contains the angular front-end source tree.
|
||||
1. [common/utils/websrv/helpfiles](../helpfiles) contains files delivered to the front-end to respond to help requests.
|
||||
|
||||
[oai web server interface home](websrv.md)
|
||||
[oai web server interface home](websrv.md)
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# enhancing the web server
|
||||
|
||||
###### development platform
|
||||
|
||||
Backend devlopment is classical C programming, using [libulfius](https://github.com/babelouest/ulfius/blob/master/API.md) for the web server implementation
|
||||
and [libjansson](https://jansson.readthedocs.io/en/latest/) for formatting and accessing the JSON http bodies which are used by the angular frontend to exchange data with the server.
|
||||
The backend processes the http requests coming from the frontend using the ulfius callback mechanism. backend can also send unsollicited data to the frontend using a websocket
|
||||
|
||||
Frontend has been developped using the [angular framework](https://angular.io/) which implies TypeScript and HTML programming with the specificity of the node.js libraries and
|
||||
angular extensions.
|
||||
|
||||
Debugging the frontend side may be more difficult than the backend, some tools may help:
|
||||
- Some IDE such as [vscode]( https://code.visualstudio.com/) are "angular aware" and can ease debugging your modifications .
|
||||
- Setting UTIL log level to informational in the backend and websrv debug flag to 2 ( `--log_config.util_log_level info --websrv.debug 2` ) will trigger backend traces which may help, including the dump of JSON type http content
|
||||
- Browser devloper tools such as console may also help
|
||||
|
||||
There is a dedicated CMakeLists.txt, located in the websrv directory, to build both backend and frontend. Including the websrv option when configuring cmake ( `./build_oai --build-lib websrv` ) is required to be able to include the web server targets in the oai build scripts (either Makefile or ninja).
|
||||
`libwebsrv.so` shared library is the backend binary. It is possibly dynamically loaded at runtime, which then triggers the execution of the
|
||||
`websrv_autoinit` function that initializes the http server. Re-building the backend can be done using either `make websrv` or `ninja websrv` and it also re-builds the frontend .
|
||||
|
||||
The frontend run-time is made of a set of files generated from the TypeScript, HTML, CSS sources via the npm utility. It also includes some directly edited files such as the helpfiles. Frontend run-time is installed in the `websrv` sub-directory of the build path
|
||||
(usually `<oai repository>/cmake_targets/ran_build/build`) Re-building frontend can be done via the websrvfront target: `make websrvfront` or `ninja websrvfront`.
|
||||
|
||||
|
||||
###### backend source files
|
||||
|
||||
They are all located in the websrv repository
|
||||
| source file |description |
|
||||
|---|---|
|
||||
| websrv.c | main backend file, starts the http server and contains functions for telnet server interface ( softmodem commands tab) |
|
||||
| websrv.h | the only web server include file, contains utils prototypes, constants definitions, message definitions. Note that it must be kept consistent with frontend, unfortunatly we have not found a way to have common include files between C and javascript |
|
||||
| websrv_utils.c | utility functions common to all backend sources: dump http request and JSON content. format string response from a file, a C string, a buffer asynchronously loaded. format help from help file |
|
||||
| websrv_websockets.c | contains functions for the softscope interface (scope tab): initialize, close websocket, dispatch incoming messages, send a websocket message to frontend |
|
||||
| websrv_scope.c | softscope specific functions: callbacks to process softope frontend request and function to send, receive and process softscope websocket messages |
|
||||
| websrv_noforms.c websrv_noforms.h | stub functions to help using a common softscope interface for xforms softscope and the webserver softscope, could be removed when improving softscope architecture (don't use interface specific function in nr_physcope.c) |
|
||||
|
||||
|
||||
###### main frontend source files
|
||||
|
||||
Frontend directory tree comes from the angular framework. The root of this tree is `websrv/frontend/`. Main sub directories or files are:
|
||||
|
||||
- `src/app/api` contains TypeScript files with functions to send http requests to the backend. These functions are used from components sources.
|
||||
- `src/app/components/<component name>` contains the code (TypeScript, HTML and possibly CSS or XCSS) for a web page, for example the softscope, or popup page used to ask a question or return transaction status.
|
||||
- `src/app/components/controls` contains TypeScript code used for managing some form fields used in the `softmodem commands` tab.
|
||||
- `src/app/components/services` contain TypeScript code for utilities such as managing the websocket interface with the backend or downloading a file.
|
||||
- `src/app/app-routing-module.ts` defines mapping between urls as entered by user and components
|
||||
- `src/app/app.component.ts` `src/app/app.component.html` define the first page displayed to user
|
||||
- `src/environments` contains environment.<build type>.ts file wich defines the `environment` variable depending on the build type. The delivered build scripts are using the `prod` version which has been written to make frontend and backend to interact properly in a production platform. Other build type is to be used in debug environment where frontend is not downloaded from the backend.
|
||||
- `src/commondefs.ts`: constant definitions common to several TypeScript sources
|
||||
|
||||
|
||||
[oai web serverinterface home](websrv.md)
|
||||
@@ -1,102 +1,299 @@
|
||||
back-end and front-end are both built when the build of the `websrv` optional library is requested. When cmake configuration has been completed, with websrv enabled,font-end and back-end can be built separatly, using respectively `make frontend` or `make websrv` from the build repository.
|
||||
## building the webserver
|
||||
|
||||
When all dependencies are met, you can build the web server interface components using the build_oai script with the `--build-lib all` option . As the web interface is an optional component, if it's dependencies are not found it won't stop the build. Web interface components (back-end or front-end) which cannot be built are just skipped. If you specifically ask for the webserver build ( `--build-lib websrv`) the build will fail if dependencies check failed.
|
||||
|
||||
###### build example when missing dependencies
|
||||
back-end (the http server) and front-end (the html and javascript code for the browsers) are both built when the build of the `websrv` optional library is requested.
|
||||
|
||||
You can include the web server interface components in your build using the build_oai script with the `--build-lib "telnetsrv websrv"` option.
|
||||
The related cmake cache entry in `ran_build/build/CMakeCache.txt` for building the web server
|
||||
is `ENABLE_WEBSRV:BOOL=ON`
|
||||
|
||||
When cmake configuration has been completed, with websrv enabled and all dependencies met,font-end and back-end
|
||||
can be built separately, using respectively `make websrvfront` or `make websrv` from the build repository (replace make by ninja if you
|
||||
build using ninja).
|
||||
|
||||
|
||||
|
||||
###### build example when back-end dependency is not installed
|
||||
|
||||
```
|
||||
./build_oai --build-lib all
|
||||
Enabling build of all optional shared libraries (telnetsrv enbscope uescope nrscope websrv websrvfront)
|
||||
RF HW set to None
|
||||
OPENAIR_DIR = /usr/local/oai/websrv3/openairinterface5g
|
||||
FreeDiameter prefix not found, install freeDiameter if EPC, HSS
|
||||
running cmake -DENABLE_WEBSRV=ON -DENABLE_TELNETSRV=ON ../../..
|
||||
NETTLE VERSION_INSTALLED = 3.5.1
|
||||
NETTLE_VERSION_MAJOR = 3
|
||||
NETTLE_VERSION_MINOR = 5
|
||||
cuda include /usr/include
|
||||
cuda library
|
||||
./build_oai --gNB --nrUE -w USRP --build-lib "telnetsrv websrv nrscope"
|
||||
Will compile gNB
|
||||
Will compile NR UE
|
||||
Enabling build of optional shared library telnetsrv
|
||||
Enabling build of optional shared library websrv
|
||||
Enabling build of optional shared library nrscope
|
||||
OPENAIR_DIR = /usr/local/oai/develop_unmodified/openairinterface5g
|
||||
Running "cmake -DOAI_USRP=ON -DENABLE_TELNETSRV=ON -DENABLE_WEBSRV=ON -DENABLE_NRSCOPE=ON ../../.."
|
||||
-- The C compiler identification is GNU 11.4.0
|
||||
-- The CXX compiler identification is GNU 11.4.0
|
||||
-- Detecting C compiler ABI info
|
||||
-- Detecting C compiler ABI info - done
|
||||
-- Check for working C compiler: /usr/bin/cc - skipped
|
||||
-- Detecting C compile features
|
||||
-- Detecting C compile features - done
|
||||
-- Detecting CXX compiler ABI info
|
||||
-- Detecting CXX compiler ABI info - done
|
||||
-- Check for working CXX compiler: /usr/bin/c++ - skipped
|
||||
-- Detecting CXX compile features
|
||||
-- Detecting CXX compile features - done
|
||||
-- Ccache not found. Consider installing it for faster compilation. Command: sudo apt/dnf install ccache
|
||||
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.2")
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -gen-APER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-UPER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-JER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-BER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-OER
|
||||
-- CMAKE_BUILD_TYPE is RelWithDebInfo
|
||||
-- CPUARCH x86_64
|
||||
-- AVX512 intrinsics are OFF
|
||||
-- AVX2 intrinsics are ON
|
||||
-- No T1 Offload support detected
|
||||
gcc -Wall -I. -I.. -I../itti -I../../../openair2/COMMON -Itracer -o _check_vcd check_vcd.c tracer/database.c tracer/utils.c -lm -pthread
|
||||
./_check_vcd || (rm -f ./_check_vcd ./T_IDs.h ./T_messages.txt.h && false)
|
||||
rm -f ./_check_vcd
|
||||
-- Found Git: /usr/bin/git (found version "2.34.1")
|
||||
-- Checking for module 'libconfig'
|
||||
-- Found libconfig, version 1.5
|
||||
-- Checking for module 'openssl'
|
||||
-- Found openssl, version 3.0.2
|
||||
-- Checking for module 'blas'
|
||||
-- Found blas, version 3.10.3
|
||||
-- Checking for module 'lapacke'
|
||||
-- Found lapacke, version 3.10.0
|
||||
-- Checking for module 'cblas'
|
||||
-- No package 'cblas' found
|
||||
-- Add enb specific telnet functions in libtelnetsrv_enb.so
|
||||
-- No specific telnet functions for gnb
|
||||
-- No specific telnet functions for 4Gue
|
||||
-- Add 5Gue specific telnet functions in libtelnetsrv_5Gue.so
|
||||
CMake Error at common/utils/websrv/CMakeLists.txt:3 (message):
|
||||
ulfius library (https://github.com/babelouest/ulfius) not found, install
|
||||
libulfius-dev (ubuntu) if you need to build websrv back-end
|
||||
-- Add CI specific telnet functions in libtelnetsrv_ci.so
|
||||
CMake Error at common/utils/websrv/CMakeLists.txt:31 (find_library):
|
||||
Could not find ULFIUS using the following names: libulfius.so
|
||||
-- Configuring incomplete, errors occurred!
|
||||
See also "/usr/local/oai/develop_unmodified/openairinterface5g/cmake_targets/ran_build/build/CMakeFiles/CMakeOutput.log".
|
||||
build have failed
|
||||
```
|
||||
You can fix this first dependency problem, the backend dependency, by installing the libulfius library:
|
||||
|
||||
On ubuntu: `sudo apt-get install libulfius-dev`, for fedora: `dnf install libulfius`. Some distribution don't have
|
||||
libulfius package, instruction to install it can be found [here](https://github.com/babelouest/ulfius/blob/master/INSTALL.md)
|
||||
|
||||
###### build example when front-end dependency is not installed
|
||||
```
|
||||
./build_oai --build-lib "websrv telnetsrv nrscope"
|
||||
|
||||
|
||||
|
||||
./build_oai --gNB --nrUE -w USRP --build-lib "telnetsrv websrv nrscope"
|
||||
Will compile gNB
|
||||
Will compile NR UE
|
||||
Enabling build of optional shared library telnetsrv
|
||||
Enabling build of optional shared library websrv
|
||||
Enabling build of optional shared library nrscope
|
||||
OPENAIR_DIR = /usr/local/oai/develop_unmodified/openairinterface5g
|
||||
Running "cmake -DOAI_USRP=ON -DENABLE_TELNETSRV=ON -DENABLE_WEBSRV=ON -DENABLE_NRSCOPE=ON ../../.."
|
||||
-- Ccache not found. Consider installing it for faster compilation. Command: sudo apt/dnf install ccache
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -gen-APER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-UPER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-JER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-BER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-OER
|
||||
-- CMAKE_BUILD_TYPE is RelWithDebInfo
|
||||
-- CPUARCH x86_64
|
||||
-- AVX512 intrinsics are OFF
|
||||
-- AVX2 intrinsics are ON
|
||||
-- Checking for module 'cblas'
|
||||
-- No package 'cblas' found
|
||||
-- Add enb specific telnet functions in libtelnetsrv_enb.so
|
||||
-- No specific telnet functions for gnb
|
||||
-- No specific telnet functions for 4Gue
|
||||
-- Add 5Gue specific telnet functions in libtelnetsrv_5Gue.so
|
||||
-- Add CI specific telnet functions in libtelnetsrv_ci.so
|
||||
-- found libulfius for websrv
|
||||
-- found libjansson for websrv
|
||||
CMake Error at common/utils/websrv/CMakeLists.txt:45 (find_program):
|
||||
Could not find NPM using the following names: npm
|
||||
|
||||
|
||||
-- Configuring incomplete, errors occurred!
|
||||
See also "/usr/local/oai/websrv3/openairinterface5g/cmake_targets/ran_build/build/CMakeFiles/CMakeOutput.log".
|
||||
See also "/usr/local/oai/websrv3/openairinterface5g/cmake_targets/ran_build/build/CMakeFiles/CMakeError.log".
|
||||
See also "/usr/local/oai/develop_unmodified/openairinterface5g/cmake_targets/ran_build/build/CMakeFiles/CMakeOutput.log".
|
||||
build have failed
|
||||
```
|
||||
Currently the web server frontend can run with nodejs 18, you can check the version (if any) installed on your system entering the `node -v` command.
|
||||
|
||||
###### build example (build-lib all) when dependencies are met
|
||||
```
|
||||
./build_oai --build-lib all
|
||||
Enabling build of all optional shared libraries (telnetsrv enbscope uescope nrscope websrv websrvfront)
|
||||
RF HW set to None
|
||||
OPENAIR_DIR = /usr/local/oai/websrv3/openairinterface5g
|
||||
FreeDiameter prefix not found, install freeDiameter if EPC, HSS
|
||||
running cmake -DENABLE_WEBSRV=ON -DENABLE_TELNETSRV=ON ../../..
|
||||
NETTLE VERSION_INSTALLED = 3.5.1
|
||||
NETTLE_VERSION_MAJOR = 3
|
||||
NETTLE_VERSION_MINOR = 5
|
||||
cuda include /usr/include
|
||||
cuda library
|
||||
To prevent difficult situations with nodejs or npm versions it is better to specifically install the required nodejs version (after removing existing versions of npm and nodejs), as explained
|
||||
[here](https://www.stewright.me/2023/04/install-nodejs-18-on-ubuntu-22-04/) for ubuntu. Similar instructions can be found for other distributions.
|
||||
It is also possible to make several nodejs versions co-habiting on your system, this is beyond this doc.
|
||||
|
||||
|
||||
###### example: installing nodejs 18 on ubuntu
|
||||
```
|
||||
|
||||
curl -s https://deb.nodesource.com/setup_18.x | sudo bash
|
||||
|
||||
## Installing the NodeSource Node.js 18.x repo...
|
||||
|
||||
|
||||
## Populating apt-get cache...
|
||||
|
||||
+ apt-get update
|
||||
Get:1 http://security.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
|
||||
Hit:2 http://us.archive.ubuntu.com/ubuntu jammy InRelease
|
||||
Get:3 http://security.ubuntu.com/ubuntu jammy-security/main i386 Packages [305 kB]
|
||||
Get:4 http://security.ubuntu.com/ubuntu jammy-security/main amd64 Packages [678 kB]
|
||||
Get:5 http://us.archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]
|
||||
Get:6 http://security.ubuntu.com/ubuntu jammy-security/main amd64 DEP-11 Metadata [42.8 kB]
|
||||
Get:7 http://security.ubuntu.com/ubuntu jammy-security/main amd64 c-n-f Metadata [11.2 kB]
|
||||
Get:8 http://security.ubuntu.com/ubuntu jammy-security/universe i386 Packages [553 kB]
|
||||
Get:9 http://us.archive.ubuntu.com/ubuntu jammy-backports InRelease [109 kB]
|
||||
Get:10 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 Packages [770 kB]
|
||||
Get:11 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 DEP-11 Metadata [39.8 kB]
|
||||
Get:12 http://us.archive.ubuntu.com/ubuntu jammy-updates/main i386 Packages [471 kB]
|
||||
Get:13 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages [892 kB]
|
||||
Get:14 http://us.archive.ubuntu.com/ubuntu jammy-updates/main Translation-en [214 kB]
|
||||
Get:15 http://us.archive.ubuntu.com/ubuntu jammy-updates/main amd64 DEP-11 Metadata [100 kB]
|
||||
Get:16 http://us.archive.ubuntu.com/ubuntu jammy-updates/restricted amd64 Packages [714 kB]
|
||||
Get:17 http://us.archive.ubuntu.com/ubuntu jammy-updates/restricted Translation-en [114 kB]
|
||||
Get:18 http://us.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 Packages [968 kB]
|
||||
Get:19 http://us.archive.ubuntu.com/ubuntu jammy-updates/universe i386 Packages [648 kB]
|
||||
Get:20 http://us.archive.ubuntu.com/ubuntu jammy-updates/universe Translation-en [211 kB]
|
||||
Get:21 http://us.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 DEP-11 Metadata [288 kB]
|
||||
Get:22 http://us.archive.ubuntu.com/ubuntu jammy-updates/multiverse amd64 DEP-11 Metadata [940 B]
|
||||
Get:23 http://us.archive.ubuntu.com/ubuntu jammy-backports/main amd64 DEP-11 Metadata [4,924 B]
|
||||
Get:24 http://us.archive.ubuntu.com/ubuntu jammy-backports/universe amd64 DEP-11 Metadata [15.6 kB]
|
||||
Fetched 7,379 kB in 4s (2,095 kB/s)
|
||||
Reading package lists... Done
|
||||
|
||||
## Confirming "jammy" is supported...
|
||||
|
||||
+ curl -sLf -o /dev/null 'https://deb.nodesource.com/node_18.x/dists/jammy/Release'
|
||||
|
||||
## Adding the NodeSource signing key to your keyring...
|
||||
|
||||
+ curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | gpg --dearmor | tee /usr/share/keyrings/nodesource.gpg >/dev/null
|
||||
|
||||
## Creating apt sources list file for the NodeSource Node.js 18.x repo...
|
||||
|
||||
+ echo 'deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x jammy main' > /etc/apt/sources.list.d/nodesource.list
|
||||
+ echo 'deb-src [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x jammy main' >> /etc/apt/sources.list.d/nodesource.list
|
||||
|
||||
## Running `apt-get update` for you...
|
||||
|
||||
+ apt-get update
|
||||
Hit:1 http://security.ubuntu.com/ubuntu jammy-security InRelease
|
||||
Get:2 https://deb.nodesource.com/node_18.x jammy InRelease [4,563 B]
|
||||
Get:3 https://deb.nodesource.com/node_18.x jammy/main amd64 Packages [776 B]
|
||||
Hit:4 http://us.archive.ubuntu.com/ubuntu jammy InRelease
|
||||
Hit:5 http://us.archive.ubuntu.com/ubuntu jammy-updates InRelease
|
||||
Hit:6 http://us.archive.ubuntu.com/ubuntu jammy-backports InRelease
|
||||
Fetched 5,339 B in 1s (7,666 B/s)
|
||||
Reading package lists... Done
|
||||
|
||||
## Run `sudo apt-get install -y nodejs` to install Node.js 18.x and npm
|
||||
## You may also need development tools to build native addons:
|
||||
sudo apt-get install gcc g++ make
|
||||
## To install the Yarn package manager, run:
|
||||
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null
|
||||
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
|
||||
sudo apt-get update && sudo apt-get install yarn
|
||||
|
||||
|
||||
sudo apt install nodejs -y
|
||||
Reading package lists... Done
|
||||
Building dependency tree... Done
|
||||
Reading state information... Done
|
||||
The following packages were automatically installed and are no longer required:
|
||||
diodon libdiodon0 libxdo3 xdotool
|
||||
Use 'sudo apt autoremove' to remove them.
|
||||
The following NEW packages will be installed:
|
||||
nodejs
|
||||
0 upgraded, 1 newly installed, 0 to remove and 8 not upgraded.
|
||||
Need to get 28.9 MB of archives.
|
||||
After this operation, 188 MB of additional disk space will be used.
|
||||
Get:1 https://deb.nodesource.com/node_18.x jammy/main amd64 nodejs amd64 18.17.1-deb-1nodesource1 [28.9 MB]
|
||||
Fetched 28.9 MB in 3s (11.3 MB/s)
|
||||
Selecting previously unselected package nodejs.
|
||||
(Reading database ... 399541 files and directories currently installed.)
|
||||
Preparing to unpack .../nodejs_18.17.1-deb-1nodesource1_amd64.deb ...
|
||||
Unpacking nodejs (18.17.1-deb-1nodesource1) ...
|
||||
Setting up nodejs (18.17.1-deb-1nodesource1) ...
|
||||
Processing triggers for man-db (2.10.2-1) ...
|
||||
|
||||
|
||||
```
|
||||
|
||||
###### build example when dependencies are met
|
||||
|
||||
|
||||
``` bash
|
||||
|
||||
./build_oai --ninja -c -C --gNB --nrUE -w USRP --build-lib "telnetsrv websrv nrscope"
|
||||
Will compile gNB
|
||||
Will compile NR UE
|
||||
Enabling build of optional shared library telnetsrv
|
||||
Enabling build of optional shared library websrv
|
||||
Enabling build of optional shared library nrscope
|
||||
OPENAIR_DIR = /usr/local/oai/develop_unmodified/openairinterface5g
|
||||
Erased all previously producted files
|
||||
Running "cmake -GNinja -DOAI_USRP=ON -DENABLE_TELNETSRV=ON -DENABLE_WEBSRV=ON -DENABLE_NRSCOPE=ON ../../.."
|
||||
-- The C compiler identification is GNU 11.4.0
|
||||
-- The CXX compiler identification is GNU 11.4.0
|
||||
-- Detecting C compiler ABI info
|
||||
-- Detecting C compiler ABI info - done
|
||||
-- Check for working C compiler: /usr/bin/cc - skipped
|
||||
-- Detecting C compile features
|
||||
-- Detecting C compile features - done
|
||||
-- Detecting CXX compiler ABI info
|
||||
-- Detecting CXX compiler ABI info - done
|
||||
-- Check for working CXX compiler: /usr/bin/c++ - skipped
|
||||
-- Detecting CXX compile features
|
||||
-- Detecting CXX compile features - done
|
||||
-- Ccache not found. Consider installing it for faster compilation. Command: sudo apt/dnf install ccache
|
||||
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.2")
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -gen-APER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-UPER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-JER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-BER
|
||||
-- Check if /opt/asn1c/bin/asn1c supports -no-gen-OER
|
||||
-- CMAKE_BUILD_TYPE is RelWithDebInfo
|
||||
-- CPUARCH x86_64
|
||||
-- AVX512 intrinsics are OFF
|
||||
-- AVX2 intrinsics are ON
|
||||
-- No T1 Offload support detected
|
||||
gcc -Wall -I. -I.. -I../itti -I../../../openair2/COMMON -Itracer -o _check_vcd check_vcd.c tracer/database.c tracer/utils.c -lm -pthread
|
||||
./_check_vcd || (rm -f ./_check_vcd ./T_IDs.h ./T_messages.txt.h && false)
|
||||
rm -f ./_check_vcd
|
||||
-- Found Git: /usr/bin/git (found version "2.34.1")
|
||||
-- Checking for module 'libconfig'
|
||||
-- Found libconfig, version 1.5
|
||||
-- Checking for module 'openssl'
|
||||
-- Found openssl, version 3.0.2
|
||||
-- Checking for module 'blas'
|
||||
-- Found blas, version 3.10.3
|
||||
-- Checking for module 'lapacke'
|
||||
-- Found lapacke, version 3.10.0
|
||||
-- Checking for module 'cblas'
|
||||
-- No package 'cblas' found
|
||||
-- Add enb specific telnet functions in libtelnetsrv_enb.so
|
||||
-- No specific telnet functions for gnb
|
||||
-- No specific telnet functions for 4Gue
|
||||
-- Add 5Gue specific telnet functions in libtelnetsrv_5Gue.so
|
||||
-- Add CI specific telnet functions in libtelnetsrv_ci.so
|
||||
-- found libulfius for websrv
|
||||
-- found libjansson for websrv
|
||||
-- found npm for websrv
|
||||
-- Configuring webserver backend
|
||||
-- Configuring webserver frontend
|
||||
-- No Doxygen documentation requested
|
||||
-- libforms library, required for scopes, found at /usr/lib/libforms.so
|
||||
-- Found UHD: /usr/lib/x86_64-linux-gnu/libuhd.so
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: /usr/local/oai/websrv3/openairinterface5g/cmake_targets/ran_build/build
|
||||
Log file for compilation is being written to: /usr/local/oai/websrv3/openairinterface5g/cmake_targets/log/telnetsrv.txt
|
||||
telnetsrv compiled
|
||||
Log file for compilation is being written to: /usr/local/oai/websrv3/openairinterface5g/cmake_targets/log/enbscope.txt
|
||||
enbscope compiled
|
||||
Log file for compilation is being written to: /usr/local/oai/websrv3/openairinterface5g/cmake_targets/log/uescope.txt
|
||||
uescope compiled
|
||||
Log file for compilation is being written to: /usr/local/oai/websrv3/openairinterface5g/cmake_targets/log/nrscope.txt
|
||||
nrscope compiled
|
||||
Log file for compilation is being written to: /usr/local/oai/websrv3/openairinterface5g/cmake_targets/log/websrv.txt
|
||||
websrv compiled
|
||||
Log file for compilation is being written to: /usr/local/oai/websrv3/openairinterface5g/cmake_targets/log/websrvfront.txt
|
||||
websrvfront compiled
|
||||
BUILD SHOULD BE SUCCESSFUL
|
||||
-- Build files have been written to: /usr/local/oai/develop_unmodified/openairinterface5g/cmake_targets/ran_build/build
|
||||
cd /usr/local/oai/develop_unmodified/openairinterface5g/cmake_targets/ran_build/build
|
||||
Running "cmake --build . --target nr-softmodem nr-cuup nr-uesoftmodem oai_usrpdevif telnetsrv websrv nrscope params_libconfig coding rfsimulator dfts -- -j8"
|
||||
Log file for compilation is being written to: /usr/local/oai/develop_unmodified/openairinterface5g/cmake_targets/log/all.txt
|
||||
nr-softmodem nr-cuup nr-uesoftmodem oai_usrpdevif telnetsrv websrv nrscope params_libconfig coding rfsimulator dfts compiled
|
||||
BUILD SHOULD BE SUCCESSFUL
|
||||
|
||||
```
|
||||
|
||||
# building and installing the front-end after cmake has been configured
|
||||
###### building and installing the front-end after cmake has been successfully configured
|
||||
|
||||
Before building the front-end you need to install the npm node.js installer, otherwise the make target won't exist:
|
||||
|
||||
`apt-get install npm` for ubuntu or `dnf install npm`for fedora
|
||||
|
||||
then configure cmake to be able to build and install the frontend without using the build_oai script:
|
||||
|
||||
``` bash
|
||||
```
|
||||
cd \<oai repository\>/openairinterface5g/cmake_targets/ran_build/build
|
||||
make websrvfront
|
||||
up to date, audited 1099 packages in 3s
|
||||
@@ -135,29 +332,21 @@ Built target websrvfront
|
||||
```
|
||||
|
||||
|
||||
|
||||
# Building and installing the web server back-end after cmake has been configured
|
||||
|
||||
The back-end has two dependencies:
|
||||
|
||||
1. the [ulfius library](https://github.com/babelouest/ulfius) and the corresponding include files which are provided by the ubuntu libulfius-dev package: `sudo apt-get install -y libulfius-dev`
|
||||
2. the [jansson](https://github.com/akheron/jansson-debian) library and the corresponding include files which are provided by the ubuntu libjansson-dev package: `sudo apt-get install -y libjansson-dev`
|
||||
|
||||
Dependencies can also be installed on fedora distribution, the jansson package is `jansson-devel`, ulfius has to be installed as explained [here](https://github.com/babelouest/ulfius/blob/master/INSTALL.md#pre-compiled-packages).
|
||||
|
||||
The websrv targets won't be available till cmake has been successfully configured with the websrv option enabled
|
||||
###### building and installing the back-end after cmake has been successfully configured
|
||||
|
||||
```bash
|
||||
cd \<oai repository\>/openairinterface5g
|
||||
cd <oai repository>/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets
|
||||
./build_oai --build-lib websrv
|
||||
```
|
||||
or, without the help of the `build_oai` script:
|
||||
|
||||
```bash
|
||||
cd \<oai repository\>/openairinterface5g/cmake_targets/ran_build/build
|
||||
make websrv
|
||||
```
|
||||
|
||||
This will create the `libwebsrv.so` file in the `targets/bin` and `cmake_targets/ran_build/build` sub directories of the oai repository.
|
||||
|
||||
When starting the softmodem, you must specify the **_\-\-websrv_** option to load and start the web server. The web server is loaded via the [oai shared library loader](loader).
|
||||
@@ -166,7 +355,7 @@ When starting the softmodem, you must specify the **_\-\-websrv_** option to loa
|
||||
|
||||
|
||||
## web server parameters
|
||||
The web server back-end is using the [oai configuration module](Config/Rtusage). web server parameters must be specified in the websrv section.
|
||||
The web server back-end is using the [oai configuration module](Config/Rtusage). web server parameters must be specified in the websrv section.
|
||||
|
||||
| name | type | default | description |
|
||||
|:---:|:---:|:---:|:----|
|
||||
@@ -180,7 +369,7 @@ The web server back-end is using the [oai configuration module](Config/Rtusage).
|
||||
## running the back-end
|
||||
To trigger the back-end use the `--websrv` option, possibly modifying the parameters as explained in the previous chapter. The two following commands allow starting the oai gNB and the oai 5G UE on the same computer, starting the telnet server and the web interface on both executables.
|
||||
|
||||
`./nr-softmodem -O /usr/local/oai/conf/gnb.band78.sa.fr1.106PRB.usrpb210.conf --rfsim --rfsimulator.serveraddr server --telnetsrv --telnetsrv.listenstdin --websrv --rfsimulator.options chanmod`
|
||||
`./nr-softmodem -O /usr/local/oai/conf/gnb.band78.sa.fr1.106PRB.usrpb210.conf --rfsim --rfsimulator.serveraddr server --telnetsrv --telnetsrv.listenstdin --websrv --rfsimulator.options chanmod`
|
||||
|
||||
.`/nr-uesoftmodem -O /usr/local/oai/conf/nrue_sim.conf --sa --numerology 1 -r 106 -C 3649440000 --rfsim --rfsimulator.serveraddr 127.0.0.1 --websrv --telnetsrv --websrv.listenport 8092 --telnetsrv.listenport 8091`
|
||||
|
||||
@@ -191,18 +380,20 @@ To trigger the back-end use the `--websrv` option, possibly modifying the parame
|
||||
Assuming that the previous commands run successfully and that you also run your browser on the same host, you should be able to connect to the gNB and UE web interface using respectively the following url's:
|
||||
|
||||
http://127.0.0.1:8090/websrv/index.html
|
||||
|
||||
http://127.0.0.1:8092/websrv/index.html
|
||||
|
||||
The interface should be intuitive enough, keeping in mind the following restrictions:
|
||||
|
||||
- The command tab is not available if the telnet server is not enabled
|
||||
- The softscope tab is not available if the xforms scope is started `(-d` option)
|
||||
- The softscope tab is not available if the xforms scope is started (`-d` option)
|
||||
- Only one connection is supported to a back-end, especially for the scope interface
|
||||
|
||||
Some front-end objects, which usage are less intuitive provide a tooltip to help interface usage.
|
||||
|
||||
## some webserver screenshots
|
||||

|
||||

|
||||

|
||||
- [main page](main.png)
|
||||
- [Configuring logs](logscfg.png)
|
||||
- [scope interface](scope.png)
|
||||
|
||||
[oai web serverinterface home](websrv.md)
|
||||
|
||||
@@ -21,7 +21,7 @@ In this tutorial we describe how to configure and run a 5G end-to-end setup with
|
||||
|
||||
Minimum hardware requirements:
|
||||
- Laptop/Desktop/Server for OAI CN5G and OAI gNB
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.3-desktop-amd64.iso)
|
||||
- CPU: 8 cores x86_64 @ 3.5 GHz
|
||||
- RAM: 32 GB
|
||||
- Laptop for UE
|
||||
@@ -45,7 +45,7 @@ Please install and configure OAI CN5G as described here:
|
||||
|
||||
|
||||
## 2.2 SIM Card
|
||||
Program SIM Card with [Open Cells Project](https://open-cells.com/) application [uicc-v2.6](https://open-cells.com/d5138782a8739209ec5760865b1e53b0/uicc-v2.6.tgz).
|
||||
Program SIM Card with [Open Cells Project](https://open-cells.com/) application [uicc-v3.2](https://open-cells.com/d5138782a8739209ec5760865b1e53b0/uicc-v3.2.tgz).
|
||||
|
||||
```bash
|
||||
sudo ./program_uicc --adm 12345678 --imsi 001010000000001 --isdn 00000001 --acc 0001 --key fec86ba6eb707ed08905757b1bb44b8f --opc C42449363BBAD02B66D16BC975D77CC1 -spn "OpenAirInterface" --authenticate
|
||||
|
||||
@@ -21,7 +21,7 @@ In this tutorial we describe how to configure and run a 5G end-to-end setup with
|
||||
|
||||
Minimum hardware requirements:
|
||||
- Laptop/Desktop/Server for OAI CN5G and OAI gNB
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.3-desktop-amd64.iso)
|
||||
- CPU: 8 cores x86_64 @ 3.5 GHz
|
||||
- RAM: 32 GB
|
||||
|
||||
|
||||
@@ -21,11 +21,11 @@ In this tutorial we describe how to configure and run a 5G end-to-end setup with
|
||||
|
||||
Minimum hardware requirements:
|
||||
- Laptop/Desktop/Server for OAI CN5G and OAI gNB
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.3-desktop-amd64.iso)
|
||||
- CPU: 8 cores x86_64 @ 3.5 GHz
|
||||
- RAM: 32 GB
|
||||
- Laptop for UE
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
|
||||
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.3-desktop-amd64.iso)
|
||||
- CPU: 8 cores x86_64 @ 3.5 GHz
|
||||
- RAM: 8 GB
|
||||
- [USRP B210](https://www.ettus.com/all-products/ub210-kit/), [USRP N300](https://www.ettus.com/all-products/USRP-N300/) or [USRP X300](https://www.ettus.com/all-products/x300-kit/)
|
||||
|
||||
@@ -465,6 +465,10 @@ static void UE_synch(void *arg) {
|
||||
} else {
|
||||
UE->is_synchronized = 1;
|
||||
}
|
||||
if (UE->synch_request.received_synch_request == 1) {
|
||||
UE->is_synchronized = 0;
|
||||
UE->synch_request.received_synch_request = 0;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (UE->UE_scan_carrier == 1) {
|
||||
|
||||
@@ -121,10 +121,7 @@ void nr_modulation(uint32_t *in,
|
||||
uint8_t* in_bytes = (uint8_t*) in;
|
||||
uint64_t* in64 = (uint64_t*) in;
|
||||
int64_t* out64 = (int64_t*) out;
|
||||
uint8_t idx;
|
||||
uint32_t i,j;
|
||||
uint32_t bit_cnt;
|
||||
uint64_t x,x1,x2;
|
||||
uint32_t i;
|
||||
|
||||
#if defined(__SSE2__)
|
||||
__m128i *nr_mod_table128;
|
||||
@@ -145,7 +142,7 @@ void nr_modulation(uint32_t *in,
|
||||
i = i*8/2;
|
||||
nr_mod_table32 = (int32_t*) nr_qpsk_mod_table;
|
||||
while (i<length/2) {
|
||||
idx = ((in_bytes[(i*2)/8]>>((i*2)&0x7)) & mask);
|
||||
const int idx = ((in_bytes[(i * 2) / 8] >> ((i * 2) & 0x7)) & mask);
|
||||
out32[i] = nr_mod_table32[idx];
|
||||
i++;
|
||||
}
|
||||
@@ -154,7 +151,7 @@ void nr_modulation(uint32_t *in,
|
||||
case 2:
|
||||
nr_mod_table32 = (int32_t*) nr_qpsk_mod_table;
|
||||
for (i=0; i<length/mod_order; i++) {
|
||||
idx = ((in[i*2/32]>>((i*2)&0x1f)) & mask);
|
||||
const int idx = ((in[i * 2 / 32] >> ((i * 2) & 0x1f)) & mask);
|
||||
out32[i] = nr_mod_table32[idx];
|
||||
}
|
||||
return;
|
||||
@@ -167,66 +164,68 @@ void nr_modulation(uint32_t *in,
|
||||
// the bits that are left out
|
||||
i = i*8/4;
|
||||
while (i<length/4) {
|
||||
idx = ((in_bytes[(i*4)/8]>>((i*4)&0x7)) & mask);
|
||||
const int idx = ((in_bytes[(i * 4) / 8] >> ((i * 4) & 0x7)) & mask);
|
||||
out32[i] = nr_16qam_mod_table[idx];
|
||||
i++;
|
||||
}
|
||||
return;
|
||||
|
||||
case 6:
|
||||
j = 0;
|
||||
for (i=0; i<length/192; i++) {
|
||||
x = in64[i*3];
|
||||
x1 = x&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x>>12)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x>>24)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x>>36)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x>>48)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x2 = (x>>60);
|
||||
x = in64[i*3+1];
|
||||
for (i = 0; i < length - 3 * 64; i += 3 * 64) {
|
||||
uint64_t x = *in64++;
|
||||
uint64_t x1 = x & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x >> 12) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x >> 24) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x >> 36) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x >> 48) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
uint64_t x2 = (x >> 60);
|
||||
x = *in64++;
|
||||
x2 |= x<<4;
|
||||
x1 = x2&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>12)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>24)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>36)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>48)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = x2 & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 12) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 24) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 36) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 48) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x2 = ((x>>56)&0xf0) | (x2>>60);
|
||||
x = in64[i*3+2];
|
||||
x = *in64++;
|
||||
x2 |= x<<8;
|
||||
x1 = x2&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>12)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>24)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>36)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (x2>>48)&4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = x2 & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 12) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 24) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 36) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (x2 >> 48) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x2 = ((x>>52)&0xff0) | (x2>>60);
|
||||
out64[j++] = nr_64qam_mod_table[x2];
|
||||
*out64++ = nr_64qam_mod_table[x2];
|
||||
}
|
||||
i *= 24;
|
||||
bit_cnt = i * 8;
|
||||
while (bit_cnt < length) {
|
||||
uint32_t xx;
|
||||
memcpy(&xx, in_bytes+i, sizeof(xx));
|
||||
x1 = xx & 4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
x1 = (xx >> 12) & 4095;
|
||||
out64[j++] = nr_64qam_mod_table[x1];
|
||||
i += 3;
|
||||
bit_cnt += 24;
|
||||
while (i + 24 <= length) {
|
||||
uint32_t xx = 0;
|
||||
memcpy(&xx, in_bytes + i / 8, 3);
|
||||
uint64_t x1 = xx & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
x1 = (xx >> 12) & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
i += 24;
|
||||
}
|
||||
if (i != length) {
|
||||
uint32_t xx = 0;
|
||||
memcpy(&xx, in_bytes + i / 8, 2);
|
||||
uint64_t x1 = xx & 0xfff;
|
||||
*out64++ = nr_64qam_mod_table[x1];
|
||||
}
|
||||
return;
|
||||
|
||||
|
||||
@@ -184,8 +184,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
///////////
|
||||
|
||||
uint32_t available_bits = G;
|
||||
uint32_t scrambled_output[(available_bits>>5)+1];
|
||||
memset(scrambled_output, 0, ((available_bits>>5)+1)*sizeof(uint32_t));
|
||||
// +1 because size can be not modulo 4
|
||||
uint32_t scrambled_output[available_bits / (8 * sizeof(uint32_t)) + 1];
|
||||
memset(scrambled_output, 0, sizeof(scrambled_output));
|
||||
|
||||
nr_pusch_codeword_scrambling(harq_process_ul_ue->f,
|
||||
available_bits,
|
||||
|
||||
@@ -40,6 +40,7 @@ MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_r
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_req_t, f1ap_ue_context_release_req)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_cmd)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_complete_t, f1ap_ue_context_release_complete)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_required_t, f1ap_ue_context_modification_required)
|
||||
|
||||
/* RRC -> F1AP messages */
|
||||
MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message )
|
||||
@@ -48,6 +49,8 @@ MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_se
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_resp)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_req_t, f1ap_ue_context_modification_req)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_resp_t, f1ap_ue_context_modification_resp)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_CONFIRM, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_confirm_t, f1ap_ue_context_modification_confirm)
|
||||
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REFUSE, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_refuse_t, f1ap_ue_context_modification_refuse)
|
||||
|
||||
/* CU -> DU*/
|
||||
MESSAGE_DEF(F1AP_PAGING_IND, MESSAGE_PRIORITY_MED, f1ap_paging_ind_t, f1ap_paging_ind)
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_req
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_resp
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_fail
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_required
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_CONFIRM(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_confirm
|
||||
#define F1AP_UE_CONTEXT_MODIFICATION_REFUSE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_refuse
|
||||
|
||||
#define F1AP_DL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_dl_rrc_message
|
||||
#define F1AP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_req
|
||||
@@ -417,6 +420,28 @@ typedef enum F1ap_Cause_e {
|
||||
F1AP_CAUSE_MISC,
|
||||
} f1ap_Cause_t;
|
||||
|
||||
typedef struct f1ap_ue_context_modif_required_t {
|
||||
uint32_t gNB_CU_ue_id;
|
||||
uint32_t gNB_DU_ue_id;
|
||||
du_to_cu_rrc_information_t *du_to_cu_rrc_information;
|
||||
f1ap_Cause_t cause;
|
||||
long cause_value;
|
||||
} f1ap_ue_context_modif_required_t;
|
||||
|
||||
typedef struct f1ap_ue_context_modif_confirm_t {
|
||||
uint32_t gNB_CU_ue_id;
|
||||
uint32_t gNB_DU_ue_id;
|
||||
uint8_t *rrc_container;
|
||||
int rrc_container_length;
|
||||
} f1ap_ue_context_modif_confirm_t;
|
||||
|
||||
typedef struct f1ap_ue_context_modif_refuse_t {
|
||||
uint32_t gNB_CU_ue_id;
|
||||
uint32_t gNB_DU_ue_id;
|
||||
f1ap_Cause_t cause;
|
||||
long cause_value;
|
||||
} f1ap_ue_context_modif_refuse_t;
|
||||
|
||||
typedef struct f1ap_ue_context_release_s {
|
||||
uint32_t gNB_CU_ue_id;
|
||||
uint32_t gNB_DU_ue_id;
|
||||
|
||||
@@ -184,6 +184,16 @@ void *F1AP_CU_task(void *arg) {
|
||||
&F1AP_PAGING_IND(received_msg));
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_MODIFICATION_CONFIRM:
|
||||
CU_send_UE_CONTEXT_MODIFICATION_CONFIRM(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
|
||||
&F1AP_UE_CONTEXT_MODIFICATION_CONFIRM(received_msg));
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_MODIFICATION_REFUSE:
|
||||
CU_send_UE_CONTEXT_MODIFICATION_REFUSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
|
||||
&F1AP_UE_CONTEXT_MODIFICATION_REFUSE(received_msg));
|
||||
break;
|
||||
|
||||
// case F1AP_SETUP_RESPONSE: // This is from RRC
|
||||
// CU_send_F1_SETUP_RESPONSE(instance, *f1ap_setup_ind, &(F1AP_SETUP_RESP) f1ap_setup_resp)
|
||||
// break;
|
||||
|
||||
@@ -1701,14 +1701,264 @@ int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance,
|
||||
AssertFatal(1==0,"Not implemented yet\n");
|
||||
}
|
||||
|
||||
int CU_handle_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
uint32_t stream,
|
||||
F1AP_F1AP_PDU_t *pdu) {
|
||||
AssertFatal(1==0,"Not implemented yet\n");
|
||||
int CU_handle_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
|
||||
MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_MODIFICATION_REQUIRED);
|
||||
f1ap_ue_context_modif_required_t *required = &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg_p);
|
||||
|
||||
F1AP_UEContextModificationRequired_t *container = &pdu->choice.initiatingMessage->value.choice.UEContextModificationRequired;
|
||||
F1AP_UEContextModificationRequiredIEs_t *ie = NULL;
|
||||
|
||||
/* required: GNB_CU_UE_F1AP_ID */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true);
|
||||
required->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
|
||||
/* required: GNB_DU_UE_F1AP_ID */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true);
|
||||
required->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
|
||||
/* optional: Resource Coordination Transfer Container */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of Resource Coordination Transfer Container not implemented\n");
|
||||
|
||||
/* optional: DU to CU RRC Information */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_DUtoCURRCInformation,
|
||||
false);
|
||||
if (ie != NULL) {
|
||||
F1AP_DUtoCURRCInformation_t *du2cu = &ie->value.choice.DUtoCURRCInformation;
|
||||
required->du_to_cu_rrc_information = malloc(sizeof(*required->du_to_cu_rrc_information));
|
||||
AssertFatal(required->du_to_cu_rrc_information != NULL, "memory allocation failed\n");
|
||||
|
||||
required->du_to_cu_rrc_information->cellGroupConfig = malloc(du2cu->cellGroupConfig.size);
|
||||
AssertFatal(required->du_to_cu_rrc_information->cellGroupConfig != NULL, "memory allocation failed\n");
|
||||
memcpy(required->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig.buf, du2cu->cellGroupConfig.size);
|
||||
required->du_to_cu_rrc_information->cellGroupConfig_length = du2cu->cellGroupConfig.size;
|
||||
|
||||
AssertFatal(du2cu->measGapConfig == NULL, "handling of measGapConfig not implemented\n");
|
||||
AssertFatal(du2cu->requestedP_MaxFR1 == NULL, "handling of requestedP_MaxFR1 not implemented\n");
|
||||
}
|
||||
|
||||
/* optional: DRB Required to Be Modified List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_DRBs_Required_ToBeModified_List,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of DRBs Required to be modified list not implemented\n");
|
||||
|
||||
/* optional: SRB Required to be Released List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_SRBs_Required_ToBeReleased_List,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of SRBs Required to be released list not implemented\n");
|
||||
|
||||
/* optional: DRB Required to be Released List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_DRBs_Required_ToBeReleased_List,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of DRBs Required to be released list not implemented\n");
|
||||
|
||||
/* mandatory: Cause */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Cause, true);
|
||||
switch (ie->value.choice.Cause.present) {
|
||||
case F1AP_Cause_PR_radioNetwork:
|
||||
required->cause = F1AP_CAUSE_RADIO_NETWORK;
|
||||
required->cause_value = ie->value.choice.Cause.choice.radioNetwork;
|
||||
break;
|
||||
case F1AP_Cause_PR_transport:
|
||||
required->cause = F1AP_CAUSE_TRANSPORT;
|
||||
required->cause_value = ie->value.choice.Cause.choice.transport;
|
||||
break;
|
||||
case F1AP_Cause_PR_protocol:
|
||||
required->cause = F1AP_CAUSE_PROTOCOL;
|
||||
required->cause_value = ie->value.choice.Cause.choice.protocol;
|
||||
break;
|
||||
case F1AP_Cause_PR_misc:
|
||||
required->cause = F1AP_CAUSE_MISC;
|
||||
required->cause_value = ie->value.choice.Cause.choice.misc;
|
||||
break;
|
||||
default:
|
||||
LOG_W(F1AP, "Unknown cause for UE Context Modification required message\n");
|
||||
/* fall through */
|
||||
case F1AP_Cause_PR_NOTHING:
|
||||
required->cause = F1AP_CAUSE_NOTHING;
|
||||
break;
|
||||
}
|
||||
|
||||
/* optional: BH RLC Channel Required to be Released List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_BHChannels_Required_ToBeReleased_List,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of BH RLC Channel Required to be Released list not implemented\n");
|
||||
|
||||
/* optional: SL DRB Required to Be Modified List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_SLDRBs_Required_ToBeModified_List,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of SL DRB Required to be modified list not implemented\n");
|
||||
|
||||
/* optional: SL DRB Required to be Released List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_SLDRBs_Required_ToBeReleased_List,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of SL DRBs Required to be released list not implemented\n");
|
||||
|
||||
/* optional: Candidate Cells To Be Cancelled List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequiredIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_Candidate_SpCell_List,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of candidate cells to be cancelled list not implemented\n");
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CU_send_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance,
|
||||
F1AP_UEContextModificationConfirm_t UEContextModificationConfirm_t) {
|
||||
AssertFatal(1==0,"Not implemented yet\n");
|
||||
int CU_send_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, f1ap_ue_context_modif_confirm_t *confirm)
|
||||
{
|
||||
F1AP_F1AP_PDU_t pdu = {0};
|
||||
pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu.choice.successfulOutcome, tmp);
|
||||
tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModificationRequired;
|
||||
tmp->criticality = F1AP_Criticality_reject;
|
||||
tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextModificationConfirm;
|
||||
F1AP_UEContextModificationConfirm_t *out = &tmp->value.choice.UEContextModificationConfirm;
|
||||
|
||||
/* mandatory: GNB_CU_UE_F1AP_ID */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationConfirmIEs_t, ie1);
|
||||
ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID;
|
||||
ie1->criticality = F1AP_Criticality_reject;
|
||||
ie1->value.present = F1AP_UEContextModificationConfirmIEs__value_PR_GNB_CU_UE_F1AP_ID;
|
||||
ie1->value.choice.GNB_CU_UE_F1AP_ID = confirm->gNB_CU_ue_id;
|
||||
|
||||
/* mandatory: GNB_DU_UE_F1AP_ID */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationConfirmIEs_t, ie2);
|
||||
ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID;
|
||||
ie2->criticality = F1AP_Criticality_reject;
|
||||
ie2->value.present = F1AP_UEContextModificationConfirmIEs__value_PR_GNB_DU_UE_F1AP_ID;
|
||||
ie2->value.choice.GNB_DU_UE_F1AP_ID = confirm->gNB_DU_ue_id;
|
||||
|
||||
/* optional: Resource Coordination Transfer Container */
|
||||
/* not implemented*/
|
||||
|
||||
/* optional: DRB Modified List */
|
||||
/* not implemented*/
|
||||
|
||||
/* optional: RRC Container */
|
||||
if (confirm->rrc_container != NULL) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationConfirmIEs_t, ie);
|
||||
ie->id = F1AP_ProtocolIE_ID_id_RRCContainer;
|
||||
ie->criticality = F1AP_Criticality_ignore;
|
||||
ie->value.present = F1AP_UEContextModificationConfirmIEs__value_PR_RRCContainer;
|
||||
OCTET_STRING_fromBuf(&ie->value.choice.RRCContainer, (const char *)confirm->rrc_container, confirm->rrc_container_length);
|
||||
}
|
||||
|
||||
/* optional: CriticalityDiagnostics */
|
||||
/* not implemented*/
|
||||
|
||||
/* optional: Execute Duplication */
|
||||
/* not implemented*/
|
||||
|
||||
/* optional: Resource Coordination Transfer Information */
|
||||
/* not implemented*/
|
||||
|
||||
/* optional: SL DRB Modified List */
|
||||
/* not implemented*/
|
||||
|
||||
/* encode */
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t len = 0;
|
||||
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
LOG_E(F1AP, "Failed to encode F1 UE Context Modification Confirm\n");
|
||||
return -1;
|
||||
}
|
||||
f1ap_itti_send_sctp_data_req(true, instance, buffer, len, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CU_send_UE_CONTEXT_MODIFICATION_REFUSE(instance_t instance, f1ap_ue_context_modif_refuse_t *refuse)
|
||||
{
|
||||
F1AP_F1AP_PDU_t pdu = {0};
|
||||
pdu.present = F1AP_F1AP_PDU_PR_unsuccessfulOutcome;
|
||||
asn1cCalloc(pdu.choice.unsuccessfulOutcome, tmp);
|
||||
tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModificationRequired;
|
||||
tmp->criticality = F1AP_Criticality_reject;
|
||||
tmp->value.present = F1AP_UnsuccessfulOutcome__value_PR_UEContextModificationRefuse;
|
||||
F1AP_UEContextModificationRefuse_t *out = &tmp->value.choice.UEContextModificationRefuse;
|
||||
|
||||
/* mandatory: GNB_CU_UE_F1AP_ID */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRefuseIEs_t, ie1);
|
||||
ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID;
|
||||
ie1->criticality = F1AP_Criticality_reject;
|
||||
ie1->value.present = F1AP_UEContextModificationRefuseIEs__value_PR_GNB_CU_UE_F1AP_ID;
|
||||
ie1->value.choice.GNB_CU_UE_F1AP_ID = refuse->gNB_CU_ue_id;
|
||||
|
||||
/* mandatory: GNB_DU_UE_F1AP_ID */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRefuseIEs_t, ie2);
|
||||
ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID;
|
||||
ie2->criticality = F1AP_Criticality_reject;
|
||||
ie2->value.present = F1AP_UEContextModificationRefuseIEs__value_PR_GNB_DU_UE_F1AP_ID;
|
||||
ie2->value.choice.GNB_DU_UE_F1AP_ID = refuse->gNB_DU_ue_id;
|
||||
|
||||
/* optional: Cause */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRefuseIEs_t, ie3);
|
||||
ie3->id = F1AP_ProtocolIE_ID_id_Cause;
|
||||
ie3->criticality = F1AP_Criticality_reject;
|
||||
ie3->value.present = F1AP_UEContextModificationRefuseIEs__value_PR_Cause;
|
||||
F1AP_Cause_t *cause = &ie3->value.choice.Cause;
|
||||
switch (refuse->cause) {
|
||||
case F1AP_CAUSE_RADIO_NETWORK:
|
||||
cause->present = F1AP_Cause_PR_radioNetwork;
|
||||
cause->choice.radioNetwork = refuse->cause_value;
|
||||
break;
|
||||
case F1AP_CAUSE_TRANSPORT:
|
||||
cause->present = F1AP_Cause_PR_transport;
|
||||
cause->choice.transport = refuse->cause_value;
|
||||
break;
|
||||
case F1AP_CAUSE_PROTOCOL:
|
||||
cause->present = F1AP_Cause_PR_protocol;
|
||||
cause->choice.protocol = refuse->cause_value;
|
||||
break;
|
||||
case F1AP_CAUSE_MISC:
|
||||
cause->present = F1AP_Cause_PR_misc;
|
||||
cause->choice.misc = refuse->cause_value;
|
||||
break;
|
||||
case F1AP_CAUSE_NOTHING:
|
||||
default:
|
||||
cause->present = F1AP_Cause_PR_NOTHING;
|
||||
break;
|
||||
} // switch
|
||||
|
||||
/* optional: CriticalityDiagnostics */
|
||||
/* not implemented*/
|
||||
|
||||
/* encode */
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t len = 0;
|
||||
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
LOG_E(F1AP, "Failed to encode F1 UE Context Modification Refuse\n");
|
||||
return -1;
|
||||
}
|
||||
f1ap_itti_send_sctp_data_req(true, instance, buffer, len, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -85,12 +85,11 @@ int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance,
|
||||
/*
|
||||
* UE Context Modification Required (gNB-DU initiated)
|
||||
*/
|
||||
int CU_handle_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
uint32_t stream,
|
||||
F1AP_F1AP_PDU_t *pdu);
|
||||
int CU_send_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance,
|
||||
F1AP_UEContextModificationConfirm_t UEContextModificationConfirm_t);
|
||||
int CU_handle_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
|
||||
|
||||
int CU_send_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, f1ap_ue_context_modif_confirm_t *confirm);
|
||||
|
||||
int CU_send_UE_CONTEXT_MODIFICATION_REFUSE(instance_t instance, f1ap_ue_context_modif_refuse_t *refuse);
|
||||
|
||||
/*
|
||||
* UE Inactivity Notification
|
||||
|
||||
@@ -169,6 +169,10 @@ void *F1AP_DU_task(void *arg) {
|
||||
DU_send_UE_CONTEXT_RELEASE_COMPLETE(myInstance, &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg));
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_MODIFICATION_REQUIRED:
|
||||
DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(myInstance, &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg));
|
||||
break;
|
||||
|
||||
case TERMINATE_MESSAGE:
|
||||
LOG_W(F1AP, " *** Exiting F1AP thread\n");
|
||||
itti_exit_task();
|
||||
|
||||
@@ -1285,12 +1285,252 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, f1ap_ue_contex
|
||||
int DU_send_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance) {
|
||||
AssertFatal(1==0,"Not implemented yet\n");
|
||||
}
|
||||
int DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance) {
|
||||
AssertFatal(1==0,"Not implemented yet\n");
|
||||
|
||||
int DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, f1ap_ue_context_modif_required_t *required)
|
||||
{
|
||||
/* 0. Message Type */
|
||||
F1AP_F1AP_PDU_t pdu = {0};
|
||||
pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage;
|
||||
asn1cCalloc(pdu.choice.initiatingMessage, tmp);
|
||||
tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModificationRequired;
|
||||
tmp->criticality = F1AP_Criticality_reject;
|
||||
tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextModificationRequired;
|
||||
F1AP_UEContextModificationRequired_t *out = &tmp->value.choice.UEContextModificationRequired;
|
||||
|
||||
/* mandatory GNB_CU_UE_F1AP_ID */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequiredIEs_t, ie1);
|
||||
ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID;
|
||||
ie1->criticality = F1AP_Criticality_reject;
|
||||
ie1->value.present = F1AP_UEContextModificationRequiredIEs__value_PR_GNB_CU_UE_F1AP_ID;
|
||||
ie1->value.choice.GNB_CU_UE_F1AP_ID = required->gNB_CU_ue_id;
|
||||
|
||||
/* mandatory: GNB_DU_UE_F1AP_ID */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequiredIEs_t, ie2);
|
||||
ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID;
|
||||
ie2->criticality = F1AP_Criticality_reject;
|
||||
ie2->value.present = F1AP_UEContextModificationRequiredIEs__value_PR_GNB_DU_UE_F1AP_ID;
|
||||
ie2->value.choice.GNB_DU_UE_F1AP_ID = required->gNB_DU_ue_id;
|
||||
|
||||
/* optional: Resource Coordination Transfer Container */
|
||||
/* not implemented!*/
|
||||
|
||||
/* optional: DU-to-CU RRC Container */
|
||||
if (required->du_to_cu_rrc_information) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequiredIEs_t, ie3);
|
||||
ie3->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation;
|
||||
ie3->criticality = F1AP_Criticality_reject;
|
||||
ie3->value.present = F1AP_UEContextModificationRequiredIEs__value_PR_DUtoCURRCInformation;
|
||||
|
||||
const du_to_cu_rrc_information_t *du2cu = required->du_to_cu_rrc_information;
|
||||
AssertFatal(du2cu->cellGroupConfig != NULL, "du2cu cellGroupConfig is mandatory!\n");
|
||||
|
||||
/* mandatorycellGroupConfig */
|
||||
OCTET_STRING_fromBuf(&ie3->value.choice.DUtoCURRCInformation.cellGroupConfig,
|
||||
(const char *)du2cu->cellGroupConfig,
|
||||
du2cu->cellGroupConfig_length);
|
||||
|
||||
/* optional: measGapConfig */
|
||||
if (du2cu->measGapConfig != NULL) {
|
||||
OCTET_STRING_fromBuf(ie3->value.choice.DUtoCURRCInformation.measGapConfig,
|
||||
(const char *)du2cu->measGapConfig,
|
||||
du2cu->measGapConfig_length);
|
||||
}
|
||||
|
||||
/* optional: requestedP_MaxFR1 */
|
||||
if (du2cu->requestedP_MaxFR1 != NULL) {
|
||||
OCTET_STRING_fromBuf(ie3->value.choice.DUtoCURRCInformation.requestedP_MaxFR1,
|
||||
(const char *)du2cu->requestedP_MaxFR1,
|
||||
du2cu->requestedP_MaxFR1_length);
|
||||
}
|
||||
}
|
||||
|
||||
/* optional: DRB required to be modified */
|
||||
/* not implemented */
|
||||
|
||||
/* optional: SRB required to be released */
|
||||
/* not implemented */
|
||||
|
||||
/* optional: DRB required to be released */
|
||||
/* not implemented */
|
||||
|
||||
/* mandatory: cause */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequiredIEs_t, ie4);
|
||||
ie4->id = F1AP_ProtocolIE_ID_id_Cause;
|
||||
ie4->criticality = F1AP_Criticality_reject;
|
||||
ie4->value.present = F1AP_UEContextModificationRequiredIEs__value_PR_Cause;
|
||||
F1AP_Cause_t *cause = &ie4->value.choice.Cause;
|
||||
switch (required->cause) {
|
||||
case F1AP_CAUSE_RADIO_NETWORK:
|
||||
cause->present = F1AP_Cause_PR_radioNetwork;
|
||||
cause->choice.radioNetwork = required->cause_value;
|
||||
break;
|
||||
case F1AP_CAUSE_TRANSPORT:
|
||||
cause->present = F1AP_Cause_PR_transport;
|
||||
cause->choice.transport = required->cause_value;
|
||||
break;
|
||||
case F1AP_CAUSE_PROTOCOL:
|
||||
cause->present = F1AP_Cause_PR_protocol;
|
||||
cause->choice.protocol = required->cause_value;
|
||||
break;
|
||||
case F1AP_CAUSE_MISC:
|
||||
cause->present = F1AP_Cause_PR_misc;
|
||||
cause->choice.misc = required->cause_value;
|
||||
break;
|
||||
case F1AP_CAUSE_NOTHING:
|
||||
default:
|
||||
cause->present = F1AP_Cause_PR_NOTHING;
|
||||
break;
|
||||
} // switch
|
||||
|
||||
/* optional: BH RLC Channel Required to be Released List */
|
||||
/* not implemented */
|
||||
|
||||
/* optional: SL DRB Required to Be Modified List */
|
||||
/* not implemented */
|
||||
|
||||
/* optional: SL DRB Required to be Released List */
|
||||
/* not implemented */
|
||||
|
||||
/* optional: Candidate Cells To Be Cancelled List */
|
||||
/* not implemented */
|
||||
|
||||
/* encode */
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t len = 0;
|
||||
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
LOG_E(F1AP, "Failed to encode F1 context release request\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
f1ap_itti_send_sctp_data_req(false, instance, buffer, len, getCxt(false, instance)->default_sctp_stream_id);
|
||||
return 0;
|
||||
}
|
||||
int DU_handle_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
uint32_t stream,
|
||||
F1AP_F1AP_PDU_t *pdu) {
|
||||
AssertFatal(1==0,"Not implemented yet\n");
|
||||
|
||||
int DU_handle_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
|
||||
{
|
||||
F1AP_UEContextModificationConfirm_t *container = &pdu->choice.successfulOutcome->value.choice.UEContextModificationConfirm;
|
||||
f1ap_ue_context_modif_confirm_t confirm = {0};
|
||||
F1AP_UEContextModificationConfirmIEs_t *ie = NULL;
|
||||
|
||||
/* mandatory: GNB_CU_UE_F1AP_ID */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true);
|
||||
confirm.gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
|
||||
/* mandatory: GNB_DU_UE_F1AP_ID */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true);
|
||||
confirm.gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
|
||||
/* optional: Resource Coordination Transfer Container */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of Resource Coordination Transfer Container not implemented\n");
|
||||
|
||||
/* optional: DRBS Modified List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_DRBs_Modified_List,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n");
|
||||
|
||||
/* optional: RRC Container */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, false);
|
||||
if (ie != NULL) {
|
||||
F1AP_RRCContainer_t *rrc_container = &ie->value.choice.RRCContainer;
|
||||
confirm.rrc_container = malloc(rrc_container->size);
|
||||
AssertFatal(confirm.rrc_container != NULL, "memory allocation failed\n");
|
||||
memcpy(confirm.rrc_container, rrc_container->buf, rrc_container->size);
|
||||
confirm.rrc_container_length = rrc_container->size;
|
||||
}
|
||||
|
||||
/* optional: Criticality Diagnostics */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_CriticalityDiagnostics,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n");
|
||||
|
||||
/* optional: Execute Duplication */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_ExecuteDuplication,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n");
|
||||
|
||||
/* optional: Resource Coordination Transfer Information */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferInformation,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n");
|
||||
|
||||
/* optional: SL DRB Modified List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationConfirmIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_SLDRBs_Modified_List,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n");
|
||||
|
||||
ue_context_modification_confirm(&confirm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DU_handle_UE_CONTEXT_MODIFICATION_REFUSE(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
|
||||
{
|
||||
F1AP_UEContextModificationRefuse_t *container = &pdu->choice.unsuccessfulOutcome->value.choice.UEContextModificationRefuse;
|
||||
f1ap_ue_context_modif_refuse_t refuse = {0};
|
||||
F1AP_UEContextModificationRefuseIEs_t *ie = NULL;
|
||||
|
||||
/* mandatory: GNB_CU_UE_F1AP_ID */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRefuseIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true);
|
||||
refuse.gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
|
||||
|
||||
/* mandatory: GNB_DU_UE_F1AP_ID */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRefuseIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true);
|
||||
refuse.gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
|
||||
|
||||
/* mandatory: Cause */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRefuseIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Cause, true);
|
||||
switch (ie->value.choice.Cause.present) {
|
||||
case F1AP_Cause_PR_radioNetwork:
|
||||
refuse.cause = F1AP_CAUSE_RADIO_NETWORK;
|
||||
refuse.cause_value = ie->value.choice.Cause.choice.radioNetwork;
|
||||
break;
|
||||
case F1AP_Cause_PR_transport:
|
||||
refuse.cause = F1AP_CAUSE_TRANSPORT;
|
||||
refuse.cause_value = ie->value.choice.Cause.choice.transport;
|
||||
break;
|
||||
case F1AP_Cause_PR_protocol:
|
||||
refuse.cause = F1AP_CAUSE_PROTOCOL;
|
||||
refuse.cause_value = ie->value.choice.Cause.choice.protocol;
|
||||
break;
|
||||
case F1AP_Cause_PR_misc:
|
||||
refuse.cause = F1AP_CAUSE_MISC;
|
||||
refuse.cause_value = ie->value.choice.Cause.choice.misc;
|
||||
break;
|
||||
default:
|
||||
LOG_W(F1AP, "Unknown cause for UE Context Modification Refuse message\n");
|
||||
/* fall through */
|
||||
case F1AP_Cause_PR_NOTHING:
|
||||
refuse.cause = F1AP_CAUSE_NOTHING;
|
||||
break;
|
||||
}
|
||||
|
||||
/* optional: Criticality Diagnostics */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRefuseIEs_t,
|
||||
ie,
|
||||
container,
|
||||
F1AP_ProtocolIE_ID_id_CriticalityDiagnostics,
|
||||
false);
|
||||
AssertFatal(ie == NULL, "handling of DRBs Modified List not implemented\n");
|
||||
|
||||
ue_context_modification_refuse(&refuse);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -79,13 +79,11 @@ int DU_send_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance);
|
||||
/*
|
||||
* UE Context Modification Required (gNB-DU initiated)
|
||||
*/
|
||||
int DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance);
|
||||
int DU_handle_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
uint32_t stream,
|
||||
F1AP_F1AP_PDU_t *pdu);
|
||||
int DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, f1ap_ue_context_modif_required_t *required);
|
||||
|
||||
int DU_send_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, f1ap_ue_context_setup_t *req);
|
||||
int DU_handle_UE_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
|
||||
|
||||
int DU_handle_UE_CONTEXT_MODIFICATION_REFUSE(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
|
||||
|
||||
/*
|
||||
* UE Inactivity Notification
|
||||
|
||||
@@ -52,7 +52,7 @@ static const f1ap_message_processing_t f1ap_messages_processing[][3] = {
|
||||
{DU_handle_UE_CONTEXT_SETUP_REQUEST, CU_handle_UE_CONTEXT_SETUP_RESPONSE, 0}, /* UEContextSetup */
|
||||
{DU_handle_UE_CONTEXT_RELEASE_COMMAND, CU_handle_UE_CONTEXT_RELEASE_COMPLETE, 0}, /* UEContextRelease */
|
||||
{DU_handle_UE_CONTEXT_MODIFICATION_REQUEST, CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE, 0}, /* UEContextModification */
|
||||
{0, 0, 0}, /* UEContextModificationRequired */
|
||||
{CU_handle_UE_CONTEXT_MODIFICATION_REQUIRED, DU_handle_UE_CONTEXT_MODIFICATION_CONFIRM, DU_handle_UE_CONTEXT_MODIFICATION_REFUSE}, /* UEContextModificationRequired */
|
||||
{0, 0, 0}, /* UEMobilityCommand */
|
||||
{CU_handle_UE_CONTEXT_RELEASE_REQUEST, 0, 0}, /* UEContextReleaseRequest */
|
||||
{CU_handle_INITIAL_UL_RRC_MESSAGE_TRANSFER, 0, 0}, /* InitialULRRCMessageTransfer */
|
||||
|
||||
@@ -4642,17 +4642,8 @@ int compute_pucch_crc_size(int O_uci)
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t compute_pucch_prb_size(uint8_t format,
|
||||
uint8_t nr_prbs,
|
||||
uint16_t O_uci,
|
||||
NR_PUCCH_MaxCodeRate_t *maxCodeRate,
|
||||
uint8_t Qm,
|
||||
uint8_t n_symb,
|
||||
uint8_t n_re_ctrl)
|
||||
float get_max_code_rate(NR_PUCCH_MaxCodeRate_t *maxCodeRate)
|
||||
{
|
||||
int O_crc = compute_pucch_crc_size(O_uci);
|
||||
int O_tot = O_uci + O_crc;
|
||||
|
||||
int rtimes100;
|
||||
switch(*maxCodeRate){
|
||||
case NR_PUCCH_MaxCodeRate_zeroDot08 :
|
||||
@@ -4680,12 +4671,46 @@ uint16_t compute_pucch_prb_size(uint8_t format,
|
||||
AssertFatal(1==0,"Invalid MaxCodeRate");
|
||||
}
|
||||
|
||||
float r = (float)rtimes100/100;
|
||||
float r = (float)rtimes100 / 100;
|
||||
return r;
|
||||
}
|
||||
|
||||
int get_f3_dmrs_symbols(NR_PUCCH_Resource_t *pucchres, NR_PUCCH_Config_t *pucch_Config)
|
||||
{
|
||||
int f3_dmrs_symbols;
|
||||
int add_dmrs_flag;
|
||||
if (pucch_Config->format3 == NULL)
|
||||
add_dmrs_flag = 0;
|
||||
else
|
||||
add_dmrs_flag = pucch_Config->format3->choice.setup->additionalDMRS ? 1 : 0;
|
||||
if (pucchres->format.choice.format3->nrofSymbols == 4)
|
||||
f3_dmrs_symbols = 1 << (pucchres->intraSlotFrequencyHopping ? 1 : 0);
|
||||
else {
|
||||
if (pucchres->format.choice.format3->nrofSymbols < 10)
|
||||
f3_dmrs_symbols = 2;
|
||||
else
|
||||
f3_dmrs_symbols = 2 << add_dmrs_flag;
|
||||
}
|
||||
return f3_dmrs_symbols;
|
||||
}
|
||||
|
||||
uint16_t compute_pucch_prb_size(uint8_t format,
|
||||
uint8_t nr_prbs,
|
||||
uint16_t O_uci,
|
||||
NR_PUCCH_MaxCodeRate_t *maxCodeRate,
|
||||
uint8_t Qm,
|
||||
uint8_t n_symb,
|
||||
uint8_t n_re_ctrl)
|
||||
{
|
||||
int O_crc = compute_pucch_crc_size(O_uci);
|
||||
int O_tot = O_uci + O_crc;
|
||||
|
||||
float r = get_max_code_rate(maxCodeRate);
|
||||
|
||||
AssertFatal(O_tot <= (nr_prbs * n_re_ctrl * n_symb * Qm * r),
|
||||
"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs",
|
||||
r,
|
||||
O_tot,
|
||||
O_uci,
|
||||
O_crc,
|
||||
nr_prbs);
|
||||
|
||||
|
||||
@@ -244,6 +244,9 @@ uint16_t compute_pucch_prb_size(uint8_t format,
|
||||
uint8_t n_symb,
|
||||
uint8_t n_re_ctrl);
|
||||
|
||||
float get_max_code_rate(NR_PUCCH_MaxCodeRate_t *maxCodeRate);
|
||||
int get_f3_dmrs_symbols(NR_PUCCH_Resource_t *pucchres, NR_PUCCH_Config_t *pucch_Config);
|
||||
|
||||
int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH);
|
||||
|
||||
void find_period_offset_SR(const NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset);
|
||||
|
||||
@@ -707,7 +707,10 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id,
|
||||
mac->si_SchedulingInfo = si_SchedulingInfo;
|
||||
mac->nr_band = *scc->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list.array[0]->freqBandIndicatorNR;
|
||||
config_common_ue_sa(mac, scc, module_id, cc_idP);
|
||||
configure_current_BWP(mac, scc, NULL);
|
||||
// configure BWP only if it is a SIB1 detection in non connected state (after sync)
|
||||
// not if it is a periodical update of SIB1 (no change of BWP in that case)
|
||||
if(mac->state < UE_CONNECTED)
|
||||
configure_current_BWP(mac, scc, NULL);
|
||||
|
||||
// Setup the SSB to Rach Occasionsif (cell_group_config->spCellConfig) { mapping according to the config
|
||||
build_ssb_to_ro_map(mac);
|
||||
|
||||
@@ -47,7 +47,7 @@ void nr_ue_init_mac(module_id_t module_idP);
|
||||
\param mac mac instance */
|
||||
void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac);
|
||||
|
||||
int8_t nr_ue_decode_mib(module_id_t module_id, int cc_id);
|
||||
void nr_ue_decode_mib(module_id_t module_id, int cc_id);
|
||||
|
||||
/**\brief decode SIB1 and other SIs pdus in NR_UE, from if_module dl_ind
|
||||
\param module_id module id
|
||||
|
||||
@@ -232,14 +232,20 @@ int get_rnti_type(NR_UE_MAC_INST_t *mac, uint16_t rnti)
|
||||
return rnti_type;
|
||||
}
|
||||
|
||||
|
||||
int8_t nr_ue_decode_mib(module_id_t module_id,
|
||||
int cc_id)
|
||||
void nr_ue_decode_mib(module_id_t module_id, int cc_id)
|
||||
{
|
||||
LOG_D(MAC,"[L2][MAC] decode mib\n");
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
if (mac->mib->cellBarred == NR_MIB__cellBarred_barred) {
|
||||
LOG_W(MAC, "Cell is barred. Going back to sync mode.\n");
|
||||
mac->synch_request.Mod_id = module_id;
|
||||
mac->synch_request.CC_id = cc_id;
|
||||
mac->synch_request.synch_req.target_Nid_cell = -1;
|
||||
mac->if_module->synch_request(&mac->synch_request);
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t frame = (mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused);
|
||||
uint16_t frame_number_4lsb = 0;
|
||||
|
||||
@@ -285,8 +291,6 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
|
||||
mac->state = UE_CONNECTED;
|
||||
else if(mac->state == UE_NOT_SYNC)
|
||||
mac->state = UE_SYNC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id,
|
||||
|
||||
@@ -2586,7 +2586,6 @@ static void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_fr
|
||||
} // if is_nr_UL_slot
|
||||
}
|
||||
|
||||
#define MAX_LCID 8 // NR_MAX_NUM_LCID shall be used but the mac_rlc_data_req function can fetch data for max 8 LCID
|
||||
typedef struct {
|
||||
uint8_t bsr_len;
|
||||
uint8_t bsr_ce_len;
|
||||
@@ -2872,7 +2871,6 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
//mac_ce_p->phr_ce_len = 0;
|
||||
//mac_ce_p->phr_header_len = 0;
|
||||
|
||||
uint8_t lcid = 0;
|
||||
uint16_t sdu_length = 0;
|
||||
uint16_t num_sdus = 0;
|
||||
mac_ce_p->sdu_length_total = 0;
|
||||
@@ -2898,8 +2896,7 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
|
||||
// Check for DCCH first
|
||||
// TO DO: Multiplex in the order defined by the logical channel prioritization
|
||||
for (lcid = UL_SCH_LCID_SRB1; lcid < MAX_LCID; lcid++) {
|
||||
|
||||
for (int lcid = UL_SCH_LCID_SRB1; lcid < NR_MAX_NUM_LCID; lcid++) {
|
||||
buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size);
|
||||
|
||||
LOG_D(NR_MAC, "In %s: [UE %d] [%d.%d] UL-DXCH -> ULSCH, RLC with LCID 0x%02x (TBS %d bytes, sdu_length_total %d bytes, MAC header len %d bytes, buflen_remain %d bytes)\n",
|
||||
|
||||
@@ -1615,192 +1615,6 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac,
|
||||
LOG_D(NR_MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci);
|
||||
}
|
||||
|
||||
static void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP,
|
||||
NR_RA_t *ra,
|
||||
nfapi_nr_dl_tti_request_t *DL_req,
|
||||
nfapi_nr_tx_data_request_t *TX_req)
|
||||
{
|
||||
gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
|
||||
|
||||
// proceed only if it is a DL slot
|
||||
if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP))
|
||||
return;
|
||||
|
||||
// UE is known by the network, C-RNTI to be used instead of TC-RNTI
|
||||
int rnti = ra->crnti;
|
||||
|
||||
NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, rnti);
|
||||
if (!UE) {
|
||||
LOG_E(NR_MAC, "Received Msg3 with C-RNTI but rnti %04x not in the table\n", rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_SearchSpace_t *ss = ra->ra_ss;
|
||||
|
||||
NR_ControlResourceSet_t *coreset = ra->coreset;
|
||||
AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg4\n");
|
||||
|
||||
// Only need to schedule DCI with and empty DL
|
||||
NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP;
|
||||
long BWPStart = 0;
|
||||
long BWPSize = 0;
|
||||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL;
|
||||
if(*ss->controlResourceSetId!=0) {
|
||||
BWPStart = dl_bwp->BWPStart;
|
||||
BWPSize = dl_bwp->BWPSize;
|
||||
} else {
|
||||
type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[ra->beam_id];
|
||||
BWPStart = type0_PDCCH_CSS_config->cset_start_rb;
|
||||
BWPSize = type0_PDCCH_CSS_config->num_rbs;
|
||||
}
|
||||
|
||||
// get CCEindex, needed also for PUCCH and then later for PDCCH
|
||||
uint8_t aggregation_level;
|
||||
int CCEIndex = get_cce_index(nr_mac,
|
||||
CC_id, slotP, 0,
|
||||
&aggregation_level,
|
||||
ss,
|
||||
coreset,
|
||||
&ra->sched_pdcch,
|
||||
true);
|
||||
|
||||
if (CCEIndex < 0) {
|
||||
LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
// Checking if the DCI allocation is feasible in current subframe
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
|
||||
if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) {
|
||||
LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t time_domain_assignment = get_dl_tda(nr_mac, scc, slotP);
|
||||
int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1;
|
||||
NR_tda_info_t tda = get_dl_tda_info(dl_bwp, ss->searchSpaceType->present, time_domain_assignment,
|
||||
scc->dmrs_TypeA_Position, mux_pattern, NR_RNTI_C, coreset->controlResourceSetId, false);
|
||||
|
||||
NR_pdsch_dmrs_t dmrs_info = get_dl_dmrs_params(scc,
|
||||
dl_bwp,
|
||||
&tda,
|
||||
1);
|
||||
|
||||
int subheader_len = sizeof(NR_MAC_SUBHEADER_SHORT);
|
||||
int pdu_length = subheader_len + 7; // 7 is contetion resolution length
|
||||
|
||||
int mcsTableIdx = dl_bwp->mcsTableIdx;
|
||||
int mcsIndex = 0;
|
||||
int rbStart = 0;
|
||||
int rbSize = 0;
|
||||
int tb_scaling = 0;
|
||||
uint32_t tb_size = 0;
|
||||
|
||||
// increase PRBs until we get to BWPSize or TBS is bigger than MAC PDU size
|
||||
do {
|
||||
if(rbSize < BWPSize)
|
||||
rbSize++;
|
||||
else
|
||||
mcsIndex++;
|
||||
LOG_D(NR_MAC,"Calling nr_compute_tbs with N_PRB_DMRS %d, N_DMRS_SLOT %d\n",dmrs_info.N_PRB_DMRS,dmrs_info.N_DMRS_SLOT);
|
||||
tb_size = nr_compute_tbs(nr_get_Qm_dl(mcsIndex, mcsTableIdx),
|
||||
nr_get_code_rate_dl(mcsIndex, mcsTableIdx),
|
||||
rbSize, tda.nrOfSymbols, dmrs_info.N_PRB_DMRS * dmrs_info.N_DMRS_SLOT, 0, tb_scaling,1) >> 3;
|
||||
} while (tb_size < pdu_length && mcsIndex<=28);
|
||||
|
||||
AssertFatal(tb_size >= pdu_length,"Cannot allocate response to MSG3 with DCCH\n");
|
||||
|
||||
int i = 0;
|
||||
uint16_t *vrb_map = cc[CC_id].vrb_map;
|
||||
while ((i < rbSize) && (rbStart + rbSize <= BWPSize)) {
|
||||
if (vrb_map[BWPStart + rbStart + i]&SL_to_bitmap(tda.startSymbolIndex, tda.nrOfSymbols)) {
|
||||
rbStart += i+1;
|
||||
i = 0;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (rbStart > (BWPSize - rbSize)) {
|
||||
LOG_E(NR_MAC, "%s(): cannot find free vrb_map for RNTI %04x!\n", __func__, rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove UE associated to TC-RNTI
|
||||
mac_remove_nr_ue(nr_mac, ra->rnti);
|
||||
|
||||
|
||||
// If the UE used MSG3 to transfer a DCCH or DTCH message, then contention resolution is successful if the UE receives a PDCCH transmission which has its CRC bits scrambled by the C-RNTI
|
||||
// Just send padding LCID
|
||||
uint8_t buf[tb_size];
|
||||
NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) &buf[0];
|
||||
padding->R = 0;
|
||||
padding->LCID = DL_SCH_LCID_PADDING;
|
||||
for(int k = 1; k < tb_size; k++)
|
||||
buf[k] = 0;
|
||||
|
||||
T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->rnti),
|
||||
T_INT(frameP), T_INT(slotP), T_INT(0), T_BUFFER(buf, tb_size));
|
||||
|
||||
// SCF222: PDU index incremented for each PDSCH PDU sent in TX control message. This is used to associate control
|
||||
// information to data and is reset every slot.
|
||||
const int pduindex = nr_mac->pdu_index[CC_id]++;
|
||||
|
||||
prepare_dl_pdus(nr_mac, ra, dl_bwp, dl_req, NULL, dmrs_info, tda, aggregation_level, CCEIndex, tb_size, 0, 0, 0,
|
||||
0, time_domain_assignment, CC_id, rnti, 0, mcsIndex, tb_scaling, pduindex, rbStart, rbSize);
|
||||
|
||||
// DL TX request
|
||||
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs];
|
||||
memcpy(tx_req->TLVs[0].value.direct, buf, sizeof(uint8_t) * tb_size);
|
||||
tx_req->PDU_length = tb_size;
|
||||
tx_req->PDU_index = pduindex;
|
||||
tx_req->num_TLV = 1;
|
||||
tx_req->TLVs[0].length = tb_size + 2;
|
||||
TX_req->SFN = frameP;
|
||||
TX_req->Number_of_PDUs++;
|
||||
TX_req->Slot = slotP;
|
||||
|
||||
// Mark the corresponding symbols and RBs as used
|
||||
fill_pdcch_vrb_map(nr_mac,
|
||||
CC_id,
|
||||
&ra->sched_pdcch,
|
||||
CCEIndex,
|
||||
aggregation_level);
|
||||
for (int rb = 0; rb < rbSize; rb++)
|
||||
vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(tda.startSymbolIndex, tda.nrOfSymbols);
|
||||
|
||||
|
||||
// If the UE used MSG3 to transfer a DCCH or DTCH message, then contention resolution is successful upon transmission of PDCCH
|
||||
LOG_A(NR_MAC, "(ue rnti 0x%04x) CBRA procedure succeeded!\n", ra->rnti);
|
||||
nr_clear_ra_proc(module_idP, CC_id, frameP, ra);
|
||||
UE->Msg4_ACKed = true;
|
||||
UE->ra_timer = 0;
|
||||
|
||||
if(!UE->CellGroup) {
|
||||
// In the specific scenario where UE correctly received MSG4 (assuming it decoded RRCsetup with CellGroup) and gNB didn't correctly received an ACK,
|
||||
// the UE would already have CG but the UE-dedicated gNB structure wouldn't (because RA didn't complete on gNB side).
|
||||
uper_decode(NULL,
|
||||
&asn_DEF_NR_CellGroupConfig, //might be added prefix later
|
||||
(void **)&UE->CellGroup,
|
||||
(uint8_t *)UE->cg_buf,
|
||||
(UE->enc_rval.encoded+7)/8, 0, 0);
|
||||
}
|
||||
|
||||
process_CellGroup(UE->CellGroup, UE);
|
||||
|
||||
// switching to initial BWP
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
configure_UE_BWP(nr_mac, scc, sched_ctrl, NULL, UE, 0, 0);
|
||||
|
||||
// Reset uplink failure flags/counters/timers at MAC so gNB will resume again scheduling resources for this UE
|
||||
nr_mac_reset_ul_failure(sched_ctrl);
|
||||
}
|
||||
|
||||
static void nr_generate_Msg4(module_id_t module_idP,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
@@ -1814,8 +1628,7 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP;
|
||||
|
||||
// if it is a DL slot, if the RA is in MSG4 state
|
||||
if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP) &&
|
||||
ra->state == Msg4) {
|
||||
if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) {
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_SearchSpace_t *ss = ra->ra_ss;
|
||||
@@ -1842,7 +1655,7 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
|
||||
if (srb_status.bytes_in_buffer == 0) {
|
||||
lcid = DL_SCH_LCID_DCCH;
|
||||
// Check for data on SRB1 (RRCReestablishment)
|
||||
// Check for data on SRB1 (RRCReestablishment, RRCReconfiguration)
|
||||
srb_status = mac_rlc_status_ind(module_idP, ra->rnti, module_idP, frameP, slotP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, 0, 0);
|
||||
}
|
||||
|
||||
@@ -1955,8 +1768,6 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_I(NR_MAC,"Generate msg4, rnti: %04x\n", ra->rnti);
|
||||
|
||||
// HARQ management
|
||||
if (current_harq_pid < 0) {
|
||||
AssertFatal(sched_ctrl->available_dl_harq.head >= 0,
|
||||
@@ -2011,7 +1822,6 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
((NR_MAC_SUBHEADER_LONG *)&buf[mac_pdu_length])->L = htons(mac_sdu_length);
|
||||
ra->mac_pdu_length = mac_pdu_length + mac_sdu_length + sizeof(NR_MAC_SUBHEADER_LONG);
|
||||
}
|
||||
LOG_I(NR_MAC,"Encoded RRCSetup Piggyback (%d + %d bytes), mac_pdu_length %d\n", mac_sdu_length, mac_subheader_len, ra->mac_pdu_length);
|
||||
memcpy(&buf[mac_pdu_length + mac_subheader_len], buffer, mac_sdu_length);
|
||||
}
|
||||
|
||||
@@ -2054,7 +1864,7 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
}
|
||||
|
||||
ra->state = WAIT_Msg4_ACK;
|
||||
LOG_D(NR_MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state);
|
||||
LOG_I(NR_MAC,"UE %04x Generate msg4: feedback at %4d.%2d, payload %d bytes, next state WAIT_Msg4_ACK\n", ra->rnti, pucch->frame, pucch->ul_slot, harq->tb_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2113,7 +1923,6 @@ void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t
|
||||
ra->timing_offset = 0;
|
||||
ra->RRC_timer = 20;
|
||||
ra->msg3_round = 0;
|
||||
ra->crnti = 0;
|
||||
if(ra->cfra == false) {
|
||||
ra->rnti = 0;
|
||||
}
|
||||
@@ -2271,7 +2080,7 @@ void nr_schedule_RA(module_id_t module_idP,
|
||||
nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req);
|
||||
break;
|
||||
case Msg3_dcch_dtch:
|
||||
nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req);
|
||||
/* fallthrough */
|
||||
case Msg4:
|
||||
nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req);
|
||||
break;
|
||||
|
||||
@@ -43,11 +43,13 @@
|
||||
#include "UTIL/OPT/opt.h"
|
||||
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
#include "F1AP_CauseRadioNetwork.h"
|
||||
|
||||
#include "RRC/NR/MESSAGES/asn1_msg.h"
|
||||
|
||||
#include "intertask_interface.h"
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
#include "F1AP_CauseRadioNetwork.h"
|
||||
|
||||
#include "T.h"
|
||||
|
||||
@@ -812,23 +814,19 @@ int nr_get_pucch_resource(NR_ControlResourceSet_t *coreset,
|
||||
}
|
||||
|
||||
// This function configures pucch pdu fapi structure
|
||||
void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||||
void nr_configure_pucch(nfapi_nr_pucch_pdu_t *pucch_pdu,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
NR_UE_info_t *UE,
|
||||
uint8_t pucch_resource,
|
||||
uint16_t O_csi,
|
||||
uint16_t O_ack,
|
||||
uint8_t O_sr,
|
||||
int r_pucch) {
|
||||
|
||||
int r_pucch)
|
||||
{
|
||||
NR_PUCCH_Resource_t *pucchres;
|
||||
NR_PUCCH_ResourceSet_t *pucchresset;
|
||||
NR_PUCCH_FormatConfig_t *pucchfmt;
|
||||
NR_PUCCH_ResourceId_t *resource_id = NULL;
|
||||
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
|
||||
|
||||
int n_list, n_set;
|
||||
uint16_t N2,N3;
|
||||
int res_found = 0;
|
||||
|
||||
pucch_pdu->bit_len_harq = O_ack;
|
||||
@@ -884,60 +882,27 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||||
pucch_pdu->cyclic_prefix = (current_BWP->cyclicprefix==NULL) ? 0 : *current_BWP->cyclicprefix;
|
||||
|
||||
NR_PUCCH_Config_t *pucch_Config = current_BWP->pucch_Config;
|
||||
if (r_pucch<0 || pucch_Config) {
|
||||
LOG_D(NR_MAC,"pucch_acknak: Filling dedicated configuration for PUCCH\n");
|
||||
if (r_pucch < 0 || pucch_Config) {
|
||||
LOG_D(NR_MAC, "pucch_acknak: Filling dedicated configuration for PUCCH\n");
|
||||
|
||||
AssertFatal(pucch_Config->resourceSetToAddModList!=NULL,
|
||||
"PUCCH resourceSetToAddModList is null\n");
|
||||
|
||||
n_set = pucch_Config->resourceSetToAddModList->list.count;
|
||||
AssertFatal(n_set>0,"PUCCH resourceSetToAddModList is empty\n");
|
||||
|
||||
LOG_D(NR_MAC, "UCI n_set= %d\n", n_set);
|
||||
|
||||
N2 = 2;
|
||||
// procedure to select pucch resource id from resource sets according to
|
||||
// number of uci bits and pucch resource indicator pucch_resource
|
||||
// ( see table 9.2.3.2 in 38.213)
|
||||
for (int i=0; i<n_set; i++) {
|
||||
pucchresset = pucch_Config->resourceSetToAddModList->list.array[i];
|
||||
n_list = pucchresset->resourceList.list.count;
|
||||
if (pucchresset->pucch_ResourceSetId == 0 && O_uci<3) {
|
||||
if (pucch_resource < n_list)
|
||||
resource_id = pucchresset->resourceList.list.array[pucch_resource];
|
||||
else
|
||||
AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci);
|
||||
}
|
||||
if (pucchresset->pucch_ResourceSetId == 1 && O_uci>2) {
|
||||
N3 = pucchresset->maxPayloadSize!= NULL ? *pucchresset->maxPayloadSize : 1706;
|
||||
if (N2<O_uci && N3>O_uci) {
|
||||
if (pucch_resource < n_list)
|
||||
resource_id = pucchresset->resourceList.list.array[pucch_resource];
|
||||
else
|
||||
AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci);
|
||||
}
|
||||
else N2 = N3;
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(resource_id!=NULL,"Couldn-t find any matching PUCCH resource in the PUCCH resource sets");
|
||||
int resource_id = get_pucch_resourceid(pucch_Config, O_uci, pucch_resource);
|
||||
|
||||
AssertFatal(pucch_Config->resourceToAddModList!=NULL,
|
||||
"PUCCH resourceToAddModList is null\n");
|
||||
|
||||
n_list = pucch_Config->resourceToAddModList->list.count;
|
||||
AssertFatal(n_list>0,"PUCCH resourceToAddModList is empty\n");
|
||||
int n_list = pucch_Config->resourceToAddModList->list.count;
|
||||
AssertFatal(n_list > 0, "PUCCH resourceToAddModList is empty\n");
|
||||
|
||||
// going through the list of PUCCH resources to find the one indexed by resource_id
|
||||
for (int i=0; i<n_list; i++) {
|
||||
for (int i = 0; i < n_list; i++) {
|
||||
pucchres = pucch_Config->resourceToAddModList->list.array[i];
|
||||
if (pucchres->pucch_ResourceId == *resource_id) {
|
||||
if (pucchres->pucch_ResourceId == resource_id) {
|
||||
res_found = 1;
|
||||
pucch_pdu->prb_start = pucchres->startingPRB;
|
||||
pucch_pdu->rnti = UE->rnti;
|
||||
// FIXME why there is only one frequency hopping flag
|
||||
// what about inter slot frequency hopping?
|
||||
pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0;
|
||||
pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping ? 1 : 0;
|
||||
pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ? *pucchres->secondHopPRB : 0;
|
||||
switch(pucchres->format.present) {
|
||||
case NR_PUCCH_Resource__format_PR_format0 :
|
||||
@@ -962,8 +927,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||||
pucch_pdu->sr_flag = O_sr;
|
||||
pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols;
|
||||
pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex;
|
||||
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
|
||||
pucch_pdu->dmrs_scrambling_id = id0!= NULL ? *id0 : *scc->physCellId;
|
||||
pucch_pdu->data_scrambling_id = pusch_id ? *pusch_id : *scc->physCellId;
|
||||
pucch_pdu->dmrs_scrambling_id = id0 ? *id0 : *scc->physCellId;
|
||||
pucch_pdu->prb_size = compute_pucch_prb_size(2,
|
||||
pucchres->format.choice.format2->nrofPRBs,
|
||||
O_uci + O_sr,
|
||||
@@ -977,25 +942,17 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||||
pucch_pdu->format_type = 3;
|
||||
pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols;
|
||||
pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex;
|
||||
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
|
||||
pucch_pdu->data_scrambling_id = pusch_id ? *pusch_id : *scc->physCellId;
|
||||
if (pucch_Config->format3 == NULL) {
|
||||
pucch_pdu->pi_2bpsk = 0;
|
||||
pucch_pdu->add_dmrs_flag = 0;
|
||||
}
|
||||
else {
|
||||
pucchfmt = pucch_Config->format3->choice.setup;
|
||||
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0;
|
||||
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0;
|
||||
}
|
||||
int f3_dmrs_symbols;
|
||||
if (pucchres->format.choice.format3->nrofSymbols==4)
|
||||
f3_dmrs_symbols = 1<<pucch_pdu->freq_hop_flag;
|
||||
else {
|
||||
if(pucchres->format.choice.format3->nrofSymbols<10)
|
||||
f3_dmrs_symbols = 2;
|
||||
else
|
||||
f3_dmrs_symbols = 2<<pucch_pdu->add_dmrs_flag;
|
||||
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK ? 1 : 0;
|
||||
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS ? 1 : 0;
|
||||
}
|
||||
int f3_dmrs_symbols = get_f3_dmrs_symbols(pucchres, pucch_Config);
|
||||
pucch_pdu->prb_size = compute_pucch_prb_size(3,
|
||||
pucchres->format.choice.format3->nrofPRBs,
|
||||
O_uci + O_sr,
|
||||
@@ -1018,8 +975,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||||
}
|
||||
else {
|
||||
pucchfmt = pucch_Config->format3->choice.setup;
|
||||
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0;
|
||||
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0;
|
||||
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK != NULL;
|
||||
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS != NULL;
|
||||
}
|
||||
pucch_pdu->bit_len_csi_part1 = O_csi;
|
||||
break;
|
||||
@@ -1028,11 +985,17 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||||
}
|
||||
}
|
||||
}
|
||||
AssertFatal(res_found==1,"No PUCCH resource found corresponding to id %ld\n",*resource_id);
|
||||
LOG_D(NR_MAC,"Configure pucch: pucch_pdu->format_type %d pucch_pdu->bit_len_harq %d, pucch->pdu->bit_len_csi %d\n",pucch_pdu->format_type,pucch_pdu->bit_len_harq,pucch_pdu->bit_len_csi_part1);
|
||||
}
|
||||
else { // this is the default PUCCH configuration, PUCCH format 0 or 1
|
||||
LOG_D(NR_MAC,"pucch_acknak: Filling default PUCCH configuration from Tables (r_pucch %d, pucch_Config %p)\n",r_pucch,pucch_Config);
|
||||
AssertFatal(res_found == 1, "No PUCCH resource found corresponding to id %d\n", resource_id);
|
||||
LOG_D(NR_MAC,
|
||||
"Configure pucch: pucch_pdu->format_type %d pucch_pdu->bit_len_harq %d, pucch->pdu->bit_len_csi %d\n",
|
||||
pucch_pdu->format_type,
|
||||
pucch_pdu->bit_len_harq,
|
||||
pucch_pdu->bit_len_csi_part1);
|
||||
} else { // this is the default PUCCH configuration, PUCCH format 0 or 1
|
||||
LOG_D(NR_MAC,
|
||||
"pucch_acknak: Filling default PUCCH configuration from Tables (r_pucch %d, pucch_Config %p)\n",
|
||||
r_pucch,
|
||||
pucch_Config);
|
||||
int rsetindex = *pucch_ConfigCommon->pucch_ResourceCommon;
|
||||
int prb_start, second_hop_prb, nr_of_symb, start_symb;
|
||||
set_r_pucch_parms(rsetindex,
|
||||
@@ -1060,7 +1023,6 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void set_r_pucch_parms(int rsetindex,
|
||||
int r_pucch,
|
||||
int bwp_size,
|
||||
@@ -2985,12 +2947,33 @@ void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ct
|
||||
* stop at 0 and we wait for a UE release command from upper layers */
|
||||
if (sched_ctrl->ul_failure_timer == 1) {
|
||||
f1_ue_data_t ue_data = du_get_f1_ue_data(rnti);
|
||||
f1ap_ue_context_release_complete_t complete = {
|
||||
f1ap_ue_context_release_req_t request = {
|
||||
.gNB_CU_ue_id = ue_data.secondary_ue,
|
||||
.gNB_DU_ue_id = rnti,
|
||||
.cause = F1AP_CAUSE_RADIO_NETWORK,
|
||||
.cause_value = 12, // F1AP_CauseRadioNetwork_rl_failure_others
|
||||
.cause_value = F1AP_CauseRadioNetwork_rl_failure_others,
|
||||
};
|
||||
nrmac->mac_rrc.ue_context_release_request(&complete);
|
||||
nrmac->mac_rrc.ue_context_release_request(&request);
|
||||
}
|
||||
}
|
||||
|
||||
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE)
|
||||
{
|
||||
DevAssert(UE->CellGroup != NULL);
|
||||
uint8_t buf[2048];
|
||||
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, UE->CellGroup, buf, sizeof(buf));
|
||||
AssertFatal(enc_rval.encoded > 0, "ASN1 encoding of CellGroupConfig failed, failed type %s\n", enc_rval.failed_type->name);
|
||||
du_to_cu_rrc_information_t du2cu = {
|
||||
.cellGroupConfig = buf,
|
||||
.cellGroupConfig_length = (enc_rval.encoded + 7) >> 3,
|
||||
};
|
||||
f1_ue_data_t ue_data = du_get_f1_ue_data(UE->rnti);
|
||||
f1ap_ue_context_modif_required_t required = {
|
||||
.gNB_CU_ue_id = ue_data.secondary_ue,
|
||||
.gNB_DU_ue_id = UE->rnti,
|
||||
.du_to_cu_rrc_information = &du2cu,
|
||||
.cause = F1AP_CAUSE_RADIO_NETWORK,
|
||||
.cause_value = F1AP_CauseRadioNetwork_action_desirable_for_radio_reasons,
|
||||
};
|
||||
nrmac->mac_rrc.ue_context_modification_required(&required);
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ void nr_csi_meas_reporting(int Mod_idP,
|
||||
const int sched_slot = (slot + ul_bwp->max_fb_time) % n_slots_frame;
|
||||
const int sched_frame = (frame + ((slot + ul_bwp->max_fb_time) / n_slots_frame)) % 1024;
|
||||
// prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
|
||||
if ((sched_frame*n_slots_frame + sched_slot - offset)%period != 0)
|
||||
if ((sched_frame * n_slots_frame + sched_slot - offset) % period != 0)
|
||||
continue;
|
||||
|
||||
AssertFatal(is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[sched_slot / 64], sched_slot), "CSI reporting slot %d is not set for an uplink slot\n", sched_slot);
|
||||
@@ -280,7 +280,14 @@ void nr_csi_meas_reporting(int Mod_idP,
|
||||
len = pucchres->format.choice.format2->nrofPRBs;
|
||||
mask = SL_to_bitmap(pucchres->format.choice.format2->startingSymbolIndex, pucchres->format.choice.format2->nrofSymbols);
|
||||
curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI;
|
||||
LOG_D(NR_MAC,"%d.%d Allocating PUCCH format 2, startPRB %d, nPRB %d, simulHARQ %d, num_bits %d\n", sched_frame, sched_slot,start,len,curr_pucch->simultaneous_harqcsi,curr_pucch->csi_bits);
|
||||
LOG_D(NR_MAC,
|
||||
"%d.%d Allocating PUCCH format 2, startPRB %d, nPRB %d, simulHARQ %d, num_bits %d\n",
|
||||
sched_frame,
|
||||
sched_slot,
|
||||
start,
|
||||
len,
|
||||
curr_pucch->simultaneous_harqcsi,
|
||||
curr_pucch->csi_bits);
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format3:
|
||||
len = pucchres->format.choice.format3->nrofPRBs;
|
||||
@@ -297,7 +304,12 @@ void nr_csi_meas_reporting(int Mod_idP,
|
||||
// verify resources are free
|
||||
for (int i = start; i < start + len; ++i) {
|
||||
if((vrb_map_UL[i+bwp_start] & mask) != 0) {
|
||||
LOG_E(NR_MAC, "%4d.%2d VRB MAP in %4d.%2d not free. Can't schedule CSI reporting on PUCCH.\n", frame, slot, sched_frame, sched_slot);
|
||||
LOG_E(NR_MAC,
|
||||
"%4d.%2d VRB MAP in %4d.%2d not free. Can't schedule CSI reporting on PUCCH.\n",
|
||||
frame,
|
||||
slot,
|
||||
sched_frame,
|
||||
sched_slot);
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
}
|
||||
else
|
||||
@@ -308,6 +320,52 @@ void nr_csi_meas_reporting(int Mod_idP,
|
||||
}
|
||||
}
|
||||
|
||||
int get_pucch_resourceid(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_resource)
|
||||
{
|
||||
NR_PUCCH_ResourceId_t *resource_id = NULL;
|
||||
AssertFatal(pucch_Config->resourceSetToAddModList != NULL, "PUCCH resourceSetToAddModList is null\n");
|
||||
|
||||
int n_set = pucch_Config->resourceSetToAddModList->list.count;
|
||||
AssertFatal(n_set > 0, "PUCCH resourceSetToAddModList is empty\n");
|
||||
|
||||
LOG_D(NR_MAC, "UCI n_set= %d\n", n_set);
|
||||
|
||||
int N2 = 2;
|
||||
// procedure to select pucch resource id from resource sets according to
|
||||
// number of uci bits and pucch resource indicator pucch_resource
|
||||
// ( see table 9.2.3.2 in 38.213)
|
||||
for (int i = 0; i < n_set; i++) {
|
||||
NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[i];
|
||||
int n_list = pucchresset->resourceList.list.count;
|
||||
if (pucchresset->pucch_ResourceSetId == 0 && O_uci < 3) {
|
||||
if (pucch_resource < n_list)
|
||||
resource_id = pucchresset->resourceList.list.array[pucch_resource];
|
||||
else
|
||||
AssertFatal(1 == 0,
|
||||
"Couldn't find pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",
|
||||
pucch_resource,
|
||||
i,
|
||||
O_uci);
|
||||
}
|
||||
if (pucchresset->pucch_ResourceSetId == 1 && O_uci > 2) {
|
||||
int N3 = pucchresset->maxPayloadSize != NULL ? *pucchresset->maxPayloadSize : 1706;
|
||||
if (N2 < O_uci && N3 > O_uci) {
|
||||
if (pucch_resource < n_list)
|
||||
resource_id = pucchresset->resourceList.list.array[pucch_resource];
|
||||
else
|
||||
AssertFatal(1 == 0,
|
||||
"Couldn't find pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",
|
||||
pucch_resource,
|
||||
i,
|
||||
O_uci);
|
||||
} else
|
||||
N2 = N3;
|
||||
}
|
||||
}
|
||||
AssertFatal(resource_id != NULL, "Couldn't find any matching PUCCH resource in the PUCCH resource sets");
|
||||
return *resource_id;
|
||||
}
|
||||
|
||||
static void handle_dl_harq(NR_UE_info_t * UE,
|
||||
int8_t harq_pid,
|
||||
bool success,
|
||||
@@ -894,7 +952,8 @@ static NR_UE_harq_t *find_harq(frame_t frame, sub_frame_t slot, NR_UE_info_t * U
|
||||
while (harq->feedback_frame != frame
|
||||
|| (harq->feedback_frame == frame && harq->feedback_slot < slot)) {
|
||||
LOG_W(NR_MAC,
|
||||
"expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the past)\n",
|
||||
"UE %04x expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the past)\n",
|
||||
UE->rnti,
|
||||
pid,
|
||||
harq->feedback_frame,
|
||||
harq->feedback_slot,
|
||||
@@ -910,7 +969,8 @@ static NR_UE_harq_t *find_harq(frame_t frame, sub_frame_t slot, NR_UE_info_t * U
|
||||
/* feedbacks that we wait for in the future: don't do anything */
|
||||
if (harq->feedback_slot > slot) {
|
||||
LOG_W(NR_MAC,
|
||||
"expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the future)\n",
|
||||
"UE %04x expected HARQ pid %d feedback at %4d.%2d, but is at %4d.%2d instead (HARQ feedback is in the future)\n",
|
||||
UE->rnti,
|
||||
pid,
|
||||
harq->feedback_frame,
|
||||
harq->feedback_slot,
|
||||
@@ -943,7 +1003,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
|
||||
const uint8_t harq_confidence = uci_01->harq->harq_confidence_level;
|
||||
NR_UE_harq_t *harq = find_harq(frame, slot, UE, nrmac->dl_bler.harq_round_max);
|
||||
if (!harq) {
|
||||
LOG_E(NR_MAC, "Oh no! Could not find a harq in %s!\n", __FUNCTION__);
|
||||
LOG_E(NR_MAC, "UE %04x: Could not find a HARQ process at %4d.%2d!\n", UE->rnti, frame, slot);
|
||||
break;
|
||||
}
|
||||
DevAssert(harq->is_waiting);
|
||||
@@ -1094,6 +1154,51 @@ static void set_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *v
|
||||
}
|
||||
}
|
||||
|
||||
bool check_bits_vs_coderate_limit(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_resource)
|
||||
{
|
||||
int resource_id = get_pucch_resourceid(pucch_Config, O_uci, pucch_resource);
|
||||
AssertFatal(pucch_Config->resourceToAddModList != NULL, "PUCCH resourceToAddModList is null\n");
|
||||
|
||||
int n_list = pucch_Config->resourceToAddModList->list.count;
|
||||
AssertFatal(n_list > 0, "PUCCH resourceToAddModList is empty\n");
|
||||
|
||||
// going through the list of PUCCH resources to find the one indexed by resource_id
|
||||
for (int i = 0; i < n_list; i++) {
|
||||
NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[i];
|
||||
if (pucchres->pucch_ResourceId == resource_id) {
|
||||
NR_PUCCH_MaxCodeRate_t *maxCodeRate = NULL;
|
||||
int nb_symbols = 0;
|
||||
int prbs = 0;
|
||||
int n_re_ctrl = 0;
|
||||
int Qm = 0;
|
||||
switch (pucchres->format.present) {
|
||||
case NR_PUCCH_Resource__format_PR_format2:
|
||||
prbs = pucchres->format.choice.format2->nrofPRBs;
|
||||
maxCodeRate = pucch_Config->format2->choice.setup->maxCodeRate;
|
||||
nb_symbols = pucchres->format.choice.format2->nrofSymbols;
|
||||
n_re_ctrl = 8;
|
||||
Qm = 2;
|
||||
break;
|
||||
case NR_PUCCH_Resource__format_PR_format3:
|
||||
prbs = pucchres->format.choice.format3->nrofPRBs;
|
||||
maxCodeRate = pucch_Config->format3->choice.setup->maxCodeRate;
|
||||
int f3_dmrs_symbols = get_f3_dmrs_symbols(pucchres, pucch_Config);
|
||||
nb_symbols = pucchres->format.choice.format3->nrofSymbols - f3_dmrs_symbols;
|
||||
n_re_ctrl = 12;
|
||||
Qm = pucch_Config->format3 ? (pucch_Config->format3->choice.setup->pi2BPSK ? 1 : 2) : 2;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "PUCCH format %d not handled\n", pucchres->format.present);
|
||||
}
|
||||
int O_crc = compute_pucch_crc_size(O_uci);
|
||||
int O_tot = O_uci + O_crc;
|
||||
float r = get_max_code_rate(maxCodeRate);
|
||||
return (O_tot <= (prbs * n_re_ctrl * nb_symbols * Qm * r));
|
||||
}
|
||||
}
|
||||
AssertFatal(false, "No PUCCH resource found\n");
|
||||
}
|
||||
|
||||
// this function returns an index to NR_sched_pucch structure
|
||||
// if the function returns -1 it was not possible to schedule acknack
|
||||
int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
@@ -1151,8 +1256,17 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
curr_pucch->dai_c == 2)
|
||||
continue;
|
||||
// if there is CSI but simultaneous HARQ+CSI is disable we can't schedule
|
||||
if(curr_pucch->csi_bits > 0 &&
|
||||
!curr_pucch->simultaneous_harqcsi)
|
||||
if (curr_pucch->csi_bits > 0 && !curr_pucch->simultaneous_harqcsi)
|
||||
continue;
|
||||
// check if the number of bits to be scheduled can fit in current PUCCH
|
||||
// according to PUCCH code rate (if not we search for another allocation)
|
||||
// the number of bits in the check need to include possible SR (1 bit)
|
||||
// and the ack/nack bit to be scheduled (1 bit)
|
||||
// so the number of bits already scheduled in current pucch + 2
|
||||
if (curr_pucch->csi_bits > 0
|
||||
&& !check_bits_vs_coderate_limit(pucch_Config,
|
||||
curr_pucch->csi_bits + curr_pucch->dai_c + 2,
|
||||
curr_pucch->resource_indicator))
|
||||
continue;
|
||||
|
||||
// otherwise we can schedule in this active PUCCH
|
||||
|
||||
@@ -223,9 +223,14 @@ static int nr_process_mac_pdu(instance_t module_idP,
|
||||
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->state >= WAIT_Msg3 && ra->rnti == UE->rnti) {
|
||||
ra->crnti = ((pduP[1]&0xFF)<<8)|(pduP[2]&0xFF);
|
||||
// remove UE context just created after Msg.3 in some milliseconds
|
||||
// as the UE is one already known (not now, as the UE context is
|
||||
// still needed for the moment)
|
||||
nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
|
||||
//mac_remove_nr_ue(RC.nrmac[module_idP], ra->rnti);
|
||||
// this UE is the one identified by the RNTI in pduP
|
||||
ra->rnti = ((pduP[1]&0xFF)<<8)|(pduP[2]&0xFF);
|
||||
ra->state = Msg3_dcch_dtch;
|
||||
LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x\n", ra->crnti);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -780,12 +785,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
|
||||
if (ra->state == Msg3_dcch_dtch) {
|
||||
// Check if the UE identified by C-RNTI still exists at the gNB
|
||||
NR_UE_info_t * UE_C = find_nr_UE(&gNB_mac->UE_info, ra->crnti);
|
||||
NR_UE_info_t * UE_C = find_nr_UE(&gNB_mac->UE_info, ra->rnti);
|
||||
if (!UE_C) {
|
||||
// The UE identified by C-RNTI no longer exists at the gNB
|
||||
// Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better solution may be implemented
|
||||
mac_remove_nr_ue(gNB_mac, ra->rnti);
|
||||
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
|
||||
LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg.3 to have UE come back with new RA attempt\n", ra->rnti);
|
||||
return;
|
||||
} else {
|
||||
// The UE identified by C-RNTI still exists at the gNB
|
||||
@@ -794,9 +800,11 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
// Reset HARQ processes
|
||||
reset_dl_harq_list(&UE_C->UE_sched_ctrl);
|
||||
reset_ul_harq_list(&UE_C->UE_sched_ctrl);
|
||||
|
||||
// Trigger RRC Reconfiguration
|
||||
LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", UE_C->rnti);
|
||||
nr_mac_trigger_reconfiguration(RC.nrmac[gnb_mod_idP], UE_C);
|
||||
}
|
||||
LOG_I(NR_MAC, "Activating scheduling response to MSG3 with DCCH/DTCCH and RNTI 0x%04x (state %d)\n",
|
||||
ra->crnti, ra->state);
|
||||
}
|
||||
else {
|
||||
LOG_I(NR_MAC, "Activating scheduling RA-Msg4 for TC_RNTI 0x%04x (state %d)\n",
|
||||
|
||||
@@ -170,6 +170,8 @@ void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr
|
||||
const NR_UE_UL_BWP_t *current_BWP,
|
||||
uint8_t *ul_ri);
|
||||
|
||||
int get_pucch_resourceid(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_resource);
|
||||
|
||||
void nr_schedule_srs(int module_id, frame_t frame, int slot);
|
||||
|
||||
void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slots_frame, nfapi_nr_dl_tti_request_t *DL_req);
|
||||
@@ -447,4 +449,6 @@ void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpac
|
||||
void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl);
|
||||
void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl);
|
||||
|
||||
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE);
|
||||
|
||||
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
#include "openair2/RRC/NR/MESSAGES/asn1_msg.h"
|
||||
#include "F1AP_CauseRadioNetwork.h"
|
||||
|
||||
#include "uper_decoder.h"
|
||||
#include "uper_encoder.h"
|
||||
@@ -243,6 +244,63 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
}
|
||||
}
|
||||
|
||||
void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm)
|
||||
{
|
||||
LOG_I(MAC, "Received UE Context Modification Confirm for UE %04x\n", confirm->gNB_DU_ue_id);
|
||||
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
NR_SCHED_LOCK(&mac->sched_lock);
|
||||
/* check first that the scheduler knows such UE */
|
||||
NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, confirm->gNB_DU_ue_id);
|
||||
if (UE == NULL) {
|
||||
LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring UE Context Modification Confirm\n", confirm->gNB_DU_ue_id);
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
return;
|
||||
}
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
|
||||
if (confirm->rrc_container_length > 0)
|
||||
nr_rlc_srb_recv_sdu(confirm->gNB_DU_ue_id, DCCH, confirm->rrc_container, confirm->rrc_container_length);
|
||||
|
||||
/* nothing else to be done? */
|
||||
}
|
||||
|
||||
void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse)
|
||||
{
|
||||
/* Currently, we only use the UE Context Modification Required procedure to
|
||||
* trigger a RRC reconfigurtion after Msg.3 with C-RNTI MAC CE. If the CU
|
||||
* refuses, it cannot do this reconfiguration, leaving the UE in an
|
||||
* unconfigured state. Therefore, we just free all RA-related info, and
|
||||
* request the release of the UE. */
|
||||
LOG_W(MAC, "Received UE Context Modification Refuse for %04x, requesting release\n", refuse->gNB_DU_ue_id);
|
||||
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
NR_SCHED_LOCK(&mac->sched_lock);
|
||||
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, refuse->gNB_DU_ue_id);
|
||||
if (UE == NULL) {
|
||||
LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring UE Context Modification Refuse\n", refuse->gNB_DU_ue_id);
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
const int CC_id = 0;
|
||||
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
|
||||
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
|
||||
NR_RA_t *ra = &cc->ra[i];
|
||||
if (ra->rnti == UE->rnti)
|
||||
nr_clear_ra_proc(0, CC_id, 0 /* frame */, ra);
|
||||
}
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
|
||||
f1ap_ue_context_release_req_t request = {
|
||||
.gNB_CU_ue_id = refuse->gNB_CU_ue_id,
|
||||
.gNB_DU_ue_id = refuse->gNB_DU_ue_id,
|
||||
.cause = F1AP_CAUSE_RADIO_NETWORK,
|
||||
.cause_value = F1AP_CauseRadioNetwork_procedure_cancelled,
|
||||
};
|
||||
mac->mac_rrc.ue_context_release_request(&request);
|
||||
}
|
||||
|
||||
void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd)
|
||||
{
|
||||
/* mark UE as to be deleted after PUSCH failure */
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
void ue_context_setup_request(const f1ap_ue_context_setup_t *req);
|
||||
void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req);
|
||||
void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm);
|
||||
void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse);
|
||||
void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd);
|
||||
|
||||
void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t* req, const f1ap_ue_context_setup_t *resp);
|
||||
typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_req_t *req,
|
||||
const f1ap_ue_context_modif_resp_t *resp);
|
||||
typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t);
|
||||
typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_release_req_t* req);
|
||||
typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete);
|
||||
|
||||
|
||||
@@ -111,6 +111,31 @@ static void ue_context_modification_response_direct(const f1ap_ue_context_modif_
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_modification_required_direct(const f1ap_ue_context_modif_required_t *required)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQUIRED);
|
||||
f1ap_ue_context_modif_required_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg);
|
||||
f1ap_msg->gNB_CU_ue_id = required->gNB_CU_ue_id;
|
||||
f1ap_msg->gNB_DU_ue_id = required->gNB_DU_ue_id;
|
||||
f1ap_msg->du_to_cu_rrc_information = NULL;
|
||||
if (required->du_to_cu_rrc_information != NULL) {
|
||||
f1ap_msg->du_to_cu_rrc_information = calloc(1, sizeof(*f1ap_msg->du_to_cu_rrc_information));
|
||||
AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n");
|
||||
du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information;
|
||||
AssertFatal(required->du_to_cu_rrc_information->cellGroupConfig != NULL && required->du_to_cu_rrc_information->cellGroupConfig_length > 0,
|
||||
"cellGroupConfig is mandatory\n");
|
||||
du2cu->cellGroupConfig_length = required->du_to_cu_rrc_information->cellGroupConfig_length;
|
||||
du2cu->cellGroupConfig = malloc(du2cu->cellGroupConfig_length * sizeof(*du2cu->cellGroupConfig));
|
||||
AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n");
|
||||
memcpy(du2cu->cellGroupConfig, required->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length);
|
||||
AssertFatal(required->du_to_cu_rrc_information->measGapConfig == NULL && required->du_to_cu_rrc_information->measGapConfig_length == 0, "not handled yet\n");
|
||||
AssertFatal(required->du_to_cu_rrc_information->requestedP_MaxFR1 == NULL && required->du_to_cu_rrc_information->requestedP_MaxFR1_length == 0, "not handled yet\n");
|
||||
}
|
||||
f1ap_msg->cause = required->cause;
|
||||
f1ap_msg->cause_value = required->cause_value;
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_release_request_direct(const f1ap_ue_context_release_req_t* req)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ);
|
||||
@@ -151,6 +176,7 @@ void mac_rrc_ul_direct_init(struct nr_mac_rrc_ul_if_s *mac_rrc)
|
||||
{
|
||||
mac_rrc->ue_context_setup_response = ue_context_setup_response_direct;
|
||||
mac_rrc->ue_context_modification_response = ue_context_modification_response_direct;
|
||||
mac_rrc->ue_context_modification_required = ue_context_modification_required_direct;
|
||||
mac_rrc->ue_context_release_request = ue_context_release_request_direct;
|
||||
mac_rrc->ue_context_release_complete = ue_context_release_complete_direct;
|
||||
mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_direct;
|
||||
|
||||
@@ -96,6 +96,31 @@ static void ue_context_modification_response_f1ap(const f1ap_ue_context_modif_re
|
||||
itti_send_msg_to_task(TASK_DU_F1, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_modification_required_f1ap(const f1ap_ue_context_modif_required_t *required)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQUIRED);
|
||||
f1ap_ue_context_modif_required_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg);
|
||||
f1ap_msg->gNB_CU_ue_id = required->gNB_CU_ue_id;
|
||||
f1ap_msg->gNB_DU_ue_id = required->gNB_DU_ue_id;
|
||||
f1ap_msg->du_to_cu_rrc_information = NULL;
|
||||
if (required->du_to_cu_rrc_information != NULL) {
|
||||
f1ap_msg->du_to_cu_rrc_information = calloc(1, sizeof(*f1ap_msg->du_to_cu_rrc_information));
|
||||
AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n");
|
||||
du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information;
|
||||
AssertFatal(required->du_to_cu_rrc_information->cellGroupConfig != NULL && required->du_to_cu_rrc_information->cellGroupConfig_length > 0,
|
||||
"cellGroupConfig is mandatory\n");
|
||||
du2cu->cellGroupConfig_length = required->du_to_cu_rrc_information->cellGroupConfig_length;
|
||||
du2cu->cellGroupConfig = malloc(du2cu->cellGroupConfig_length * sizeof(*du2cu->cellGroupConfig));
|
||||
AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n");
|
||||
memcpy(du2cu->cellGroupConfig, required->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length);
|
||||
AssertFatal(required->du_to_cu_rrc_information->measGapConfig == NULL && required->du_to_cu_rrc_information->measGapConfig_length == 0, "not handled yet\n");
|
||||
AssertFatal(required->du_to_cu_rrc_information->requestedP_MaxFR1 == NULL && required->du_to_cu_rrc_information->requestedP_MaxFR1_length == 0, "not handled yet\n");
|
||||
}
|
||||
f1ap_msg->cause = required->cause;
|
||||
f1ap_msg->cause_value = required->cause_value;
|
||||
itti_send_msg_to_task(TASK_DU_F1, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_release_request_f1ap(const f1ap_ue_context_release_req_t* req)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ);
|
||||
@@ -138,6 +163,7 @@ void mac_rrc_ul_f1ap_init(struct nr_mac_rrc_ul_if_s *mac_rrc)
|
||||
{
|
||||
mac_rrc->ue_context_setup_response = ue_context_setup_response_f1ap;
|
||||
mac_rrc->ue_context_modification_response = ue_context_modification_response_f1ap;
|
||||
mac_rrc->ue_context_modification_required = ue_context_modification_required_f1ap;
|
||||
mac_rrc->ue_context_release_request = ue_context_release_request_f1ap;
|
||||
mac_rrc->ue_context_release_complete = ue_context_release_complete_f1ap;
|
||||
mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_f1ap;
|
||||
|
||||
@@ -204,8 +204,6 @@ typedef struct {
|
||||
NR_CellGroupConfig_t *CellGroup;
|
||||
/// Preambles for contention-free access
|
||||
NR_preamble_ue_t preambles;
|
||||
/// NSA: the UEs C-RNTI to use
|
||||
rnti_t crnti;
|
||||
/// CFRA flag
|
||||
bool cfra;
|
||||
// BWP for RA
|
||||
@@ -660,6 +658,7 @@ typedef struct NR_bler_options {
|
||||
typedef struct nr_mac_rrc_ul_if_s {
|
||||
ue_context_setup_response_func_t ue_context_setup_response;
|
||||
ue_context_modification_response_func_t ue_context_modification_response;
|
||||
ue_context_modification_required_func_t ue_context_modification_required;
|
||||
ue_context_release_request_func_t ue_context_release_request;
|
||||
ue_context_release_complete_func_t ue_context_release_complete;
|
||||
initial_ul_rrc_message_transfer_func_t initial_ul_rrc_message_transfer;
|
||||
|
||||
@@ -54,15 +54,17 @@ static uint64_t nr_rlc_current_time;
|
||||
static int nr_rlc_current_time_last_frame;
|
||||
static int nr_rlc_current_time_last_subframe;
|
||||
|
||||
nr_rlc_entity_t *get_rlc_entity_from_lcid(nr_rlc_ue_t *ue,
|
||||
logical_chan_id_t channel_id)
|
||||
static nr_rlc_entity_t *get_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_id_t channel_id)
|
||||
{
|
||||
if (channel_id == 0)
|
||||
return ue->srb0;
|
||||
nr_rlc_rb_t *rb = &ue->lcid2rb[channel_id - 1];
|
||||
if (rb->type == NR_RLC_SRB)
|
||||
if (rb->type == NR_RLC_NONE)
|
||||
return NULL;
|
||||
if (rb->type == NR_RLC_SRB) {
|
||||
AssertFatal(rb->choice.srb_id > 0, "logic bug: impossible to have srb0 here\n");
|
||||
return ue->srb[rb->choice.srb_id - 1];
|
||||
else {
|
||||
} else {
|
||||
AssertFatal(rb->type == NR_RLC_DRB,
|
||||
"Invalid RB type\n");
|
||||
return ue->drb[rb->choice.drb_id - 1];
|
||||
|
||||
@@ -27,10 +27,7 @@
|
||||
|
||||
typedef void nr_rlc_ue_manager_t;
|
||||
|
||||
typedef enum nr_rlc_rb_type {
|
||||
NR_RLC_SRB = 0,
|
||||
NR_RLC_DRB = 1
|
||||
} nr_rlc_rb_type;
|
||||
typedef enum nr_rlc_rb_type { NR_RLC_NONE = 0, NR_RLC_SRB = 1, NR_RLC_DRB = 2 } nr_rlc_rb_type;
|
||||
|
||||
typedef struct nr_rlc_rb_t {
|
||||
nr_rlc_rb_type type;
|
||||
|
||||
@@ -3842,7 +3842,7 @@ void rrc_eNB_handover_ue_context_release(
|
||||
ue_context_p->ue_context.enb_gtp_ebi[e_rab] = 0;
|
||||
}
|
||||
|
||||
gtpv1u_delete_s1u_tunnel(ctxt_pP->module_id, &delete_tunnels);
|
||||
gtpv1u_delete_all_s1u_tunnel(ctxt_pP->module_id, delete_tunnels.rnti);
|
||||
struct rrc_ue_s1ap_ids_s *rrc_ue_s1ap_ids = NULL;
|
||||
rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(RC.rrc[ctxt_pP->module_id], 0, eNB_ue_s1ap_id);
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
typedef void (*ue_context_setup_request_func_t)(const f1ap_ue_context_setup_t *req);
|
||||
typedef void (*ue_context_modification_request_func_t)(const f1ap_ue_context_modif_req_t *req);
|
||||
typedef void (*ue_context_modification_confirm_func_t)(const f1ap_ue_context_modif_confirm_t *confirm);
|
||||
typedef void (*ue_context_modification_refuse_func_t)(const f1ap_ue_context_modif_refuse_t *refuse);
|
||||
typedef void (*ue_context_release_command_func_t)(const f1ap_ue_context_release_cmd_t *cmd);
|
||||
|
||||
typedef void (*dl_rrc_message_transfer_func_t)(const f1ap_dl_rrc_message_t *dl_rrc);
|
||||
|
||||
@@ -28,6 +28,8 @@ void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc)
|
||||
{
|
||||
mac_rrc->ue_context_setup_request = ue_context_setup_request;
|
||||
mac_rrc->ue_context_modification_request = ue_context_modification_request;
|
||||
mac_rrc->ue_context_modification_confirm = ue_context_modification_confirm;
|
||||
mac_rrc->ue_context_modification_refuse = ue_context_modification_refuse;
|
||||
mac_rrc->ue_context_release_command = ue_context_release_command;
|
||||
mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,31 @@ static void ue_context_modification_request_f1ap(const f1ap_ue_context_modif_req
|
||||
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_modification_confirm_f1ap(const f1ap_ue_context_modif_confirm_t *confirm)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_CONFIRM);
|
||||
f1ap_ue_context_modif_confirm_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_CONFIRM(msg);
|
||||
f1ap_msg->gNB_CU_ue_id = confirm->gNB_CU_ue_id;
|
||||
f1ap_msg->gNB_DU_ue_id = confirm->gNB_DU_ue_id;
|
||||
f1ap_msg->rrc_container = NULL;
|
||||
f1ap_msg->rrc_container_length = 0;
|
||||
if (confirm->rrc_container != NULL) {
|
||||
f1ap_msg->rrc_container = calloc(1, sizeof(*f1ap_msg->rrc_container));
|
||||
AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n");
|
||||
memcpy(f1ap_msg->rrc_container, confirm->rrc_container, confirm->rrc_container_length);
|
||||
f1ap_msg->rrc_container_length = confirm->rrc_container_length;
|
||||
}
|
||||
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_modification_refuse_f1ap(const f1ap_ue_context_modif_refuse_t *refuse)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REFUSE);
|
||||
f1ap_ue_context_modif_refuse_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REFUSE(msg);
|
||||
*f1ap_msg = *refuse;
|
||||
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_release_command_f1ap(const f1ap_ue_context_release_cmd_t *cmd)
|
||||
{
|
||||
MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_CMD);
|
||||
@@ -110,6 +135,8 @@ void mac_rrc_dl_f1ap_init(nr_mac_rrc_dl_if_t *mac_rrc)
|
||||
{
|
||||
mac_rrc->ue_context_setup_request = ue_context_setup_request_f1ap;
|
||||
mac_rrc->ue_context_modification_request = ue_context_modification_request_f1ap;
|
||||
mac_rrc->ue_context_modification_confirm = ue_context_modification_confirm_f1ap;
|
||||
mac_rrc->ue_context_modification_refuse = ue_context_modification_refuse_f1ap;
|
||||
mac_rrc->ue_context_release_command = ue_context_release_command_f1ap;
|
||||
mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer_f1ap;
|
||||
}
|
||||
|
||||
@@ -365,6 +365,8 @@ typedef struct {
|
||||
typedef struct nr_mac_rrc_dl_if_s {
|
||||
ue_context_setup_request_func_t ue_context_setup_request;
|
||||
ue_context_modification_request_func_t ue_context_modification_request;
|
||||
ue_context_modification_confirm_func_t ue_context_modification_confirm;
|
||||
ue_context_modification_refuse_func_t ue_context_modification_refuse;
|
||||
ue_context_release_command_func_t ue_context_release_command;
|
||||
dl_rrc_message_transfer_func_t dl_rrc_message_transfer;
|
||||
} nr_mac_rrc_dl_if_t;
|
||||
|
||||
+77
-34
@@ -43,7 +43,6 @@
|
||||
#include "rrc_gNB_radio_bearers.h"
|
||||
|
||||
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
|
||||
#include "LAYER2/RLC/rlc.h"
|
||||
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "COMMON/mac_rrc_primitives.h"
|
||||
@@ -68,7 +67,6 @@
|
||||
#include "uper_encoder.h"
|
||||
#include "uper_decoder.h"
|
||||
|
||||
#include "rlc.h"
|
||||
#include "platform_types.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
@@ -188,26 +186,6 @@ static void freeDRBlist(NR_DRB_ToAddModList_t *list)
|
||||
return;
|
||||
}
|
||||
|
||||
static void nr_rrc_addmod_drbs(int rnti,
|
||||
const NR_DRB_ToAddModList_t *drb_list,
|
||||
const struct NR_CellGroupConfig__rlc_BearerToAddModList *bearer_list)
|
||||
{
|
||||
if (drb_list == NULL || bearer_list == NULL)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < drb_list->list.count; i++) {
|
||||
const NR_DRB_ToAddMod_t *drb = drb_list->list.array[i];
|
||||
for (int j = 0; j < bearer_list->list.count; j++) {
|
||||
const NR_RLC_BearerConfig_t *bearer = bearer_list->list.array[j];
|
||||
if (bearer->servedRadioBearer != NULL
|
||||
&& bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity
|
||||
&& drb->drb_Identity == bearer->servedRadioBearer->choice.drb_Identity) {
|
||||
nr_rlc_add_drb(rnti, drb->drb_Identity, bearer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct deliver_dl_rrc_message_data_s {
|
||||
const gNB_RRC_INST *rrc;
|
||||
f1ap_dl_rrc_message_t *dl_rrc;
|
||||
@@ -994,14 +972,6 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co
|
||||
kUPint,
|
||||
get_softmodem_params()->sa ? ue_p->masterCellGroup->rlc_BearerToAddModList : NULL);
|
||||
|
||||
/* Refresh DRBs */
|
||||
if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) {
|
||||
LOG_D(NR_RRC,"Configuring RLC DRBs/SRBs for UE %04x\n",ue_context_pP->ue_context.rnti);
|
||||
const struct NR_CellGroupConfig__rlc_BearerToAddModList *bearer_list =
|
||||
ue_context_pP->ue_context.masterCellGroup->rlc_BearerToAddModList;
|
||||
nr_rrc_addmod_drbs(ctxt_pP->rntiMaybeUEid, DRB_configList, bearer_list);
|
||||
}
|
||||
|
||||
/* Loop through DRBs and establish if necessary */
|
||||
if (DRB_configList != NULL) {
|
||||
for (int i = 0; i < DRB_configList->list.count; i++) {
|
||||
@@ -1219,6 +1189,7 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP
|
||||
|
||||
uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id);
|
||||
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
|
||||
ue_p->xids[xid] = RRC_DEDICATED_RECONF;
|
||||
|
||||
NR_CellGroupConfig_t *masterCellGroup = ue_p->masterCellGroup;
|
||||
if (dl_bwp_id > 0) {
|
||||
@@ -1247,18 +1218,22 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP
|
||||
NULL,
|
||||
masterCellGroup);
|
||||
|
||||
nr_rrc_mac_update_cellgroup(ue_context_pP->ue_context.rnti, masterCellGroup);
|
||||
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DCCH, buffer, size);
|
||||
|
||||
if (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type)) {
|
||||
uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated
|
||||
nr_rrc_mac_update_cellgroup(ue_context_pP->ue_context.rnti, masterCellGroup);
|
||||
|
||||
uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig
|
||||
&& ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated
|
||||
&& ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList
|
||||
? NR_RRC_RECONFIGURATION_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS
|
||||
: NR_RRC_RECONFIGURATION_DELAY_MS;
|
||||
|
||||
nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, ue_p->rnti, *rrc->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, delay_ms);
|
||||
nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id,
|
||||
ue_p->rnti,
|
||||
*rrc->carrier.servingcellconfigcommon->ssbSubcarrierSpacing,
|
||||
delay_ms);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1711,6 +1686,7 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_
|
||||
rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p);
|
||||
break;
|
||||
case RRC_REESTABLISH_COMPLETE:
|
||||
case RRC_DEDICATED_RECONF:
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
@@ -2131,6 +2107,69 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i
|
||||
}
|
||||
}
|
||||
|
||||
static void rrc_CU_process_ue_modification_required(MessageDef *msg_p)
|
||||
{
|
||||
f1ap_ue_context_modif_required_t *required = &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg_p);
|
||||
protocol_ctxt_t ctxt = {.rntiMaybeUEid = required->gNB_CU_ue_id, .module_id = 0, .instance = 0, .enb_flag = 1, .eNB_index = 0};
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, required->gNB_CU_ue_id);
|
||||
if (ue_context_p == NULL) {
|
||||
LOG_E(RRC, "Could not find UE context for CU UE ID %d, cannot handle UE context modification request\n", required->gNB_CU_ue_id);
|
||||
f1ap_ue_context_modif_refuse_t refuse = {
|
||||
.gNB_CU_ue_id = required->gNB_CU_ue_id,
|
||||
.gNB_DU_ue_id = required->gNB_DU_ue_id,
|
||||
.cause = F1AP_CAUSE_RADIO_NETWORK,
|
||||
.cause_value = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_cu_ue_f1ap_id,
|
||||
};
|
||||
rrc->mac_rrc.ue_context_modification_refuse(&refuse);
|
||||
return;
|
||||
}
|
||||
|
||||
if (required->du_to_cu_rrc_information && required->du_to_cu_rrc_information->cellGroupConfig) {
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
LOG_I(RRC,
|
||||
"UE Context Modification Required: new CellGroupConfig for UE ID %d/RNTI %04x, triggering reconfiguration\n",
|
||||
UE->rrc_ue_id,
|
||||
UE->rnti);
|
||||
|
||||
NR_CellGroupConfig_t *cellGroupConfig = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
|
||||
&asn_DEF_NR_CellGroupConfig,
|
||||
(void **)&cellGroupConfig,
|
||||
(uint8_t *)required->du_to_cu_rrc_information->cellGroupConfig,
|
||||
required->du_to_cu_rrc_information->cellGroupConfig_length);
|
||||
if (dec_rval.code != RC_OK && dec_rval.consumed == 0) {
|
||||
LOG_E(RRC, "Cell group config decode error, refusing reconfiguration\n");
|
||||
f1ap_ue_context_modif_refuse_t refuse = {
|
||||
.gNB_CU_ue_id = required->gNB_CU_ue_id,
|
||||
.gNB_DU_ue_id = required->gNB_DU_ue_id,
|
||||
.cause = F1AP_CAUSE_PROTOCOL,
|
||||
.cause_value = F1AP_CauseProtocol_transfer_syntax_error,
|
||||
};
|
||||
rrc->mac_rrc.ue_context_modification_refuse(&refuse);
|
||||
return;
|
||||
}
|
||||
|
||||
if (UE->masterCellGroup) {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
|
||||
LOG_I(RRC, "UE %d/RNTI %04x replacing existing CellGroupConfig with new one received from DU\n", UE->rrc_ue_id, UE->rnti);
|
||||
}
|
||||
UE->masterCellGroup = cellGroupConfig;
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1))
|
||||
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
|
||||
|
||||
/* trigger reconfiguration */
|
||||
nr_rrc_reconfiguration_req(ue_context_p, &ctxt, 0, 0);
|
||||
//rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p);
|
||||
//rrc_gNB_generate_defaultRRCReconfiguration(&ctxt, ue_context_p);
|
||||
return;
|
||||
}
|
||||
LOG_W(RRC,
|
||||
"nothing to be done after UE Context Modification Required for UE ID %d/RNTI %04x\n",
|
||||
required->gNB_CU_ue_id,
|
||||
required->gNB_DU_ue_id);
|
||||
}
|
||||
|
||||
unsigned int mask_flip(unsigned int x) {
|
||||
return((((x>>8) + (x<<8))&0xffff)>>6);
|
||||
}
|
||||
@@ -2598,6 +2637,10 @@ void *rrc_gnb_task(void *args_p) {
|
||||
rrc_CU_process_ue_context_modification_response(msg_p, instance);
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_MODIFICATION_REQUIRED:
|
||||
rrc_CU_process_ue_modification_required(msg_p);
|
||||
break;
|
||||
|
||||
case F1AP_UE_CONTEXT_RELEASE_REQ:
|
||||
rrc_CU_process_ue_context_release_request(msg_p);
|
||||
break;
|
||||
|
||||
@@ -432,7 +432,7 @@ void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) {
|
||||
memset(&ue_context->ue_context.nsa_gtp_addrs[e_rab], 0, sizeof(ue_context->ue_context.nsa_gtp_addrs[e_rab]));
|
||||
ue_context->ue_context.nsa_gtp_ebi[e_rab] = 0;
|
||||
}
|
||||
gtpv1u_delete_s1u_tunnel(rrc->module_id, &tmp);
|
||||
gtpv1u_delete_all_s1u_tunnel(rrc->module_id, rnti);
|
||||
/* remove context */
|
||||
rrc_gNB_remove_ue_context(rrc, ue_context);
|
||||
}
|
||||
|
||||
+24
-21
@@ -431,55 +431,55 @@ bool check_si_validity(NR_UE_RRC_SI_INFO *SI_info, int si_type)
|
||||
{
|
||||
switch (si_type) {
|
||||
case NR_SIB_TypeInfo__type_sibType2:
|
||||
if (!SI_info->sib2)
|
||||
if (!SI_info->sib2 || SI_info->sib2_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType3:
|
||||
if (!SI_info->sib3)
|
||||
if (!SI_info->sib3 || SI_info->sib3_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType4:
|
||||
if (!SI_info->sib4)
|
||||
if (!SI_info->sib4 || SI_info->sib4_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType5:
|
||||
if (!SI_info->sib5)
|
||||
if (!SI_info->sib5 || SI_info->sib5_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType6:
|
||||
if (!SI_info->sib6)
|
||||
if (!SI_info->sib6 || SI_info->sib6_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType7:
|
||||
if (!SI_info->sib7)
|
||||
if (!SI_info->sib7 || SI_info->sib7_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType8:
|
||||
if (!SI_info->sib8)
|
||||
if (!SI_info->sib8 || SI_info->sib8_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType9:
|
||||
if (!SI_info->sib9)
|
||||
if (!SI_info->sib9 || SI_info->sib9_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType10_v1610:
|
||||
if (!SI_info->sib10)
|
||||
if (!SI_info->sib10 || SI_info->sib10_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType11_v1610:
|
||||
if (!SI_info->sib11)
|
||||
if (!SI_info->sib11 || SI_info->sib11_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType12_v1610:
|
||||
if (!SI_info->sib12)
|
||||
if (!SI_info->sib12 || SI_info->sib12_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType13_v1610:
|
||||
if (!SI_info->sib13)
|
||||
if (!SI_info->sib13 || SI_info->sib13_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
case NR_SIB_TypeInfo__type_sibType14_v1610:
|
||||
if (!SI_info->sib14)
|
||||
if (!SI_info->sib14 || SI_info->sib14_timer == -1)
|
||||
return false;
|
||||
break;
|
||||
default :
|
||||
@@ -490,10 +490,9 @@ bool check_si_validity(NR_UE_RRC_SI_INFO *SI_info, int si_type)
|
||||
|
||||
int check_si_status(NR_UE_RRC_SI_INFO *SI_info)
|
||||
{
|
||||
if (!get_softmodem_params()->sa)
|
||||
return 0;
|
||||
// schedule reception of SIB1 if RRC doesn't have it
|
||||
if (!SI_info->sib1)
|
||||
// or if the timer expired
|
||||
if (!SI_info->sib1 || SI_info->sib1_timer == -1)
|
||||
return 1;
|
||||
else {
|
||||
if (SI_info->sib1->si_SchedulingInfo) {
|
||||
@@ -534,9 +533,12 @@ int8_t nr_rrc_ue_decode_NR_BCCH_BCH_Message(const module_id_t module_id, const u
|
||||
NR_UE_rrc_inst[module_id].mib = bcch_message->message.choice.mib;
|
||||
bcch_message->message.choice.mib = NULL;
|
||||
|
||||
NR_UE_RRC_SI_INFO *SI_info = &NR_UE_rrc_inst[module_id].SInfo[gNB_index];
|
||||
// to schedule MAC to get SI if required
|
||||
int get_sib = check_si_status(SI_info);
|
||||
int get_sib = 0;
|
||||
if (get_softmodem_params()->sa && NR_UE_rrc_inst[module_id].mib->cellBarred == NR_MIB__cellBarred_notBarred) {
|
||||
NR_UE_RRC_SI_INFO *SI_info = &NR_UE_rrc_inst[module_id].SInfo[gNB_index];
|
||||
// to schedule MAC to get SI if required
|
||||
get_sib = check_si_status(SI_info);
|
||||
}
|
||||
nr_rrc_mac_config_req_mib(module_id, 0, NR_UE_rrc_inst[module_id].mib, get_sib);
|
||||
ret = 0;
|
||||
}
|
||||
@@ -770,8 +772,9 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(module_id_t module_id,
|
||||
if (bcch_message->message.present == NR_BCCH_DL_SCH_MessageType_PR_c1) {
|
||||
switch (bcch_message->message.choice.c1->present) {
|
||||
case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1:
|
||||
if(SI_info->sib1 != NULL)
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB1, (void *)SI_info->sib1, 1);
|
||||
LOG_D(NR_RRC, "[UE %"PRIu8"] Decoding SIB1\n", module_id);
|
||||
if(SI_info->sib1)
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SIB1, SI_info->sib1);
|
||||
NR_SIB1_t *sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1;
|
||||
SI_info->sib1 = sib1;
|
||||
if(g_log->log_component[NR_RRC].level >= OAILOG_DEBUG)
|
||||
|
||||
@@ -25,117 +25,76 @@ void nr_rrc_SI_timers(NR_UE_RRC_SI_INFO *SInfo)
|
||||
{
|
||||
// delete any stored version of a SIB after 3 hours
|
||||
// from the moment it was successfully confirmed as valid
|
||||
if (SInfo->sib1) {
|
||||
if (SInfo->sib1 && SInfo->sib1_timer >= 0) {
|
||||
SInfo->sib1_timer += 10;
|
||||
if (SInfo->sib1_timer > 10800000) {
|
||||
SInfo->sib1_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB1, SInfo->sib1, 1);
|
||||
SInfo->sib1 = NULL;
|
||||
}
|
||||
if (SInfo->sib1_timer > 10800000)
|
||||
SInfo->sib1_timer = -1;
|
||||
}
|
||||
if (SInfo->sib2) {
|
||||
if (SInfo->sib2 && SInfo->sib2_timer >= 0) {
|
||||
SInfo->sib2_timer += 10;
|
||||
if (SInfo->sib2_timer > 10800000) {
|
||||
SInfo->sib2_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB2, SInfo->sib2, 1);
|
||||
SInfo->sib2 = NULL;
|
||||
}
|
||||
if (SInfo->sib2_timer > 10800000)
|
||||
SInfo->sib2_timer = -1;
|
||||
}
|
||||
if (SInfo->sib3) {
|
||||
if (SInfo->sib3 && SInfo->sib3_timer >= 0) {
|
||||
SInfo->sib3_timer += 10;
|
||||
if (SInfo->sib3_timer > 10800000) {
|
||||
SInfo->sib3_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB3, SInfo->sib3, 1);
|
||||
SInfo->sib3 = NULL;
|
||||
}
|
||||
if (SInfo->sib3_timer > 10800000)
|
||||
SInfo->sib3_timer = -1;
|
||||
}
|
||||
if (SInfo->sib4) {
|
||||
if (SInfo->sib4 && SInfo->sib4_timer >= 0) {
|
||||
SInfo->sib4_timer += 10;
|
||||
if (SInfo->sib4_timer > 10800000) {
|
||||
SInfo->sib4_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB4, SInfo->sib4, 1);
|
||||
SInfo->sib4 = NULL;
|
||||
}
|
||||
if (SInfo->sib4_timer > 10800000)
|
||||
SInfo->sib4_timer = -1;
|
||||
}
|
||||
if (SInfo->sib5) {
|
||||
if (SInfo->sib5 && SInfo->sib5_timer >= 0) {
|
||||
SInfo->sib5_timer += 10;
|
||||
if (SInfo->sib5_timer > 10800000) {
|
||||
SInfo->sib5_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB5, SInfo->sib5, 1);
|
||||
SInfo->sib5 = NULL;
|
||||
}
|
||||
if (SInfo->sib5_timer > 10800000)
|
||||
SInfo->sib5_timer = -1;
|
||||
}
|
||||
if (SInfo->sib6) {
|
||||
if (SInfo->sib6 && SInfo->sib6_timer >= 0) {
|
||||
SInfo->sib6_timer += 10;
|
||||
if (SInfo->sib6_timer > 10800000) {
|
||||
SInfo->sib6_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB6, SInfo->sib6, 1);
|
||||
SInfo->sib6 = NULL;
|
||||
}
|
||||
if (SInfo->sib6_timer > 10800000)
|
||||
SInfo->sib6_timer = -1;
|
||||
}
|
||||
if (SInfo->sib7) {
|
||||
if (SInfo->sib7 && SInfo->sib7_timer >= 0) {
|
||||
SInfo->sib7_timer += 10;
|
||||
if (SInfo->sib7_timer > 10800000) {
|
||||
SInfo->sib7_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB7, SInfo->sib7, 1);
|
||||
SInfo->sib7 = NULL;
|
||||
}
|
||||
if (SInfo->sib7_timer > 10800000)
|
||||
SInfo->sib7_timer = -1;
|
||||
}
|
||||
if (SInfo->sib8) {
|
||||
if (SInfo->sib8 && SInfo->sib8_timer >= 0) {
|
||||
SInfo->sib8_timer += 10;
|
||||
if (SInfo->sib8_timer > 10800000) {
|
||||
SInfo->sib8_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB8, SInfo->sib8, 1);
|
||||
SInfo->sib8 = NULL;
|
||||
}
|
||||
if (SInfo->sib8_timer > 10800000)
|
||||
SInfo->sib8_timer = -1;
|
||||
}
|
||||
if (SInfo->sib9) {
|
||||
if (SInfo->sib9 && SInfo->sib9_timer >= 0) {
|
||||
SInfo->sib9_timer += 10;
|
||||
if (SInfo->sib9_timer > 10800000) {
|
||||
SInfo->sib9_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB9, SInfo->sib9, 1);
|
||||
SInfo->sib9 = NULL;
|
||||
}
|
||||
if (SInfo->sib9_timer > 10800000)
|
||||
SInfo->sib9_timer = -1;
|
||||
|
||||
}
|
||||
if (SInfo->sib10) {
|
||||
if (SInfo->sib10 && SInfo->sib10_timer >= 0) {
|
||||
SInfo->sib10_timer += 10;
|
||||
if (SInfo->sib10_timer > 10800000) {
|
||||
SInfo->sib10_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB10_r16, SInfo->sib10, 1);
|
||||
SInfo->sib10 = NULL;
|
||||
}
|
||||
if (SInfo->sib10_timer > 10800000)
|
||||
SInfo->sib10_timer = -1;
|
||||
}
|
||||
if (SInfo->sib11) {
|
||||
if (SInfo->sib11 && SInfo->sib11_timer >= 0) {
|
||||
SInfo->sib11_timer += 10;
|
||||
if (SInfo->sib11_timer > 10800000) {
|
||||
SInfo->sib11_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB11_r16, SInfo->sib11, 1);
|
||||
SInfo->sib11 = NULL;
|
||||
}
|
||||
if (SInfo->sib11_timer > 10800000)
|
||||
SInfo->sib11_timer = -1;
|
||||
}
|
||||
if (SInfo->sib12) {
|
||||
if (SInfo->sib12 && SInfo->sib12_timer >= 0) {
|
||||
SInfo->sib12_timer += 10;
|
||||
if (SInfo->sib12_timer > 10800000) {
|
||||
SInfo->sib12_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB12_r16, SInfo->sib12, 1);
|
||||
SInfo->sib12 = NULL;
|
||||
}
|
||||
if (SInfo->sib12_timer > 10800000)
|
||||
SInfo->sib12_timer = -1;
|
||||
}
|
||||
if (SInfo->sib13) {
|
||||
if (SInfo->sib13 && SInfo->sib13_timer >= 0) {
|
||||
SInfo->sib13_timer += 10;
|
||||
if (SInfo->sib13_timer > 10800000) {
|
||||
SInfo->sib13_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB13_r16, SInfo->sib13, 1);
|
||||
SInfo->sib13 = NULL;
|
||||
}
|
||||
if (SInfo->sib13_timer > 10800000)
|
||||
SInfo->sib13_timer = -1;
|
||||
}
|
||||
if (SInfo->sib14) {
|
||||
if (SInfo->sib14 && SInfo->sib14_timer >= 0) {
|
||||
SInfo->sib14_timer += 10;
|
||||
if (SInfo->sib14_timer > 10800000) {
|
||||
SInfo->sib14_timer = 0;
|
||||
SEQUENCE_free(&asn_DEF_NR_SIB14_r16, SInfo->sib14, 1);
|
||||
SInfo->sib14 = NULL;
|
||||
}
|
||||
if (SInfo->sib14_timer > 10800000)
|
||||
SInfo->sib14_timer = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -825,11 +825,47 @@ int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) {
|
||||
return !GTPNOK;
|
||||
}
|
||||
|
||||
// Legacy delete tunnel finish by deleting all the ue id
|
||||
// so the list of bearer provided is only a design bug
|
||||
int gtpv1u_delete_s1u_tunnel( const instance_t instance,
|
||||
const gtpv1u_enb_delete_tunnel_req_t *const req_pP) {
|
||||
return newGtpuDeleteAllTunnels(instance, req_pP->rnti);
|
||||
LOG_D(GTPU, "[%ld] Start delete tunnels for RNTI %x\n", instance, req_pP->rnti);
|
||||
pthread_mutex_lock(&globGtp.gtp_lock);
|
||||
auto inst = &globGtp.instances[compatInst(instance)];
|
||||
auto ptrRNTI = inst->ue2te_mapping.find(req_pP->rnti);
|
||||
if (ptrRNTI == inst->ue2te_mapping.end()) {
|
||||
LOG_W(GTPU, "[%ld] Delete Released GTP tunnels for rnti: %x, but no tunnel exits\n", instance, req_pP->rnti);
|
||||
pthread_mutex_unlock(&globGtp.gtp_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nb = 0;
|
||||
|
||||
for (int i = 0; i < req_pP->num_erab; i++) {
|
||||
auto ptr2 = ptrRNTI->second.bearers.find(req_pP->eps_bearer_id[i]);
|
||||
if (ptr2 == ptrRNTI->second.bearers.end()) {
|
||||
LOG_E(GTPU,
|
||||
"[%ld] GTP-U instance: delete of not existing tunnel RNTI:RAB: %x/%x\n",
|
||||
instance,
|
||||
req_pP->rnti,
|
||||
req_pP->eps_bearer_id[i]);
|
||||
} else {
|
||||
globGtp.te2ue_mapping.erase(ptr2->second.teid_incoming);
|
||||
nb++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptrRNTI->second.bearers.size() == 0)
|
||||
// no tunnels on this rnti, erase the ue entry
|
||||
inst->ue2te_mapping.erase(ptrRNTI);
|
||||
|
||||
pthread_mutex_unlock(&globGtp.gtp_lock);
|
||||
LOG_I(GTPU, "[%ld] Deleted released tunnels for RNTI %x (%d tunnels deleted)\n", instance, req_pP->rnti, nb);
|
||||
return !GTPNOK;
|
||||
}
|
||||
|
||||
// Legacy delete tunnel finish by deleting all the ue id
|
||||
int gtpv1u_delete_all_s1u_tunnel(const instance_t instance, const rnti_t rnti)
|
||||
{
|
||||
return newGtpuDeleteAllTunnels(instance, rnti);
|
||||
}
|
||||
|
||||
int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdusessionid_t *pdusession_id) {
|
||||
|
||||
@@ -61,6 +61,7 @@ extern "C" {
|
||||
);
|
||||
|
||||
int gtpv1u_delete_s1u_tunnel( const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP);
|
||||
int gtpv1u_delete_all_s1u_tunnel(const instance_t instance, const rnti_t rnti);
|
||||
|
||||
int gtpv1u_create_x2u_tunnel(const instance_t instanceP,
|
||||
const gtpv1u_enb_create_x2u_tunnel_req_t *const create_tunnel_req_pP,
|
||||
|
||||
Reference in New Issue
Block a user