Commit 97b08440 authored by Robert Schmidt's avatar Robert Schmidt

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
parents 464a62dd f08998af
......@@ -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
......
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)
# 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)
\ No newline at end of file
[oai web server interface home](websrv.md)
# 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)
This diff is collapsed.
......@@ -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;
......
......@@ -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();
......
......@@ -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",
......
......@@ -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;
......
......@@ -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);
}
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment