mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Compare commits
41 Commits
develop-ha
...
o1e2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e70756892 | ||
|
|
8d25885c79 | ||
|
|
53d5c9fa7f | ||
|
|
eae174b652 | ||
|
|
dc4289812f | ||
|
|
33faaed657 | ||
|
|
f3cbfe1789 | ||
|
|
585b2e0588 | ||
|
|
c5073d52fc | ||
|
|
0f1c3172f0 | ||
|
|
a9adb7f3e4 | ||
|
|
2005432a39 | ||
|
|
5ba0f11ef3 | ||
|
|
48e1468039 | ||
|
|
20b62f34a3 | ||
|
|
2413dc74bd | ||
|
|
c03e77b458 | ||
|
|
0de72f9e1f | ||
|
|
3b265e6c5c | ||
|
|
14dcc97a99 | ||
|
|
ef11cac4c6 | ||
|
|
11dd6491ee | ||
|
|
6282c26de2 | ||
|
|
c493e7994c | ||
|
|
c5da7ac9ad | ||
|
|
a08fa58ebd | ||
|
|
aa58389ff0 | ||
|
|
910e842049 | ||
|
|
c6ef9c3baf | ||
|
|
b264f4aebf | ||
|
|
dd01c029d8 | ||
|
|
8a329c03fb | ||
|
|
98cbf6c080 | ||
|
|
e1640d89b4 | ||
|
|
b5499e1412 | ||
|
|
2270cd4cfa | ||
|
|
45546102d7 | ||
|
|
2da515e51c | ||
|
|
5881077e86 | ||
|
|
e44d68287e | ||
|
|
965ed3e8d3 |
@@ -1,4 +1,4 @@
|
||||
Active_gNBs = ( "gNB-in-docker");
|
||||
Active_gNBs = ( "gNB-DU-in-docker");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
@@ -6,17 +6,32 @@ gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
gNB_name = "gNB-in-docker";
|
||||
gNB_ID = 0xe00;
|
||||
|
||||
# cell_type = "CELL_MACRO_GNB";
|
||||
|
||||
gNB_name = "gNB-DU-in-docker";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 222; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) });
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
#min_rxtxtime = 6;
|
||||
force_256qam_off = 0;
|
||||
|
||||
do_CSIRS = 0;
|
||||
do_SRS = 0;
|
||||
|
||||
pdcch_ConfigSIB1 = (
|
||||
{
|
||||
controlResourceSetZero = 12;
|
||||
searchSpaceZero = 0;
|
||||
}
|
||||
);
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
@@ -156,36 +171,35 @@ gNBs =
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "172.21.16.137";
|
||||
amf_ip_address = ( { ipv4 = "192.168.70.132";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "eth0";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.68.194";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "eth0";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.68.194";
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp3s0";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "10.0.0.2";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "enp3s0";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "10.0.0.2";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 200;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
ul_prbblack_SNR_threshold = 10;
|
||||
ulsch_max_frame_inactivity = 0;
|
||||
}
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 230; # 200; after test in lab
|
||||
pucch_TargetSNRx10 = 200;
|
||||
ulsch_max_frame_inactivity = 1;
|
||||
ul_max_mcs = 16;
|
||||
min_grant_prb = 20;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
@@ -203,11 +217,11 @@ RUs = (
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 14;
|
||||
att_rx = 14;
|
||||
att_tx = 6; # 8; after test in lab
|
||||
att_rx = 6; # 8; after test in lab
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
max_rxgain = 120;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
@@ -224,22 +238,6 @@ THREAD_STRUCT = (
|
||||
}
|
||||
);
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
@@ -250,6 +248,6 @@ log_config :
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="debug";
|
||||
f1ap_log_level ="debug";
|
||||
ngap_log_level ="info";
|
||||
f1ap_log_level ="info";
|
||||
};
|
||||
|
||||
@@ -112,6 +112,7 @@ void *config_allocate_new(configmodule_interface_t *cfg, int sz, bool autoFree)
|
||||
// add the memory piece in the managed memory pieces list
|
||||
pthread_mutex_lock(&cfg->memBlocks_mutex);
|
||||
int newBlockIdx=cfg->numptrs++;
|
||||
AssertFatal(newBlockIdx <= sizeof(cfg->oneBlock) / sizeof(cfg->oneBlock[0]), "reached maximum number of dynamically allocatable blocks\n");
|
||||
oneBlock_t* tmp=&cfg->oneBlock[newBlockIdx];
|
||||
tmp->ptrs = (char *)ptr;
|
||||
tmp->ptrsAllocated = true;
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#include "common/config/config_paramdesc.h"
|
||||
#include "common/utils/T/T.h"
|
||||
#define CONFIG_MAX_OOPT_PARAMS 10 // maximum number of parameters in the -O option (-O <cfgmode>:P1:P2...
|
||||
#define CONFIG_MAX_ALLOCATEDPTRS 2048 // maximum number of parameters that can be dynamicaly allocated in the config module
|
||||
#define CONFIG_MAX_ALLOCATEDPTRS 32768 // maximum number of parameters that can be dynamicaly allocated in the config module
|
||||
|
||||
/* default values for configuration module parameters */
|
||||
#define CONFIG_LIBCONFIGFILE "libconfig" // use libconfig file
|
||||
|
||||
@@ -411,7 +411,7 @@ frame_type_t get_frame_type(uint16_t current_band, uint8_t scs_index)
|
||||
else
|
||||
current_type = FDD;
|
||||
|
||||
LOG_I(NR_MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[current_type], delta_duplex);
|
||||
LOG_D(NR_MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[current_type], delta_duplex);
|
||||
|
||||
return current_type;
|
||||
}
|
||||
@@ -423,7 +423,7 @@ int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index)
|
||||
|
||||
int32_t delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min);
|
||||
|
||||
LOG_I(NR_MAC, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band);
|
||||
LOG_D(NR_MAC, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band);
|
||||
|
||||
return delta_duplex;
|
||||
}
|
||||
|
||||
@@ -64,8 +64,14 @@ add_library(telnetsrv_bearer MODULE telnetsrv_bearer.c)
|
||||
target_link_libraries(telnetsrv_bearer PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
add_dependencies(telnetsrv telnetsrv_bearer)
|
||||
|
||||
message(STATUS "Add CI specific telnet functions in libtelnetsrv_o1.so")
|
||||
add_library(telnetsrv_o1 MODULE telnetsrv_o1.c)
|
||||
target_link_libraries(telnetsrv_o1 PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
add_dependencies(telnetsrv telnetsrv_o1)
|
||||
|
||||
# all libraries should be written to root build dir
|
||||
set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci telnetsrv_bearer
|
||||
telnetsrv_o1
|
||||
PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../..
|
||||
)
|
||||
|
||||
|
||||
185
common/utils/telnetsrv/DOC/telneto1.md
Normal file
185
common/utils/telnetsrv/DOC/telneto1.md
Normal file
@@ -0,0 +1,185 @@
|
||||
[[_TOC_]]
|
||||
|
||||
The telnet O1 module (`telnetsrv_o1.c`) can be used to perform some O1-related
|
||||
actions (reading data, starting and stopping the nr-softmodem, reconfigurating
|
||||
frequency and bandwidth).
|
||||
|
||||
# General usage
|
||||
|
||||
The usage is similar to the general telnet usage, but in short:
|
||||
```
|
||||
./build_oai --ninja -c --gNB --nrUE --build-lib telnetsrv
|
||||
```
|
||||
to build everything including the telnet library. Then, run the nr-softmodem
|
||||
by activating telnet and loading the `o1` module:
|
||||
```
|
||||
./nr-softmodem -O <config> --telnetsrv --telnetsrv.shrmod o1
|
||||
```
|
||||
|
||||
Afterwards, it should be possible to connect via telnet on localhost, port
|
||||
9090. Use `help` to get help on the different command sections, and type e.g.
|
||||
`o1 stats` to get statistics (more information further below):
|
||||
|
||||
```
|
||||
$ telnet 127.0.0.1 9090
|
||||
Trying 127.0.0.1...
|
||||
Connected to 127.0.0.1.
|
||||
Escape character is '^]'.
|
||||
|
||||
softmodem_gnb> help
|
||||
[...]
|
||||
module 4 = o1:
|
||||
o1 stats
|
||||
o1 config ?
|
||||
o1 stop_modem
|
||||
o1 start_modem
|
||||
[...]
|
||||
softmodem_gnb> o1 stats
|
||||
[...]
|
||||
softmodem_gnb> exit
|
||||
Connection closed by foreign host.
|
||||
```
|
||||
|
||||
It also possible to send a command "directly from the command line", by piping
|
||||
the command into netcat:
|
||||
```
|
||||
echo o1 stats | nc -N 127.0.0.1 9090
|
||||
```
|
||||
|
||||
Note that only one telnet client can be connected at a time.
|
||||
|
||||
# Get statistics
|
||||
|
||||
Use the `o1 stats` command. The output is in JSON format:
|
||||
```json
|
||||
{
|
||||
"o1-config": {
|
||||
"BWP": {
|
||||
"dl": [
|
||||
{
|
||||
"bwp3gpp:isInitialBwp": true,
|
||||
"bwp3gpp:numberOfRBs": 106,
|
||||
"bwp3gpp:startRB": 0,
|
||||
"bwp3gpp:subCarrierSpacing": 30
|
||||
}
|
||||
],
|
||||
"ul": [
|
||||
{
|
||||
"bwp3gpp:isInitialBwp": true,
|
||||
"bwp3gpp:numberOfRBs": 106,
|
||||
"bwp3gpp:startRB": 0,
|
||||
"bwp3gpp:subCarrierSpacing": 30
|
||||
}
|
||||
]
|
||||
},
|
||||
"NRCELLDU": {
|
||||
"nrcelldu3gpp:ssbFrequency": 641280,
|
||||
"nrcelldu3gpp:arfcnDL": 640008,
|
||||
"nrcelldu3gpp:bSChannelBwDL": 40,
|
||||
"nrcelldu3gpp:arfcnUL": 640008,
|
||||
"nrcelldu3gpp:bSChannelBwUL": 40,
|
||||
"nrcelldu3gpp:nRPCI": 0,
|
||||
"nrcelldu3gpp:nRTAC": 1,
|
||||
"nrcelldu3gpp:mcc": "208",
|
||||
"nrcelldu3gpp:mnc": "95",
|
||||
"nrcelldu3gpp:sd": 16777215,
|
||||
"nrcelldu3gpp:sst": 1
|
||||
},
|
||||
"device": {
|
||||
"gnbId": 1,
|
||||
"gnbName": "gNB-Eurecom-5GNRBox",
|
||||
"vendor": "OpenAirInterface"
|
||||
}
|
||||
},
|
||||
"O1-Operational": {
|
||||
"frame-type": "tdd",
|
||||
"band-number": 78,
|
||||
"num-ues": 1,
|
||||
"ues": [
|
||||
6876
|
||||
],
|
||||
"load": 9,
|
||||
"ues-thp": [
|
||||
{
|
||||
"rnti": 6876,
|
||||
"dl": 3279,
|
||||
"ul": 2725
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that no actual JSON engine is used, so no actual verification is done; it
|
||||
is for convenience of the consumer. To verify, you can employ `jq`:
|
||||
```
|
||||
echo o1 stats | nc -N 127.0.0.1 9090 | awk '/^{$/, /^}$/' | jq .
|
||||
```
|
||||
(`awk`'s pattern matching makes that only everything between the first `{` and
|
||||
its corresponding `}` is printed).
|
||||
|
||||
There are two sections:
|
||||
1. `.o1-config` show some stats that map directly to the O1 Netconf model. Note
|
||||
that only one MCC/MNC/SD/SST (each) are supported right now. Also, note that
|
||||
as per 3GPP specifications, SD of value `0xffffff` (16777215 in decimal)
|
||||
means "no SD". `bSChannelBwDL/UL` is reported in MHz.
|
||||
2. `.O1-operational` output some statistics that do not map yet to any netconf
|
||||
parameters, but that might be useful nevertheless for a consumer.
|
||||
|
||||
# Write a new configuration
|
||||
|
||||
Use `o1 config` to write a configuration:
|
||||
```
|
||||
echo o1 config nrcelldu3gpp:ssbFrequency 620736 nrcelldu3gpp:arfcnDL 620020 nrcelldu3gpp:bSChannelBwDL 51 bwp3gpp:numberOfRBs 51 bwp3gpp:startRB 0 | nc -N 127.0.0.1 9090
|
||||
```
|
||||
You have to pass the above parameters in exactly this order. The softmodem
|
||||
needs to be stopped; it will pick up the new configuration when starting the
|
||||
softmodem again.
|
||||
|
||||
Note that you cannot switch three-quarter sampling for this as of now.
|
||||
|
||||
For values of the configuration, refer to the next section.
|
||||
|
||||
# Use hardcoded configuration
|
||||
|
||||
Use `o1 bwconfig` to write a hard-coded configuration for 20 or 40 MHz cells:
|
||||
```
|
||||
echo o1 bwconfig 20 | nc -N 127.0.0.1 9090
|
||||
echo o1 bwconfig 40 | nc -N 127.0.0.1 9090
|
||||
```
|
||||
|
||||
The softmodem needs to be stopped; it will pick up the new configuration when
|
||||
starting the softmodem again.
|
||||
|
||||
Use `o1 stats` to see which configurations are set by these commands for the
|
||||
parameters `nrcelldu3gpp:ssbFrequency`, `nrcelldu3gpp:arfcnDL`,
|
||||
`nrcelldu3gpp:arfcnUL`, `nrcelldu3gpp:bSChannelBwDL`,
|
||||
`nrcelldu3gpp:bSChannelBwUL`, and `bwp3gpp:numberOfRBsbwp3gpp:startRB`.
|
||||
Furthermore, for 20MHz, it *disables* three-quarter sampling, whereas it
|
||||
*enables* three-quarter sampling for 40MHz.
|
||||
|
||||
# Restart the softmodem
|
||||
|
||||
Use `o1 stop_modem` to stop the `nr-softmodem`. To restart the softmodem, use
|
||||
`o1 start_modem`:
|
||||
```
|
||||
echo o1 stop_modem | nc -N 127.0.0.1 9090
|
||||
echo o1 start_modem | nc -N 127.0.0.1 9090
|
||||
```
|
||||
|
||||
In fact, stopping terminates all L1 threads and, due to implementation details,
|
||||
the RRC thread. It will be as if the softmodem "freezes", and no periodical
|
||||
output of statistics will occur (the O1 telnet interface will still work,
|
||||
though). Starting again will "defreeze" the softmodem.
|
||||
|
||||
`stop_modem` works reliably at this point. `start_modem` comes with a couple of
|
||||
caveats:
|
||||
* not all memory is freed properly: for instance, the configuration module runs
|
||||
out of memory after a couple of restarts, and will stop everything.
|
||||
* it is advisable to disconnect any UE before stopping. The MAC runs in the
|
||||
same thread as the L1, and since we stop the L1, it is as if the MAC
|
||||
"freezes" in time. When you restart the softmodem, frame and slot numbers
|
||||
might not match with data stored internally at the MAC, and the softmodem
|
||||
might assert. Alse, any UE will be disconnected (USRP: no radio, RFsimulator:
|
||||
TCP socket closed); this in itself is not a problem from a gNB perspective,
|
||||
but of course the UE is not immediately operational after restarting.
|
||||
@@ -3,5 +3,6 @@ The oai embedded telnet server is an optional monitoring and debugging tool. It
|
||||
* [Using the telnet server](telnetusage.md)
|
||||
* [Adding commands to the oai telnet server](telnetaddcmd.md)
|
||||
* [telnet server architecture ](telnetarch.md)
|
||||
* [on the telnet O1 module](telneto1.md)
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -681,7 +681,6 @@ void run_telnetsrv(void) {
|
||||
}
|
||||
|
||||
if(!readc) {
|
||||
printf ("[TELNETSRV] Telnet Client disconnected.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -727,7 +726,7 @@ void run_telnetsrv(void) {
|
||||
write_history(telnetparams.histfile);
|
||||
clear_history();
|
||||
close(telnetparams.new_socket);
|
||||
printf ("[TELNETSRV] Telnet server waitting for connection...\n");
|
||||
//printf ("[TELNETSRV] Telnet server waitting for connection...\n");
|
||||
}
|
||||
|
||||
close(sock);
|
||||
|
||||
@@ -56,7 +56,7 @@ int get_single_rnti(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//void rrc_gNB_trigger_new_bearer(int rnti);
|
||||
void rrc_gNB_trigger_new_bearer(int rnti);
|
||||
int add_bearer(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
int rnti = -1;
|
||||
@@ -75,13 +75,12 @@ int add_bearer(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
if (!rrcue)
|
||||
ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti);
|
||||
|
||||
AssertFatal(false, "not implemented\n");
|
||||
//rrc_gNB_trigger_new_bearer(rnti);
|
||||
rrc_gNB_trigger_new_bearer(rnti);
|
||||
prnt("called rrc_gNB_trigger_new_bearer(%04x)\n", rnti);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//void rrc_gNB_trigger_release_bearer(int rnti);
|
||||
void rrc_gNB_trigger_release_bearer(int rnti);
|
||||
int release_bearer(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
int rnti = -1;
|
||||
@@ -100,8 +99,7 @@ int release_bearer(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
if (!rrcue)
|
||||
ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti);
|
||||
|
||||
AssertFatal(false, "not implemented\n");
|
||||
//rrc_gNB_trigger_release_bearer(rnti);
|
||||
rrc_gNB_trigger_release_bearer(rnti);
|
||||
prnt("called rrc_gNB_trigger_release_bearer(%04x)\n", rnti);
|
||||
return 0;
|
||||
}
|
||||
|
||||
447
common/utils/telnetsrv/telnetsrv_o1.c
Normal file
447
common/utils/telnetsrv/telnetsrv_o1.c
Normal file
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define TELNETSERVERCODE
|
||||
#include "telnetsrv.h"
|
||||
|
||||
#include "openair2/RRC/NR/nr_rrc_defs.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "openair2/RRC/NR/nr_rrc_config.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
|
||||
#define ERROR_MSG_RET(mSG, aRGS...) do { prnt("FAILURE: " mSG, ##aRGS); return 1; } while (0)
|
||||
|
||||
#define ISINITBWP "bwp3gpp:isInitialBwp"
|
||||
//#define CYCLPREF "bwp3gpp:cyclicPrefix"
|
||||
#define NUMRBS "bwp3gpp:numberOfRBs"
|
||||
#define STARTRB "bwp3gpp:startRB"
|
||||
#define BWPSCS "bwp3gpp:subCarrierSpacing"
|
||||
|
||||
#define SSBFREQ "nrcelldu3gpp:ssbFrequency"
|
||||
#define ARFCNDL "nrcelldu3gpp:arfcnDL"
|
||||
#define BWDL "nrcelldu3gpp:bSChannelBwDL"
|
||||
#define ARFCNUL "nrcelldu3gpp:arfcnUL"
|
||||
#define BWUL "nrcelldu3gpp:bSChannelBwUL"
|
||||
#define PCI "nrcelldu3gpp:nRPCI"
|
||||
#define TAC "nrcelldu3gpp:nRTAC"
|
||||
#define MCC "nrcelldu3gpp:mcc"
|
||||
#define MNC "nrcelldu3gpp:mnc"
|
||||
#define SD "nrcelldu3gpp:sd"
|
||||
#define SST "nrcelldu3gpp:sst"
|
||||
|
||||
typedef struct b {
|
||||
long int dl;
|
||||
long int ul;
|
||||
} b_t;
|
||||
|
||||
static int get_stats(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
if (buf)
|
||||
ERROR_MSG_RET("no parameter allowed\n");
|
||||
|
||||
const gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
AssertFatal(mac != NULL, "need MAC\n");
|
||||
|
||||
const f1ap_setup_req_t *sr = mac->f1_config.setup_req;
|
||||
const f1ap_served_cell_info_t *cell_info = &sr->cell[0].info;
|
||||
|
||||
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
const NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
|
||||
const NR_FrequencyInfoUL_t *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL;
|
||||
frame_type_t frame_type = get_frame_type(*frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
|
||||
const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
|
||||
const NR_BWP_t *initialUL = &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
|
||||
|
||||
int scs = initialDL->subcarrierSpacing;
|
||||
AssertFatal(scs == initialUL->subcarrierSpacing, "different SCS for UL/DL not supported!\n");
|
||||
int band = *frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
int nrb = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
|
||||
AssertFatal(nrb == frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth, "different BW for UL/DL not supported!\n");
|
||||
int bw_index = get_supported_band_index(scs, band, nrb);
|
||||
int bw_mhz = get_supported_bw_mhz(band > 256 ? FR2 : FR1, bw_index);
|
||||
|
||||
int num_ues = 0;
|
||||
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
|
||||
num_ues++;
|
||||
}
|
||||
|
||||
const mac_stats_t *stat = &mac->mac_stats;
|
||||
static mac_stats_t last = {0};
|
||||
int diff_used = stat->used_prb_aggregate - last.used_prb_aggregate;
|
||||
int diff_total = stat->total_prb_aggregate - last.total_prb_aggregate;
|
||||
int load = diff_total > 0 ? 100 * diff_used / diff_total : 0;
|
||||
last = *stat;
|
||||
|
||||
static struct timespec tp_last = {0};
|
||||
struct timespec tp_now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp_now);
|
||||
size_t diff_msec = (tp_now.tv_sec - tp_last.tv_sec) * 1000 + (tp_now.tv_nsec - tp_last.tv_nsec) / 1000000;
|
||||
tp_last = tp_now;
|
||||
|
||||
const int srb_flag = 0;
|
||||
const int rb_id = 1;
|
||||
static b_t last_total[MAX_MOBILES_PER_GNB] = {0};
|
||||
b_t thr[MAX_MOBILES_PER_GNB] = {0};
|
||||
int i = 0;
|
||||
{
|
||||
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
|
||||
nr_rlc_statistics_t rlc = {0};
|
||||
nr_rlc_get_statistics(it->rnti, srb_flag, rb_id, &rlc);
|
||||
// static var last_total: we might have old data, larger than what
|
||||
// reports RLC, leading to a huge number -> cut off to zero
|
||||
if (last_total[i].dl > rlc.txpdu_bytes)
|
||||
last_total[i].dl = rlc.txpdu_bytes;
|
||||
if (last_total[i].ul > rlc.rxpdu_bytes)
|
||||
last_total[i].ul = rlc.rxpdu_bytes;
|
||||
thr[i].dl = (rlc.txpdu_bytes - last_total[i].dl) * 8 / diff_msec;
|
||||
thr[i].ul = (rlc.rxpdu_bytes - last_total[i].ul) * 8 / diff_msec;
|
||||
last_total[i].dl = rlc.txpdu_bytes;
|
||||
last_total[i].ul = rlc.rxpdu_bytes;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
prnt("{\n");
|
||||
prnt(" \"o1-config\": {\n");
|
||||
|
||||
prnt(" \"BWP\": {\n");
|
||||
prnt(" \"dl\": [{\n");
|
||||
prnt(" \"" ISINITBWP "\": true,\n");
|
||||
//prnt(" \"" CYCLPREF "\": %ld,\n", *initialDL->cyclicPrefix);
|
||||
prnt(" \"" NUMRBS "\": %ld,\n", NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE));
|
||||
prnt(" \"" STARTRB "\": %ld,\n", NRRIV2PRBOFFSET(initialDL->locationAndBandwidth, MAX_BWP_SIZE));
|
||||
prnt(" \"" BWPSCS "\": %ld\n", 15 * (1U << scs));
|
||||
prnt(" }],\n");
|
||||
prnt(" \"ul\": [{\n");
|
||||
prnt(" \"" ISINITBWP "\": true,\n");
|
||||
//prnt(" \"" CYCLPREF "\": %ld,\n", *initialUL->cyclicPrefix);
|
||||
prnt(" \"" NUMRBS "\": %ld,\n", NRRIV2BW(initialUL->locationAndBandwidth, MAX_BWP_SIZE));
|
||||
prnt(" \"" STARTRB "\": %ld,\n", NRRIV2PRBOFFSET(initialUL->locationAndBandwidth, MAX_BWP_SIZE));
|
||||
prnt(" \"" BWPSCS "\": %ld\n", 15 * (1U << scs));
|
||||
prnt(" }]\n");
|
||||
prnt(" },\n");
|
||||
|
||||
prnt(" \"NRCELLDU\": {\n");
|
||||
prnt(" \"" SSBFREQ "\": %ld,\n", *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB);
|
||||
prnt(" \"" ARFCNDL "\": %ld,\n", frequencyInfoDL->absoluteFrequencyPointA);
|
||||
prnt(" \"" BWDL "\": %ld,\n", bw_mhz);
|
||||
prnt(" \"" ARFCNUL "\": %ld,\n", frequencyInfoUL->absoluteFrequencyPointA ? *frequencyInfoUL->absoluteFrequencyPointA : frequencyInfoDL->absoluteFrequencyPointA);
|
||||
prnt(" \"" BWUL "\": %ld,\n", bw_mhz);
|
||||
prnt(" \"" PCI "\": %ld,\n", *scc->physCellId);
|
||||
prnt(" \"" TAC "\": %ld,\n", *cell_info->tac);
|
||||
prnt(" \"" MCC "\": \"%03d\",\n", cell_info->plmn.mcc);
|
||||
prnt(" \"" MNC "\": \"%0*d\",\n", cell_info->plmn.mnc_digit_length, cell_info->plmn.mnc);
|
||||
prnt(" \"" SD "\": %d,\n", cell_info->sd);
|
||||
prnt(" \"" SST "\": %d\n", cell_info->sst);
|
||||
prnt(" },\n");
|
||||
prnt(" \"device\": {\n");
|
||||
prnt(" \"gnbId\": %d,\n", sr->gNB_DU_id);
|
||||
prnt(" \"gnbName\": \"%s\",\n", sr->gNB_DU_name);
|
||||
prnt(" \"vendor\": \"OpenAirInterface\"\n");
|
||||
prnt(" }\n");
|
||||
prnt(" },\n");
|
||||
|
||||
prnt(" \"O1-Operational\": {\n");
|
||||
prnt(" \"frame-type\": \"%s\",\n", frame_type == TDD ? "tdd" : "fdd");
|
||||
prnt(" \"band-number\": %ld,\n", band);
|
||||
prnt(" \"num-ues\": %d,\n", num_ues);
|
||||
prnt(" \"ues\": [");
|
||||
{
|
||||
bool first = true;
|
||||
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
|
||||
if (!first) { prnt(", "); }
|
||||
prnt("%d", it->rnti);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
prnt(" ],\n");
|
||||
prnt(" \"load\": %d,\n", load);
|
||||
prnt(" \"ues-thp\": [\n");
|
||||
{
|
||||
bool first = true;
|
||||
int i = 0;
|
||||
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
|
||||
if (!first) { prnt(", "); }
|
||||
prnt(" {\"rnti\": %d, \"dl\": %ld, \"ul\": %ld}\n", it->rnti, thr[i].dl, thr[i].ul);
|
||||
i++;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
prnt(" ]\n");
|
||||
prnt(" }\n");
|
||||
prnt("}\n");
|
||||
prnt("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_long(const char *buf, const char *end, const char *id, long *val)
|
||||
{
|
||||
const char *curr = buf;
|
||||
while (isspace(*curr) && curr < end) // skip leading spaces
|
||||
curr++;
|
||||
int len = strlen(id);
|
||||
if (curr + len >= end)
|
||||
return -1;
|
||||
if (strncmp(curr, id, len) != 0) // check buf has id
|
||||
return -1;
|
||||
curr += len;
|
||||
while (isspace(*curr) && curr < end) // skip middle spaces
|
||||
curr++;
|
||||
if (curr >= end)
|
||||
return -1;
|
||||
int nread = sscanf(curr, "%ld", val);
|
||||
if (nread != 1)
|
||||
return -1;
|
||||
while (isdigit(*curr) && curr < end) // skip all digits read above
|
||||
curr++;
|
||||
if (curr > end)
|
||||
return -1;
|
||||
return curr - buf;
|
||||
}
|
||||
|
||||
bool running = true; // in the beginning, the softmodem is started automatically
|
||||
static int set_config(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
if (!buf)
|
||||
ERROR_MSG_RET("need param: o1 config param1 val1 [param2 val2 ...]\n");
|
||||
if (running)
|
||||
ERROR_MSG_RET("cannot set parameters while L1 is running\n");
|
||||
const char *end = buf + strlen(buf);
|
||||
|
||||
/* we need to update the following fields to change frequency and/or
|
||||
* bandwidth:
|
||||
* --gNBs.[0].servingCellConfigCommon.[0].absoluteFrequencySSB 620736 -> SSBFREQ
|
||||
* --gNBs.[0].servingCellConfigCommon.[0].dl_absoluteFrequencyPointA 620020 -> ARFCNDL
|
||||
* --gNBs.[0].servingCellConfigCommon.[0].dl_carrierBandwidth 51 -> BWDL
|
||||
* --gNBs.[0].servingCellConfigCommon.[0].initialDLBWPlocationAndBandwidth 13750 -> NUMRBS + STARTRB
|
||||
* --gNBs.[0].servingCellConfigCommon.[0].ul_carrierBandwidth 51 -> BWUL?
|
||||
* --gNBs.[0].servingCellConfigCommon.[0].initialULBWPlocationAndBandwidth 13750 -> ?
|
||||
*/
|
||||
|
||||
int processed = 0;
|
||||
int pos = 0;
|
||||
|
||||
long ssbfreq;
|
||||
processed = read_long(buf + pos, end, SSBFREQ, &ssbfreq);
|
||||
if (processed < 0)
|
||||
ERROR_MSG_RET("could not read " SSBFREQ " at index %d\n", pos + processed);
|
||||
pos += processed;
|
||||
prnt("setting " SSBFREQ ": %ld [len %d]\n", ssbfreq, pos);
|
||||
|
||||
long arfcn;
|
||||
processed = read_long(buf + pos, end, ARFCNDL, &arfcn);
|
||||
if (processed < 0)
|
||||
ERROR_MSG_RET("could not read " ARFCNDL " at index %d\n", pos + processed);
|
||||
pos += processed;
|
||||
prnt("setting " ARFCNDL ": %ld [len %d]\n", arfcn, pos);
|
||||
|
||||
long bwdl;
|
||||
processed = read_long(buf + pos, end, BWDL, &bwdl);
|
||||
if (processed < 0)
|
||||
ERROR_MSG_RET("could not read " BWDL " at index %d\n", pos + processed);
|
||||
pos += processed;
|
||||
prnt("setting " BWDL ": %ld [len %d]\n", bwdl, pos);
|
||||
|
||||
long numrbs;
|
||||
processed = read_long(buf + pos, end, NUMRBS, &numrbs);
|
||||
if (processed < 0)
|
||||
ERROR_MSG_RET("could not read " NUMRBS " at index %d\n", pos + processed);
|
||||
pos += processed;
|
||||
prnt("setting " NUMRBS ": %ld [len %d]\n", numrbs, pos);
|
||||
|
||||
long startrb;
|
||||
processed = read_long(buf + pos, end, STARTRB, &startrb);
|
||||
if (processed < 0)
|
||||
ERROR_MSG_RET("could not read " STARTRB " at index %d\n", pos + processed);
|
||||
pos += processed;
|
||||
prnt("setting " STARTRB ": %ld [len %d]\n", startrb, pos);
|
||||
|
||||
int locationAndBandwidth = PRBalloc_to_locationandbandwidth0(numrbs, startrb, MAX_BWP_SIZE);
|
||||
prnt("inferred locationAndBandwidth: %d\n", locationAndBandwidth);
|
||||
|
||||
/*
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
NR_ServingCellConfigCommon_t *scc = rrc->carrier.servingcellconfigcommon;
|
||||
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
|
||||
NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
|
||||
NR_FrequencyInfoUL_t *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL;
|
||||
NR_BWP_t *initialUL = &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
|
||||
|
||||
//--gNBs.[0].servingCellConfigCommon.[0].absoluteFrequencySSB 620736 -> SSBFREQ
|
||||
*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB = ssbfreq;
|
||||
|
||||
// --gNBs.[0].servingCellConfigCommon.[0].dl_absoluteFrequencyPointA 620020 -> ARFCNDL
|
||||
frequencyInfoDL->absoluteFrequencyPointA = arfcn;
|
||||
AssertFatal(frequencyInfoUL->absoluteFrequencyPointA == NULL, "only handle TDD\n");
|
||||
|
||||
// --gNBs.[0].servingCellConfigCommon.[0].dl_carrierBandwidth 51 -> BWDL
|
||||
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = bwdl;
|
||||
|
||||
// --gNBs.[0].servingCellConfigCommon.[0].initialDLBWPlocationAndBandwidth 13750 -> NUMRBS + STARTRB
|
||||
initialDL->locationAndBandwidth = locationAndBandwidth;
|
||||
|
||||
// --gNBs.[0].servingCellConfigCommon.[0].ul_carrierBandwidth 51 -> BWUL?
|
||||
// we assume the same BW as DL
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = bwdl;
|
||||
|
||||
// --gNBs.[0].servingCellConfigCommon.[0].initialULBWPlocationAndBandwidth 13750 -> ?
|
||||
// we assume same locationAndBandwidth as DL
|
||||
initialUL->locationAndBandwidth = locationAndBandwidth;
|
||||
*/
|
||||
|
||||
prnt("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int8_t threequarter_fs;
|
||||
extern openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
static int set_bwconfig(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
if (running)
|
||||
ERROR_MSG_RET("cannot set parameters while L1 is running\n");
|
||||
if (!buf)
|
||||
ERROR_MSG_RET("need param: o1 bwconfig <BW>\n");
|
||||
|
||||
char *end = NULL;
|
||||
if (NULL != (end = strchr(buf, '\n')))
|
||||
*end = 0;
|
||||
if (NULL != (end = strchr(buf, '\r')))
|
||||
*end = 0;
|
||||
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
|
||||
NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
|
||||
NR_FrequencyInfoUL_t *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL;
|
||||
NR_BWP_t *initialUL = &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
|
||||
if (strcmp(buf, "40") == 0) {
|
||||
*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB = 641280;
|
||||
frequencyInfoDL->absoluteFrequencyPointA = 640008;
|
||||
AssertFatal(frequencyInfoUL->absoluteFrequencyPointA == NULL, "only handle TDD\n");
|
||||
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = 106;
|
||||
initialDL->locationAndBandwidth = 28875;
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = 106;
|
||||
initialUL->locationAndBandwidth = 28875;
|
||||
threequarter_fs = 1;
|
||||
openair0_cfg[0].threequarter_fs = 1;
|
||||
} else if (strcmp(buf, "20") == 0) {
|
||||
*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB = 641280;
|
||||
frequencyInfoDL->absoluteFrequencyPointA = 640596;
|
||||
AssertFatal(frequencyInfoUL->absoluteFrequencyPointA == NULL, "only handle TDD\n");
|
||||
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = 51;
|
||||
initialDL->locationAndBandwidth = 13750;
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = 51;
|
||||
initialUL->locationAndBandwidth = 13750;
|
||||
threequarter_fs = 0;
|
||||
openair0_cfg[0].threequarter_fs = 0;
|
||||
} else {
|
||||
ERROR_MSG_RET("unhandled option %s\n", buf);
|
||||
}
|
||||
|
||||
free(RC.nrmac[0]->sched_ctrlCommon);
|
||||
RC.nrmac[0]->sched_ctrlCommon = NULL;
|
||||
|
||||
|
||||
free_MIB_NR(mac->common_channels[0].mib);
|
||||
mac->common_channels[0].mib = get_new_MIB_NR(scc);
|
||||
|
||||
// due to outrightly CRAZY memory handling in get_SIB1_NR(), we need to set
|
||||
// some structures to zero to prevent that we shoot ourselves into the foot
|
||||
//struct NR_SIB1 *xyz = rrc->carrier.siblock1->message.choice.c1->choice.systemInformationBlockType1;
|
||||
//xyz->servingCellConfigCommon = NULL;
|
||||
//free_SIB1_NR(rrc->carrier.siblock1);
|
||||
const f1ap_served_cell_info_t *info = &mac->f1_config.setup_req->cell[0].info;
|
||||
/*
|
||||
NR_BCCH_DL_SCH_Message_t *sib1 = get_SIB1_NR(scc, &info->plmn, into->nr_cellid, *info.tac);
|
||||
rrc->carrier.SIB1 = calloc(NR_MAX_SIB_LENGTH / 8, sizeof(*rrc->carrier.SIB1));
|
||||
AssertFatal(rrc->carrier.SIB1 != NULL, "out of memory\n");
|
||||
rrc->carrier.sizeof_SIB1 = encode_SIB1_NR(sib1, rrc->carrier.SIB1, NR_MAX_SIB_LENGTH / 8);
|
||||
rrc->carrier.siblock1 = sib1;
|
||||
*/
|
||||
nr_mac_configure_sib1(mac, &info->plmn, info->nr_cellid, *info->tac);
|
||||
|
||||
//nr_mac_config_scc(mac, scc, &mac->radio_config);
|
||||
|
||||
prnt("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int stop_L1L2(module_id_t gnb_id);
|
||||
static int stop_modem(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
if (!running)
|
||||
ERROR_MSG_RET("cannot stop, nr-softmodem not running\n");
|
||||
|
||||
/* make UEs out of sync and wait 20ms to ensure no PUCCH is scheduled. After
|
||||
* a restart, the frame/slot numbers will be different, which "confuses" the
|
||||
* scheduler, which has many PUCCH structures filled with expected frame/slot
|
||||
* combinations that won't happen. */
|
||||
const gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
|
||||
it->UE_sched_ctrl.rrc_processing_timer = 1000;
|
||||
}
|
||||
usleep(50000);
|
||||
|
||||
stop_L1L2(0);
|
||||
running = false;
|
||||
prnt("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int start_L1L2(module_id_t gnb_id);
|
||||
static int start_modem(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
if (running)
|
||||
ERROR_MSG_RET("cannot start, nr-softmodem already running\n");
|
||||
start_L1L2(0);
|
||||
running = true;
|
||||
prnt("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static telnetshell_cmddef_t o1cmds[] = {
|
||||
{"stats", "", get_stats},
|
||||
{"config", "[]", set_config},
|
||||
{"bwconfig", "", set_bwconfig},
|
||||
{"stop_modem", "", stop_modem},
|
||||
{"start_modem", "", start_modem},
|
||||
{"", "", NULL},
|
||||
};
|
||||
|
||||
static telnetshell_vardef_t o1vars[] = {
|
||||
{"", 0, 0, NULL}
|
||||
};
|
||||
|
||||
void add_o1_cmds(void) {
|
||||
add_telnetcmd("o1", o1vars, o1cmds);
|
||||
}
|
||||
99
cu.conf
Normal file
99
cu.conf
Normal file
@@ -0,0 +1,99 @@
|
||||
Active_gNBs = ( "gNB-CU-in-docker");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
Num_Threads_PUSCH = 8;
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xc00;
|
||||
|
||||
# cell_type = "CELL_MACRO_GNB";
|
||||
|
||||
gNB_name = "gNB-CU-in-docker";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
|
||||
nr_cellid = 1L;
|
||||
|
||||
tr_s_preference = "f1";
|
||||
|
||||
local_s_if_name = "eth0";
|
||||
local_s_address = "16.1.1.3";
|
||||
remote_s_address = "16.1.1.2";
|
||||
local_s_portc = 501;
|
||||
local_s_portd = 2154;
|
||||
remote_s_portc = 500;
|
||||
remote_s_portd = 2153;
|
||||
#min_rxtxtime = 6;
|
||||
|
||||
enable_sdap = 1;
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "192.168.70.132";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp3s0";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "enp3s0";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
e2_agent = {
|
||||
#near_ric_ip_addr = "16.1.1.3";
|
||||
#near_ric_ip_addr = "10.104.66.177";
|
||||
near_ric_ip_addr = "16.1.1.3";
|
||||
sm_dir = "/usr/local/lib/flexric/"
|
||||
}
|
||||
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="debug";
|
||||
f1ap_log_level ="info";
|
||||
};
|
||||
263
du_20.conf
Normal file
263
du_20.conf
Normal file
@@ -0,0 +1,263 @@
|
||||
Active_gNBs = ( "gNB");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
sa=1;
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xd00;
|
||||
gNB_DU_ID = 0xd01;
|
||||
|
||||
# cell_type = "CELL_MACRO_GNB";
|
||||
|
||||
gNB_name = "gNB";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
|
||||
nr_cellid = 1L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
#min_rxtxtime = 6;
|
||||
force_256qam_off = 0;
|
||||
|
||||
do_CSIRS = 0;
|
||||
do_SRS = 0;
|
||||
|
||||
pdcch_ConfigSIB1 = (
|
||||
{
|
||||
controlResourceSetZero = 12;
|
||||
searchSpaceZero = 0;
|
||||
}
|
||||
);
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3300.30 MHz + (19 PRBs + 10 SCs)@30kHz SCS (GSCN: 7715)
|
||||
absoluteFrequencySSB = 641280; #620736;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3300.30 MHz
|
||||
dl_absoluteFrequencyPointA = 640596; #620052;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 51;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 13750;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 51;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 13750;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
preambleReceivedTargetPower = -96;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "f1";
|
||||
local_n_if_name = "eth0";
|
||||
local_n_address = "16.1.1.2";
|
||||
#local_n_address = "172.23.100.26";
|
||||
remote_n_address = "16.1.1.3";
|
||||
#remote_n_address = "172.23.100.27";
|
||||
local_n_portc = 500;
|
||||
local_n_portd = 2153;
|
||||
remote_n_portc = 501;
|
||||
remote_n_portd = 2154;
|
||||
pusch_TargetSNRx10 = 230; # 200; after test in lab
|
||||
pucch_TargetSNRx10 = 200;
|
||||
ulsch_max_frame_inactivity = 1;
|
||||
ul_max_mcs = 16;
|
||||
min_grant_prb = 20;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
pucch0_dtx_threshold = 100;
|
||||
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
|
||||
max_ldpc_iterations = 10;
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 6; # 8; after test in lab
|
||||
att_rx = 6; # 8; after test in lab
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 125;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
e2_agent = {
|
||||
#near_ric_ip_addr = "16.1.1.3"
|
||||
#near_ric_ip_addr = "10.104.66.177"
|
||||
near_ric_ip_addr = "16.1.1.3";
|
||||
sm_dir = "/usr/local/lib/flexric/"
|
||||
};
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = "4043";
|
||||
options = (); #("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="info";
|
||||
f1ap_log_level ="info";
|
||||
};
|
||||
263
du_40.conf
Normal file
263
du_40.conf
Normal file
@@ -0,0 +1,263 @@
|
||||
Active_gNBs = ( "gNB-DU-in-docker");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
sa=1;
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xd00;
|
||||
gNB_DU_ID = 0xd01;
|
||||
|
||||
# cell_type = "CELL_MACRO_GNB";
|
||||
|
||||
gNB_name = "gNB-DU-in-docker";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
|
||||
nr_cellid = 1L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
#min_rxtxtime = 6;
|
||||
force_256qam_off = 0;
|
||||
|
||||
do_CSIRS = 0;
|
||||
do_SRS = 0;
|
||||
|
||||
pdcch_ConfigSIB1 = (
|
||||
{
|
||||
controlResourceSetZero = 12;
|
||||
searchSpaceZero = 0;
|
||||
}
|
||||
);
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
|
||||
absoluteFrequencySSB = 641280;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3600 MHz
|
||||
dl_absoluteFrequencyPointA = 640008;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
preambleReceivedTargetPower = -96;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "f1";
|
||||
local_n_if_name = "eth0";
|
||||
local_n_address = "16.1.1.2";
|
||||
#local_n_address = "172.23.100.26";
|
||||
remote_n_address = "16.1.1.3";
|
||||
#remote_n_address = "172.23.100.27";
|
||||
local_n_portc = 500;
|
||||
local_n_portd = 2153;
|
||||
remote_n_portc = 501;
|
||||
remote_n_portd = 2154;
|
||||
pusch_TargetSNRx10 = 230; # 200; after test in lab
|
||||
pucch_TargetSNRx10 = 200;
|
||||
ulsch_max_frame_inactivity = 1;
|
||||
ul_max_mcs = 16;
|
||||
min_grant_prb = 20;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
pucch0_dtx_threshold = 100;
|
||||
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
|
||||
max_ldpc_iterations = 10;
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 6; # 8; after test in lab
|
||||
att_rx = 6; # 8; after test in lab
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 125;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
e2_agent = {
|
||||
#near_ric_ip_addr = "16.1.1.3"
|
||||
#near_ric_ip_addr = "10.104.66.177"
|
||||
near_ric_ip_addr = "16.1.1.3";
|
||||
sm_dir = "/usr/local/lib/flexric/"
|
||||
};
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = "4043";
|
||||
options = (); #("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="info";
|
||||
f1ap_log_level ="info";
|
||||
};
|
||||
@@ -149,6 +149,9 @@ f1ap_cudu_inst_t *getCxt(instance_t instanceP)
|
||||
return &fake;
|
||||
}
|
||||
configmodule_interface_t *uniqCfg = NULL;
|
||||
|
||||
void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t gNB_ue_ngap_id) { };
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/// static configuration for NR at the moment
|
||||
|
||||
@@ -548,6 +548,122 @@ void terminate_task(task_id_t task_id, module_id_t mod_id) {
|
||||
//extern void free_transport(PHY_VARS_gNB *);
|
||||
extern void nr_phy_free_RU(RU_t *);
|
||||
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
|
||||
int stop_L1L2(module_id_t gnb_id)
|
||||
{
|
||||
LOG_W(GNB_APP, "stopping nr-softmodem\n");
|
||||
oai_exit = 1;
|
||||
|
||||
if (!RC.ru) {
|
||||
LOG_F(GNB_APP, "no RU configured\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* stop trx devices, multiple carrier currently not supported by RU */
|
||||
if (RC.ru[gnb_id]) {
|
||||
AssertFatal(RC.ru[gnb_id]->rfdevice.trx_stop_func != NULL, "cannot call rfdevice.trx_stop_func(), is NULL\n");
|
||||
RC.ru[gnb_id]->rfdevice.trx_stop_func(&RC.ru[gnb_id]->rfdevice);
|
||||
LOG_I(GNB_APP, "turned off RU rfdevice\n");
|
||||
|
||||
/*
|
||||
AssertFatal(RC.ru[gnb_id]->ifdevice.trx_stop_func != NULL, "cannot call ifdevice.trx_stop_func(), is NULL\n");
|
||||
RC.ru[gnb_id]->ifdevice.trx_stop_func(&RC.ru[gnb_id]->ifdevice);
|
||||
LOG_I(GNB_APP, "turned off RU ifdevice\n");
|
||||
*/
|
||||
}
|
||||
|
||||
/* these tasks/layers need to pick up new configuration */
|
||||
if (RC.nb_nr_L1_inst > 0)
|
||||
stop_gNB(RC.nb_nr_L1_inst);
|
||||
|
||||
if (RC.nb_RU > 0)
|
||||
stop_RU(RC.nb_RU);
|
||||
|
||||
/* release memory used by the RU/gNB threads (incomplete), after all
|
||||
* threads have been stopped (they partially use the same memory) */
|
||||
for (int inst = 0; inst < RC.nb_RU; inst++) {
|
||||
nr_phy_free_RU(RC.ru[inst]);
|
||||
}
|
||||
|
||||
for (int inst = 0; inst < RC.nb_nr_L1_inst; inst++) {
|
||||
phy_free_nr_gNB(RC.gNB[inst]);
|
||||
}
|
||||
oai_exit = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern f1ap_tdd_info_t read_tdd_config(const NR_ServingCellConfigCommon_t *scc);
|
||||
extern f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1);
|
||||
/*
|
||||
* Restart the nr-softmodem after it has been soft-stopped with stop_L1L2()
|
||||
*/
|
||||
int start_L1L2(module_id_t gnb_id)
|
||||
{
|
||||
//RU_t *ru = RC.ru[gnb_id];
|
||||
//MessageDef *msg_p = NULL;
|
||||
LOG_W(GNB_APP, "restarting nr-softmodem\n");
|
||||
/* block threads */
|
||||
sync_var = -1;
|
||||
RC.gNB[gnb_id]->configured = 0;
|
||||
extern void init_sched_response(void);
|
||||
init_sched_response();
|
||||
/*
|
||||
RC.ru_mask |= (1 << ru->idx);
|
||||
set_function_spec_param(RC.ru[gnb_id]);
|
||||
LOG_I(GNB_APP, "attempting to create ITTI tasks\n");
|
||||
*/
|
||||
// No more rrc thread, as many race conditions are hidden behind
|
||||
|
||||
//int rc = itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL);
|
||||
//AssertFatal(rc == 0, "could not create RRC task\n");
|
||||
/* pass a reconfiguration request which will configure everything down to
|
||||
* RC.eNB[i][j]->frame_parms, too */
|
||||
/*
|
||||
msg_p = itti_alloc_new_message(TASK_GNB_APP, 0, NRRRC_CONFIGURATION_REQ);
|
||||
NRRRC_CONFIGURATION_REQ(msg_p) = RC.nrrrc[gnb_id]->configuration;
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg_p);
|
||||
*/
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
nr_mac_config_scc(mac, scc, &mac->radio_config);
|
||||
|
||||
NR_BCCH_BCH_Message_t *mib = mac->common_channels[0].mib;
|
||||
const NR_BCCH_DL_SCH_Message_t *sib1 = mac->common_channels[0].sib1;
|
||||
|
||||
/* update existing config in F1 Setup request structures */
|
||||
f1ap_setup_req_t *sr = mac->f1_config.setup_req;
|
||||
DevAssert(sr->num_cells_available == 1);
|
||||
f1ap_served_cell_info_t *info = &sr->cell[0].info;
|
||||
DevAssert(info->mode == F1AP_MODE_TDD);
|
||||
DevAssert(scc->tdd_UL_DL_ConfigurationCommon != NULL);
|
||||
info->tdd = read_tdd_config(scc); /* updates radio config */
|
||||
|
||||
/* send gNB-DU configuration update to RRC */
|
||||
f1ap_gnb_du_configuration_update_t update = {
|
||||
.transaction_id = 1,
|
||||
.num_cells_to_modify = 1,
|
||||
};
|
||||
update.cell_to_modify[0].old_nr_cellid = info->nr_cellid;
|
||||
update.cell_to_modify[0].info = *info;
|
||||
update.cell_to_modify[0].sys_info = get_sys_info(mib, sib1);
|
||||
mac->mac_rrc.gnb_du_configuration_update(&update);
|
||||
|
||||
//sleep(2);
|
||||
|
||||
init_NR_RU(config_get_if(), NULL);
|
||||
|
||||
start_NR_RU();
|
||||
wait_RUs();
|
||||
init_eNB_afterRU();
|
||||
printf("Sending sync to all threads\n");
|
||||
pthread_mutex_lock(&sync_mutex);
|
||||
sync_var=0;
|
||||
pthread_cond_broadcast(&sync_cond);
|
||||
pthread_mutex_unlock(&sync_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wait_nfapi_init(char *thread_name) {
|
||||
printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
|
||||
pthread_mutex_lock( &nfapi_sync_mutex );
|
||||
|
||||
@@ -168,6 +168,9 @@ nr_bler_struct nr_bler_data[NR_NUM_MCS];
|
||||
|
||||
static void init_bler_table(char*);
|
||||
|
||||
// to be removed
|
||||
void nr_mac_trigger_ul_failure(int rnti) { abort(); }
|
||||
|
||||
/*---------------------BMC: timespec helpers -----------------------------*/
|
||||
|
||||
struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
|
||||
|
||||
257
gnb_20.conf
Normal file
257
gnb_20.conf
Normal file
@@ -0,0 +1,257 @@
|
||||
Active_gNBs = ( "du");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
|
||||
# cell_type = "CELL_MACRO_GNB";
|
||||
|
||||
gNB_name = "du";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
#min_rxtxtime = 6;
|
||||
force_256qam_off = 0;
|
||||
|
||||
do_CSIRS = 0;
|
||||
do_SRS = 0;
|
||||
|
||||
pdcch_ConfigSIB1 = (
|
||||
{
|
||||
controlResourceSetZero = 12;
|
||||
searchSpaceZero = 0;
|
||||
}
|
||||
);
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3300.30 MHz + (19 PRBs + 10 SCs)@30kHz SCS (GSCN: 7715)
|
||||
absoluteFrequencySSB = 641280; #620736;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3300.30 MHz
|
||||
dl_absoluteFrequencyPointA = 640596; #620052;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 51;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 13750;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 51;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 13750;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
preambleReceivedTargetPower = -96;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "192.168.70.132";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp3s0";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "16.1.1.2";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "enp3s0";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "16.1.1.2";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 230; # 200; after test in lab
|
||||
pucch_TargetSNRx10 = 200;
|
||||
ulsch_max_frame_inactivity = 1;
|
||||
ul_max_mcs = 16;
|
||||
min_grant_prb = 20;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
pucch0_dtx_threshold = 100;
|
||||
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 6; # 8; after test in lab
|
||||
att_rx = 6; # 8; after test in lab
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 115; #120;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="info";
|
||||
f1ap_log_level ="info";
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
gtp_log_level ="debug";
|
||||
>>>>>>> origin/qoe-e2
|
||||
};
|
||||
267
gnb_40.conf
Normal file
267
gnb_40.conf
Normal file
@@ -0,0 +1,267 @@
|
||||
Active_gNBs = ( "gNB-DU-in-docker");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
|
||||
# cell_type = "CELL_MACRO_GNB";
|
||||
|
||||
gNB_name = "gNB-DU-in-docker";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
#min_rxtxtime = 6;
|
||||
force_256qam_off = 0;
|
||||
|
||||
do_CSIRS = 0;
|
||||
do_SRS = 0;
|
||||
|
||||
pdcch_ConfigSIB1 = (
|
||||
{
|
||||
controlResourceSetZero = 12;
|
||||
searchSpaceZero = 0;
|
||||
}
|
||||
);
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
|
||||
absoluteFrequencySSB = 641280;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3600 MHz
|
||||
dl_absoluteFrequencyPointA = 640008;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
preambleReceivedTargetPower = -96;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "192.168.70.132";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp3s0";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "16.1.1.2";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "enp3s0";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "16.1.1.2";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
e2_agent = {
|
||||
#address = "10.0.0.4";
|
||||
address = "172.23.100.25";
|
||||
sm_dir = "/usr/local/lib/flexric/"
|
||||
}
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 230; # 200; after test in lab
|
||||
pucch_TargetSNRx10 = 200;
|
||||
ulsch_max_frame_inactivity = 1;
|
||||
ul_max_mcs = 16;
|
||||
min_grant_prb = 20;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
pucch0_dtx_threshold = 100;
|
||||
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 6; # 8; after test in lab
|
||||
att_rx = 6; # 8; after test in lab
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 115;
|
||||
eNB_instances = [0];
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = "4043";
|
||||
options = (); #("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="info";
|
||||
f1ap_log_level ="info";
|
||||
};
|
||||
@@ -550,11 +550,6 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config)
|
||||
nr_init_frame_parms(gNB_config, fp);
|
||||
|
||||
|
||||
if (RC.gNB[Mod_id]->configured == 1) {
|
||||
LOG_E(PHY,"Already gNB already configured, do nothing\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fd_occasion = 0;
|
||||
nfapi_nr_prach_config_t *prach_config = &gNB_config->prach_config;
|
||||
short_sequence = prach_config->prach_sequence_length.value;
|
||||
|
||||
@@ -217,4 +217,8 @@ void nr_phy_free_RU(RU_t *ru)
|
||||
}
|
||||
}
|
||||
free_and_zero(ru->common.sync_corr);
|
||||
|
||||
PHY_VARS_gNB *gNB0= ru->gNB_list[0];
|
||||
gNB0->num_RU--;
|
||||
DevAssert(gNB0->num_RU >= 0);
|
||||
}
|
||||
|
||||
@@ -27,11 +27,14 @@ MESSAGE_DEF(F1AP_DU_REGISTER_REQ, MESSAGE_PRIORITY_MED, f1ap_du_register_req_t,
|
||||
MESSAGE_DEF(F1AP_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_setup_req_t , f1ap_setup_req)
|
||||
MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_acknowledge_t , f1ap_gnb_cu_configuration_update_acknowledge)
|
||||
MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_failure_t , f1ap_gnb_cu_configuration_update_failure)
|
||||
MESSAGE_DEF(F1AP_GNB_DU_CONFIGURATION_UPDATE, MESSAGE_PRIORITY_MED, f1ap_gnb_du_configuration_update_t, f1ap_gnb_du_configuration_update)
|
||||
|
||||
/* F1AP -> eNB_DU or eNB_CU_RRC -> F1AP application layer messages */
|
||||
MESSAGE_DEF(F1AP_SETUP_RESP , MESSAGE_PRIORITY_MED, f1ap_setup_resp_t , f1ap_setup_resp)
|
||||
MESSAGE_DEF(F1AP_SETUP_FAILURE , MESSAGE_PRIORITY_MED, f1ap_setup_failure_t , f1ap_setup_failure)
|
||||
MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_t , f1ap_gnb_cu_configuration_update)
|
||||
MESSAGE_DEF(F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE , MESSAGE_PRIORITY_MED, f1ap_gnb_du_configuration_update_acknowledge_t, f1ap_gnb_du_configuration_update_acknowledge)
|
||||
MESSAGE_DEF(F1AP_GNB_DU_CONFIGURATION_UPDATE_FAILURE , MESSAGE_PRIORITY_MED, f1ap_gnb_du_configuration_update_failure_t, f1ap_gnb_du_configuration_update_failure)
|
||||
|
||||
/* F1AP -> RRC to inform about lost connection */
|
||||
MESSAGE_DEF(F1AP_LOST_CONNECTION, MESSAGE_PRIORITY_MED, f1ap_lost_connection_t, f1ap_lost_connection)
|
||||
|
||||
@@ -39,6 +39,10 @@
|
||||
#define F1AP_GNB_CU_CONFIGURATION_UPDATE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update
|
||||
#define F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update_acknowledge
|
||||
#define F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update_failure
|
||||
#define F1AP_GNB_DU_CONFIGURATION_UPDATE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_du_configuration_update
|
||||
#define F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_du_configuration_update_acknowledge
|
||||
#define F1AP_GNB_DU_CONFIGURATION_UPDATE_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_du_configuration_update_failure
|
||||
|
||||
#define F1AP_SETUP_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_setup_failure
|
||||
|
||||
#define F1AP_LOST_CONNECTION(mSGpTR) (mSGpTR)->ittiMsg.f1ap_lost_connection
|
||||
@@ -127,7 +131,7 @@ typedef struct f1ap_served_cell_info_t {
|
||||
// Number of slide support items (max 16, could be increased to as much as 1024)
|
||||
uint16_t num_ssi;
|
||||
uint8_t sst;
|
||||
uint8_t sd;
|
||||
uint32_t sd;
|
||||
|
||||
f1ap_mode_t mode;
|
||||
union {
|
||||
@@ -246,6 +250,58 @@ typedef struct f1ap_gnb_cu_configuration_update_failure_s {
|
||||
uint16_t criticality_diagnostics;
|
||||
} f1ap_gnb_cu_configuration_update_failure_t;
|
||||
|
||||
/*DU configuration messages*/
|
||||
typedef struct f1ap_gnb_du_configuration_update_s {
|
||||
/*TODO UPDATE TO SUPPORT DU CONFIG*/
|
||||
|
||||
/* Transaction ID */
|
||||
uint64_t transaction_id;
|
||||
/// int cells_to_add
|
||||
uint16_t num_cells_to_add;
|
||||
struct {
|
||||
f1ap_served_cell_info_t info;
|
||||
f1ap_gnb_du_system_info_t *sys_info;
|
||||
} cell_to_add[F1AP_MAX_NB_CELLS];
|
||||
|
||||
/// int cells_to_modify
|
||||
uint16_t num_cells_to_modify;
|
||||
struct {
|
||||
f1ap_plmn_t old_plmn;
|
||||
uint64_t old_nr_cellid; // NR Global Cell Id
|
||||
f1ap_served_cell_info_t info;
|
||||
f1ap_gnb_du_system_info_t *sys_info;
|
||||
} cell_to_modify[F1AP_MAX_NB_CELLS];
|
||||
|
||||
/// int cells_to_delete
|
||||
uint16_t num_cells_to_delete;
|
||||
struct {
|
||||
// NR CGI
|
||||
f1ap_plmn_t plmn;
|
||||
uint64_t nr_cellid; // NR Global Cell Id
|
||||
} cell_to_delete[F1AP_MAX_NB_CELLS];
|
||||
|
||||
/// string holding gNB_CU_name
|
||||
uint64_t *gNB_DU_ID;
|
||||
} f1ap_gnb_du_configuration_update_t;
|
||||
|
||||
typedef struct f1ap_gnb_du_configuration_update_acknowledge_s {
|
||||
/// ulong transaction id
|
||||
uint64_t transaction_id;
|
||||
/// string holding gNB_CU_name
|
||||
char *gNB_CU_name;
|
||||
/// number of DU cells to activate
|
||||
uint16_t num_cells_to_activate; //0< num_cells_to_activate <= 512;
|
||||
served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS];
|
||||
} f1ap_gnb_du_configuration_update_acknowledge_t;
|
||||
|
||||
typedef struct f1ap_gnb_du_configuration_update_failure_s {
|
||||
/*TODO UPDATE TO SUPPORT DU CONFIG*/
|
||||
uint16_t cause;
|
||||
uint16_t time_to_wait;
|
||||
uint16_t criticality_diagnostics;
|
||||
} f1ap_gnb_du_configuration_update_failure_t;
|
||||
|
||||
|
||||
typedef struct f1ap_dl_rrc_message_s {
|
||||
|
||||
uint32_t gNB_CU_ue_id;
|
||||
|
||||
@@ -412,6 +412,8 @@ typedef struct NRRrcConfigurationReq_s {
|
||||
uint16_t mnc[PLMN_LIST_MAX_SIZE];
|
||||
uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE];
|
||||
uint8_t num_plmn;
|
||||
int sd;
|
||||
int sst;
|
||||
|
||||
bool um_on_default_drb;
|
||||
bool enable_sdap;
|
||||
|
||||
@@ -214,22 +214,43 @@ sm_ag_if_ans_t write_subs_rc_sm(void const* src)
|
||||
return ans;
|
||||
}
|
||||
|
||||
void rrc_gNB_trigger_new_bearer(int rnti);
|
||||
void rrc_gNB_trigger_release_bearer(int rnti);
|
||||
|
||||
sm_ag_if_ans_t write_ctrl_rc_sm(void const* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
// assert(data->type == RAN_CONTROL_CTRL_V1_03 );
|
||||
// assert(data->type == RAN_CONTROL_CTRL_V1_03 );
|
||||
|
||||
rc_ctrl_req_data_t const* ctrl = (rc_ctrl_req_data_t const*)data;
|
||||
if(ctrl->hdr.format == FORMAT_1_E2SM_RC_CTRL_HDR){
|
||||
if(ctrl->hdr.frmt_1.ric_style_type == 1 && ctrl->hdr.frmt_1.ctrl_act_id == 2){
|
||||
printf("QoS flow mapping configuration \n");
|
||||
|
||||
//mir
|
||||
//int const rnti = get_single_ue_rnti();
|
||||
int const rnti = -1;
|
||||
|
||||
printf("QoS flow mapping configuration with rnti %d \n", rnti);
|
||||
e2sm_rc_ctrl_msg_frmt_1_t const* frmt_1 = &ctrl->msg.frmt_1;
|
||||
printf("int_ran %ld \n", frmt_1->ran_param[0].ran_param_val.flag_true->int_ran);
|
||||
|
||||
for(size_t i = 0; i < frmt_1->sz_ran_param; ++i){
|
||||
seq_ran_param_t const* rp = frmt_1->ran_param;
|
||||
if(rp[i].ran_param_id == 1){
|
||||
assert(rp[i].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE );
|
||||
printf("DRB ID %ld \n", rp[i].ran_param_val.flag_true->int_ran);
|
||||
if(rp[i].ran_param_val.flag_true->int_ran == 5){
|
||||
printf("[O-RAN RC]: Creating a new bearer\n");
|
||||
fflush(stdout);
|
||||
rrc_gNB_trigger_new_bearer(rnti);
|
||||
} else if(rp[i].ran_param_val.flag_true->int_ran == 4){
|
||||
printf("[O-RAN RC]: Releasing bearer\n");
|
||||
fflush(stdout);
|
||||
rrc_gNB_trigger_release_bearer(rnti);
|
||||
} else{
|
||||
assert(0!=0 && "Unknown int_ran");
|
||||
}
|
||||
|
||||
} else if(rp[i].ran_param_id == 2){
|
||||
assert(rp[i].ran_param_val.type == LIST_RAN_PARAMETER_VAL_TYPE);
|
||||
printf("List of QoS Flows to be modified \n");
|
||||
|
||||
Submodule openair2/E2AP/flexric updated: 29af8408af...e4a676b58b
@@ -431,17 +431,337 @@ int CU_send_F1_SETUP_FAILURE(sctp_assoc_t assoc_id, const f1ap_setup_failure_t *
|
||||
|
||||
int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
|
||||
{
|
||||
AssertFatal(1==0,"Not implemented yet\n");
|
||||
LOG_D(F1AP, "CU_handle_gNB_DU_CONFIGURATION_UPDATE\n");
|
||||
F1AP_GNBDUConfigurationUpdate_t *container;
|
||||
F1AP_GNBDUConfigurationUpdateIEs_t *ie;
|
||||
int i = 0;
|
||||
DevAssert(pdu != NULL);
|
||||
container = &pdu->choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate;
|
||||
|
||||
/* gNB DU Configuration Update == Non UE-related procedure -> stream 0 */
|
||||
if (stream != 0) {
|
||||
LOG_W(F1AP, "[SCTP %d] Received f1 setup request on stream != 0 (%d)\n",
|
||||
assoc_id, stream);
|
||||
}
|
||||
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE);
|
||||
message_p->ittiMsgHeader.originInstance = assoc_id;
|
||||
f1ap_gnb_du_configuration_update_t *req = &F1AP_GNB_DU_CONFIGURATION_UPDATE(message_p);
|
||||
|
||||
/* 3GPP TS 38.473 Transaction ID*/
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true);
|
||||
req->transaction_id = ie->value.choice.TransactionID;
|
||||
LOG_D(F1AP, "req->transaction_id %lu \n", req->transaction_id);
|
||||
|
||||
/* 3GPP TS 38.473 Served Cells To Add List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container,
|
||||
F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List, false);
|
||||
|
||||
if(ie!=NULL){
|
||||
req->num_cells_to_add = ie->value.choice.Served_Cells_To_Add_List.list.count;
|
||||
LOG_D(F1AP, "req->num_cells_to_add %d \n", req->num_cells_to_add);
|
||||
|
||||
for (i=0; i<req->num_cells_to_add; i++) {
|
||||
F1AP_Served_Cells_To_Add_Item_t *served_cells_item = &((F1AP_Served_Cells_To_Add_ItemIEs_t *)
|
||||
ie->value.choice.Served_Cells_To_Add_List.list.array[i])->
|
||||
value.choice.Served_Cells_To_Add_Item;
|
||||
F1AP_Served_Cell_Information_t *servedCellInformation= &served_cells_item->served_Cell_Information;
|
||||
/* tac */
|
||||
if (servedCellInformation->fiveGS_TAC) {
|
||||
req->cell_to_add[i].info.tac = malloc(sizeof(*req->cell_to_add[i].info.tac));
|
||||
AssertFatal(req->cell_to_add[i].info.tac != NULL, "out of memory\n");
|
||||
OCTET_STRING_TO_INT24(servedCellInformation->fiveGS_TAC, *req->cell_to_add[i].info.tac);
|
||||
LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell_to_add[i].info.tac);
|
||||
}
|
||||
|
||||
/* - nRCGI */
|
||||
TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity),
|
||||
req->cell_to_add[i].info.plmn.mcc,
|
||||
req->cell_to_add[i].info.plmn.mnc,
|
||||
req->cell_to_add[i].info.plmn.mnc_digit_length);
|
||||
// NR cellID
|
||||
BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity,
|
||||
req->cell_to_add[i].info.nr_cellid);
|
||||
LOG_D(F1AP, "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id,
|
||||
req->cell_to_add[i].info.plmn.mcc,
|
||||
req->cell_to_add[i].info.plmn.mnc,
|
||||
(long long unsigned int)req->cell_to_add[i].info.nr_cellid);
|
||||
|
||||
/* - nRPCI */
|
||||
req->cell_to_add[i].info.nr_pci = servedCellInformation->nRPCI;
|
||||
LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell_to_add[i].info.nr_pci);
|
||||
|
||||
// FDD Cells
|
||||
if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_fDD) {
|
||||
req->cell_to_add[i].info.mode = F1AP_MODE_FDD;
|
||||
f1ap_fdd_info_t *FDDs = &req->cell_to_add[i].info.fdd;
|
||||
F1AP_FDD_Info_t * fDD_Info=servedCellInformation->nR_Mode_Info.choice.fDD;
|
||||
FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN;
|
||||
AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n");
|
||||
for (int f=0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) {
|
||||
F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f];
|
||||
FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr;
|
||||
AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n");
|
||||
}
|
||||
FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN;
|
||||
int dlBands=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count;
|
||||
AssertFatal(dlBands == 0, "cannot handled more than one frequency band\n");
|
||||
for (int dlB=0; dlB < dlBands; dlB++) {
|
||||
F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB];
|
||||
FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr;
|
||||
int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count;
|
||||
AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n");
|
||||
}
|
||||
FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS;
|
||||
FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB];
|
||||
FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS;
|
||||
FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB];
|
||||
} else if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_tDD) {
|
||||
req->cell_to_add[i].info.mode = F1AP_MODE_TDD;
|
||||
f1ap_tdd_info_t *TDDs = &req->cell_to_add[i].info.tdd;
|
||||
F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD;
|
||||
TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN;
|
||||
AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n");
|
||||
for (int f=0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) {
|
||||
struct F1AP_FreqBandNrItem * FreqItem=tDD_Info->nRFreqInfo.freqBandListNr.list.array[f];
|
||||
TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr;
|
||||
int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count;
|
||||
AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n");
|
||||
}
|
||||
TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS;
|
||||
TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB];
|
||||
} else {
|
||||
AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present);
|
||||
}
|
||||
|
||||
struct F1AP_GNB_DU_System_Information * DUsi=served_cells_item->gNB_DU_System_Information;
|
||||
// System Information
|
||||
req->cell_to_add[i].sys_info = calloc(1, sizeof(*req->cell_to_add[i].sys_info));
|
||||
AssertFatal(req->cell_to_add[i].sys_info != NULL, "out of memory\n");
|
||||
f1ap_gnb_du_system_info_t *sys_info = req->cell_to_add[i].sys_info;
|
||||
/* mib */
|
||||
sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char));
|
||||
memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size);
|
||||
sys_info->mib_length = DUsi->mIB_message.size;
|
||||
/* sib1 */
|
||||
sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char));
|
||||
memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size);
|
||||
sys_info->sib1_length = DUsi->sIB1_message.size;
|
||||
}
|
||||
}
|
||||
else {
|
||||
req->num_cells_to_add = 0;
|
||||
}
|
||||
/* 3GPP TS 38.473 Served Cells To Modify List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List, false);
|
||||
|
||||
if(ie){
|
||||
req->num_cells_to_modify = ie->value.choice.Served_Cells_To_Modify_List.list.count;
|
||||
LOG_D(F1AP, "req->num_cells_to_modify %d \n", req->num_cells_to_modify);
|
||||
|
||||
for (i=0; i<req->num_cells_to_modify; i++) {
|
||||
F1AP_Served_Cells_To_Modify_Item_t *served_cells_item = &((F1AP_Served_Cells_To_Modify_ItemIEs_t *)
|
||||
ie->value.choice.Served_Cells_To_Modify_List.list.array[i])->
|
||||
value.choice.Served_Cells_To_Modify_Item;
|
||||
|
||||
/* OLD NRCGI */
|
||||
TBCD_TO_MCC_MNC(&(served_cells_item->oldNRCGI.pLMN_Identity),
|
||||
req->cell_to_modify[i].old_plmn.mcc,
|
||||
req->cell_to_modify[i].old_plmn.mnc,
|
||||
req->cell_to_modify[i].old_plmn.mnc_digit_length);
|
||||
|
||||
BIT_STRING_TO_NR_CELL_IDENTITY(&served_cells_item->oldNRCGI.nRCellIdentity,
|
||||
req->cell_to_modify[i].old_nr_cellid);
|
||||
|
||||
|
||||
F1AP_Served_Cell_Information_t *servedCellInformation= &served_cells_item->served_Cell_Information;
|
||||
/* SERVED CELL INFORMATION*/
|
||||
/* tac */
|
||||
if (servedCellInformation->fiveGS_TAC) {
|
||||
req->cell_to_modify[i].info.tac = malloc(sizeof(*req->cell_to_modify[i].info.tac));
|
||||
AssertFatal(req->cell_to_modify[i].info.tac != NULL, "out of memory\n");
|
||||
OCTET_STRING_TO_INT16(servedCellInformation->fiveGS_TAC, *req->cell_to_modify[i].info.tac);
|
||||
LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell_to_modify[i].info.tac);
|
||||
}
|
||||
|
||||
/* - nRCGI */
|
||||
TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity),
|
||||
req->cell_to_modify[i].info.plmn.mcc,
|
||||
req->cell_to_modify[i].info.plmn.mnc,
|
||||
req->cell_to_modify[i].info.plmn.mnc_digit_length);
|
||||
// NR cellID
|
||||
BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity,
|
||||
req->cell_to_modify[i].info.nr_cellid);
|
||||
LOG_D(F1AP, "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id,
|
||||
req->cell_to_modify[i].info.plmn.mcc,
|
||||
req->cell_to_modify[i].info.plmn.mnc,
|
||||
(long long unsigned int)req->cell_to_modify[i].info.nr_cellid);
|
||||
|
||||
/* - nRPCI */
|
||||
req->cell_to_modify[i].info.nr_pci = servedCellInformation->nRPCI;
|
||||
LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell_to_modify[i].info.nr_pci);
|
||||
|
||||
// FDD Cells
|
||||
if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_fDD) {
|
||||
req->cell_to_modify[i].info.mode = F1AP_MODE_FDD;
|
||||
f1ap_fdd_info_t *FDDs = &req->cell_to_modify[i].info.fdd;
|
||||
F1AP_FDD_Info_t * fDD_Info=servedCellInformation->nR_Mode_Info.choice.fDD;
|
||||
FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN;
|
||||
AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n");
|
||||
for (int f=0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) {
|
||||
F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f];
|
||||
FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr;
|
||||
AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n");
|
||||
}
|
||||
FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN;
|
||||
int dlBands=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count;
|
||||
AssertFatal(dlBands == 0, "cannot handled more than one frequency band\n");
|
||||
for (int dlB=0; dlB < dlBands; dlB++) {
|
||||
F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB];
|
||||
FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr;
|
||||
int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count;
|
||||
AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n");
|
||||
}
|
||||
FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS;
|
||||
FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB];
|
||||
FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS;
|
||||
FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB];
|
||||
} else if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_tDD) {
|
||||
req->cell_to_modify[i].info.mode = F1AP_MODE_TDD;
|
||||
f1ap_tdd_info_t *TDDs = &req->cell_to_modify[i].info.tdd;
|
||||
F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD;
|
||||
TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN;
|
||||
AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n");
|
||||
for (int f=0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) {
|
||||
struct F1AP_FreqBandNrItem * FreqItem=tDD_Info->nRFreqInfo.freqBandListNr.list.array[f];
|
||||
TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr;
|
||||
int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count;
|
||||
AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n");
|
||||
}
|
||||
TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS;
|
||||
TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB];
|
||||
} else {
|
||||
AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present);
|
||||
}
|
||||
//TODO: Measurement Config
|
||||
|
||||
|
||||
|
||||
/*gNB DU SYSTEM INFORMATION */
|
||||
struct F1AP_GNB_DU_System_Information * DUsi=served_cells_item->gNB_DU_System_Information;
|
||||
if(DUsi!=NULL){
|
||||
// System Information
|
||||
req->cell_to_modify[i].sys_info = calloc(1, sizeof(*req->cell_to_modify[i].sys_info));
|
||||
AssertFatal(req->cell_to_modify[i].sys_info != NULL, "out of memory\n");
|
||||
f1ap_gnb_du_system_info_t *sys_info = req->cell_to_modify[i].sys_info;
|
||||
/* mib */
|
||||
sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char));
|
||||
AssertFatal(req->cell_to_modify[i].sys_info->mib != NULL, "out of memory\n");
|
||||
memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size);
|
||||
sys_info->mib_length = DUsi->mIB_message.size;
|
||||
|
||||
/* sib1 */
|
||||
sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char));
|
||||
AssertFatal(req->cell_to_modify[i].sys_info->sib1 != NULL, "out of memory\n");
|
||||
memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size);
|
||||
sys_info->sib1_length = DUsi->sIB1_message.size;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
req->num_cells_to_modify = 0;
|
||||
}
|
||||
|
||||
/* 3GPP TS 38.473 Served Cells To Delete List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List, false);
|
||||
if(ie){
|
||||
req->num_cells_to_delete = ie->value.choice.Served_Cells_To_Delete_List.list.count;
|
||||
LOG_D(F1AP, "req->num_cells_to_delete %d \n", req->num_cells_to_delete);
|
||||
|
||||
for (i=0; i<req->num_cells_to_delete; i++) {
|
||||
F1AP_Served_Cells_To_Delete_Item_t *served_cells_item = &((F1AP_Served_Cells_To_Delete_ItemIEs_t *)
|
||||
ie->value.choice.Served_Cells_To_Delete_List.list.array[i])->
|
||||
value.choice.Served_Cells_To_Delete_Item;
|
||||
/* - Old nRCGI */
|
||||
TBCD_TO_MCC_MNC(&(served_cells_item->oldNRCGI.pLMN_Identity),
|
||||
req->cell_to_delete[i].plmn.mcc,
|
||||
req->cell_to_delete[i].plmn.mnc,
|
||||
req->cell_to_delete[i].plmn.mnc_digit_length);
|
||||
// NR cellID
|
||||
BIT_STRING_TO_NR_CELL_IDENTITY(&served_cells_item->oldNRCGI.nRCellIdentity,
|
||||
req->cell_to_delete[i].nr_cellid);
|
||||
LOG_D(F1AP, "[SCTP %d] Received nRCGI to delete: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id,
|
||||
req->cell_to_delete[i].plmn.mcc,
|
||||
req->cell_to_delete[i].plmn.mnc,
|
||||
(long long unsigned int)req->cell_to_delete[i].nr_cellid);
|
||||
}
|
||||
} else {
|
||||
req->num_cells_to_delete = 0;
|
||||
}
|
||||
|
||||
/* 3GPP TS 38.473 Cells Status List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Cells_Status_List, false);
|
||||
|
||||
/* 3GPP TS 38.473 Dedicated SI Delivery Needed UE List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Dedicated_SIDelivery_NeededUE_List, false);
|
||||
|
||||
/* 3GPP TS 38.473 gNB-DU ID */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_ID, false);
|
||||
if(ie!=NULL)
|
||||
asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID,req->gNB_DU_ID);
|
||||
|
||||
/* 3GPP TS 38.473 gNB-DU TNL Association To Remove List */
|
||||
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_GNB_DU_TNL_Association_To_Remove_List, false);
|
||||
|
||||
|
||||
LOG_D(F1AP, "Sending F1AP_GNB_DU_CONFIGURATION_UPDATE ITTI message \n");
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p);
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
int CU_send_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id,
|
||||
F1AP_GNBDUConfigurationUpdateFailure_t *GNBDUConfigurationUpdateFailure) {
|
||||
f1ap_gnb_du_configuration_update_failure_t *GNBDUConfigurationUpdateFailure) {
|
||||
AssertFatal(1==0,"Not implemented yet\n");
|
||||
}
|
||||
|
||||
int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id,
|
||||
F1AP_GNBDUConfigurationUpdateAcknowledge_t *GNBDUConfigurationUpdateAcknowledge) {
|
||||
AssertFatal(1==0,"Not implemented yet\n");
|
||||
f1ap_gnb_du_configuration_update_acknowledge_t *GNBDUConfigurationUpdateAcknowledge) {
|
||||
F1AP_F1AP_PDU_t pdu = {};
|
||||
uint8_t *buffer;
|
||||
uint32_t len;
|
||||
|
||||
|
||||
/* Create */
|
||||
/* 0. Message */
|
||||
|
||||
pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu.choice.successfulOutcome, succOut);
|
||||
succOut->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate;
|
||||
succOut->criticality = F1AP_Criticality_reject;
|
||||
succOut->value.present = F1AP_SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge ;
|
||||
F1AP_GNBDUConfigurationUpdateAcknowledge_t *ack = &succOut->value.choice.GNBDUConfigurationUpdateAcknowledge;
|
||||
|
||||
/* Mandatory */
|
||||
/* Transaction Id */
|
||||
asn1cSequenceAdd(ack->protocolIEs.list, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie1);
|
||||
ie1->id = F1AP_ProtocolIE_ID_id_TransactionID;
|
||||
ie1->criticality = F1AP_Criticality_reject;
|
||||
ie1->value.present = F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID;
|
||||
ie1->value.choice.TransactionID = GNBDUConfigurationUpdateAcknowledge->transaction_id;
|
||||
|
||||
/* Todo add optional fields */
|
||||
/* encode */
|
||||
|
||||
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_DUMPMSG(F1AP, LOG_DUMP_CHAR, buffer, len, "F1AP gNB-DU CONFIGURATION UPDATE : ");
|
||||
ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu);
|
||||
f1ap_itti_send_sctp_data_req(assoc_id, buffer, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -62,10 +62,10 @@ int CU_send_F1_SETUP_FAILURE(sctp_assoc_t assoc_id, const f1ap_setup_failure_t *
|
||||
int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
|
||||
|
||||
int CU_send_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id,
|
||||
F1AP_GNBDUConfigurationUpdateFailure_t *GNBDUConfigurationUpdateFailure);
|
||||
f1ap_gnb_du_configuration_update_failure_t *GNBDUConfigurationUpdateFailure);
|
||||
|
||||
int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id,
|
||||
F1AP_GNBDUConfigurationUpdateAcknowledge_t *GNBDUConfigurationUpdateAcknowledge);
|
||||
f1ap_gnb_du_configuration_update_acknowledge_t *GNBDUConfigurationUpdateAcknowledge);
|
||||
|
||||
/*
|
||||
* gNB-CU Configuration Update
|
||||
|
||||
@@ -179,6 +179,9 @@ void *F1AP_CU_task(void *arg) {
|
||||
&F1AP_GNB_CU_CONFIGURATION_UPDATE(received_msg));
|
||||
break;
|
||||
|
||||
case F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE:
|
||||
CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(assoc_id,&F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(received_msg));
|
||||
break;
|
||||
case F1AP_DL_RRC_MESSAGE: // from rrc
|
||||
CU_send_DL_RRC_MESSAGE_TRANSFER(assoc_id,
|
||||
&F1AP_DL_RRC_MESSAGE(received_msg));
|
||||
|
||||
@@ -38,8 +38,6 @@
|
||||
|
||||
#include "rrc_extern.h"
|
||||
#include "openair2/RRC/NR/rrc_gNB_NGAP.h"
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
|
||||
static void setQos(F1AP_NonDynamic5QIDescriptor_t **toFill)
|
||||
{
|
||||
@@ -163,7 +161,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
|
||||
for (int i=0; i<1; i++) {
|
||||
asn1cSequenceAdd(ie7->value.choice.Candidate_SpCell_List.list,F1AP_Candidate_SpCell_ItemIEs_t, candidate_spCell_item_ies);
|
||||
candidate_spCell_item_ies->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_Item; // 91
|
||||
candidate_spCell_item_ies->criticality = F1AP_Criticality_reject;
|
||||
candidate_spCell_item_ies->criticality = F1AP_Criticality_ignore;
|
||||
candidate_spCell_item_ies->value.present = F1AP_Candidate_SpCell_ItemIEs__value_PR_Candidate_SpCell_Item;
|
||||
/* 7.1 Candidate_SpCell_Item */
|
||||
F1AP_Candidate_SpCell_Item_t *candidate_spCell_item=
|
||||
@@ -253,7 +251,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
|
||||
for (int i=0; i<f1ap_ue_context_setup_req->srbs_to_be_setup_length; i++) {
|
||||
asn1cSequenceAdd(ie11->value.choice.SRBs_ToBeSetup_List.list, F1AP_SRBs_ToBeSetup_ItemIEs_t, srbs_toBeSetup_item_ies);
|
||||
srbs_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item; // 73
|
||||
srbs_toBeSetup_item_ies->criticality = F1AP_Criticality_ignore;
|
||||
srbs_toBeSetup_item_ies->criticality = F1AP_Criticality_reject;
|
||||
srbs_toBeSetup_item_ies->value.present = F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item;
|
||||
/* 11.1 SRBs_ToBeSetup_Item */
|
||||
F1AP_SRBs_ToBeSetup_Item_t *srbs_toBeSetup_item=&srbs_toBeSetup_item_ies->value.choice.SRBs_ToBeSetup_Item;
|
||||
@@ -503,19 +501,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
|
||||
|
||||
/* 12.1.3 uLUPTNLInformation_ToBeSetup_List */
|
||||
for (int j = 0; j < f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) {
|
||||
/*Use a dummy teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU*/
|
||||
/* Use a dummy address and teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU */
|
||||
transport_layer_addr_t addr = { .length= 32, .buffer= { 0 } };
|
||||
f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid = newGtpuCreateTunnel(getCxt(0)->gtpInst,
|
||||
f1ap_ue_context_setup_req->gNB_CU_ue_id,
|
||||
f1ap_ue_context_setup_req->drbs_to_be_setup[i].drb_id,
|
||||
f1ap_ue_context_setup_req->drbs_to_be_setup[i].drb_id,
|
||||
0xFFFF, // We will set the right value from DU answer
|
||||
-1, // no qfi
|
||||
addr, // We will set the right value from DU answer
|
||||
f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_dl_tnl[0].port,
|
||||
cu_f1u_data_req,
|
||||
NULL);
|
||||
DevAssert(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid > 0);
|
||||
/* 12.3.1 ULTunnels_ToBeSetup_Item */
|
||||
asn1cSequenceAdd(drbs_toBeSetup_item->uLUPTNLInformation_ToBeSetup_List.list,
|
||||
F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item);
|
||||
@@ -590,7 +576,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
|
||||
if(f1ap_ue_context_setup_req->rrc_container_length > 0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie14);
|
||||
ie14->id = F1AP_ProtocolIE_ID_id_RRCContainer;
|
||||
ie14->criticality = F1AP_Criticality_reject;
|
||||
ie14->criticality = F1AP_Criticality_ignore;
|
||||
ie14->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer;
|
||||
OCTET_STRING_fromBuf(&ie14->value.choice.RRCContainer, (const char *)f1ap_ue_context_setup_req->rrc_container,
|
||||
f1ap_ue_context_setup_req->rrc_container_length);
|
||||
@@ -688,11 +674,6 @@ int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_
|
||||
F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel;
|
||||
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address);
|
||||
OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
|
||||
GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(instance)->gtpInst,
|
||||
f1ap_ue_context_setup_resp->gNB_DU_ue_id,
|
||||
(ebi_t)drbs_setup_item_p->dRBID,
|
||||
drb_p->up_dl_tnl[0].tl_address,
|
||||
drb_p->up_dl_tnl[0].teid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1569,9 +1550,6 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte
|
||||
&drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item;
|
||||
/* dRBID */
|
||||
drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id;
|
||||
newGtpuDeleteOneTunnel(getCxt(0)->gtpInst,
|
||||
f1ap_ue_context_modification_req->gNB_CU_ue_id,
|
||||
f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1644,11 +1622,6 @@ int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, sctp_assoc_t
|
||||
F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel;
|
||||
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address);
|
||||
OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
|
||||
GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(instance)->gtpInst,
|
||||
f1ap_ue_context_modification_resp->gNB_CU_ue_id,
|
||||
(ebi_t)drbs_setupmod_item_p->dRBID,
|
||||
drb_p->up_dl_tnl[0].tl_address,
|
||||
drb_p->up_dl_tnl[0].teid);
|
||||
}
|
||||
}
|
||||
// SRBs_FailedToBeSetupMod_List
|
||||
|
||||
@@ -83,12 +83,145 @@ int DU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint3
|
||||
AssertFatal(1==0,"Not implemented yet\n");
|
||||
}
|
||||
|
||||
/*
|
||||
F1 Setup
|
||||
*/
|
||||
static F1AP_Served_Cell_Information_t encode_served_cell_info(const f1ap_served_cell_info_t *c)
|
||||
{
|
||||
/* 4.1.1 served cell Information */
|
||||
F1AP_Served_Cell_Information_t scell_info = {0};
|
||||
addnRCGI(scell_info.nRCGI, c);
|
||||
|
||||
/* - nRPCI */
|
||||
scell_info.nRPCI = c->nr_pci; // int 0..1007
|
||||
|
||||
/* - fiveGS_TAC */
|
||||
if (c->tac != NULL) {
|
||||
uint32_t tac = htonl(*c->tac);
|
||||
asn1cCalloc(scell_info.fiveGS_TAC, netOrder);
|
||||
OCTET_STRING_fromBuf(netOrder, ((char *)&tac) + 1, 3);
|
||||
}
|
||||
|
||||
/* - Configured_EPS_TAC */
|
||||
if (0) {
|
||||
scell_info.configured_EPS_TAC = (F1AP_Configured_EPS_TAC_t *)calloc(1, sizeof(F1AP_Configured_EPS_TAC_t));
|
||||
OCTET_STRING_fromBuf(scell_info.configured_EPS_TAC, "2", 2);
|
||||
}
|
||||
|
||||
/* servedPLMN information */
|
||||
asn1cSequenceAdd(scell_info.servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item);
|
||||
MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity);
|
||||
|
||||
F1AP_NR_Mode_Info_t *nR_Mode_Info = &scell_info.nR_Mode_Info;
|
||||
F1AP_ProtocolExtensionContainer_10696P34_t *p = calloc(1, sizeof(*p));
|
||||
servedPLMN_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p;
|
||||
asn1cSequenceAdd(p->list, F1AP_ServedPLMNs_ItemExtIEs_t, served_plmns_itemExtIEs);
|
||||
served_plmns_itemExtIEs->criticality = F1AP_Criticality_ignore;
|
||||
served_plmns_itemExtIEs->id = F1AP_ProtocolIE_ID_id_TAISliceSupportList;
|
||||
served_plmns_itemExtIEs->extensionValue.present = F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList;
|
||||
F1AP_SliceSupportList_t *slice_support_list = &served_plmns_itemExtIEs->extensionValue.choice.SliceSupportList;
|
||||
|
||||
AssertFatal(c->num_ssi == 1, "can only encode one slice\n");
|
||||
for (int s = 0; s < c->num_ssi; s++) {
|
||||
asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice);
|
||||
INT8_TO_OCTET_STRING(c->sst, &slice->sNSSAI.sST);
|
||||
if (c->sd != 0xffffff) {
|
||||
asn1cCalloc(slice->sNSSAI.sD, tmp);
|
||||
INT24_TO_OCTET_STRING(c->sd, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (c->mode == F1AP_MODE_FDD) { // FDD
|
||||
const f1ap_fdd_info_t *fdd = &c->fdd;
|
||||
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD;
|
||||
asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info);
|
||||
/* FDD.1.1 UL NRFreqInfo ARFCN */
|
||||
fDD_Info->uL_NRFreqInfo.nRARFCN = fdd->ul_freqinfo.arfcn; // Integer
|
||||
|
||||
/* FDD.1.2 F1AP_SUL_Information */
|
||||
|
||||
/* FDD.1.3 freqBandListNr */
|
||||
int ul_band = 1;
|
||||
for (int j = 0; j < ul_band; j++) {
|
||||
asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
|
||||
/* FDD.1.3.1 freqBandIndicatorNr*/
|
||||
nr_freqBandNrItem->freqBandIndicatorNr = fdd->ul_freqinfo.band;
|
||||
|
||||
/* FDD.1.3.2 supportedSULBandList*/
|
||||
}
|
||||
|
||||
/* FDD.2.1 DL NRFreqInfo ARFCN */
|
||||
fDD_Info->dL_NRFreqInfo.nRARFCN = fdd->dl_freqinfo.arfcn; // Integer
|
||||
|
||||
/* FDD.2.2 F1AP_SUL_Information */
|
||||
|
||||
/* FDD.2.3 freqBandListNr */
|
||||
int dl_bands = 1;
|
||||
for (int j = 0; j < dl_bands; j++) {
|
||||
asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
|
||||
/* FDD.2.3.1 freqBandIndicatorNr*/
|
||||
nr_freqBandNrItem->freqBandIndicatorNr = fdd->dl_freqinfo.band;
|
||||
|
||||
/* FDD.2.3.2 supportedSULBandList*/
|
||||
} // for FDD : DL freq_Bands
|
||||
|
||||
/* FDD.3 UL Transmission Bandwidth */
|
||||
fDD_Info->uL_Transmission_Bandwidth.nRSCS = fdd->ul_tbw.scs;
|
||||
fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->ul_tbw.nrb);
|
||||
/* FDD.4 DL Transmission Bandwidth */
|
||||
fDD_Info->dL_Transmission_Bandwidth.nRSCS = fdd->dl_tbw.scs;
|
||||
fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->dl_tbw.nrb);
|
||||
} else if (c->mode == F1AP_MODE_TDD) {
|
||||
const f1ap_tdd_info_t *tdd = &c->tdd;
|
||||
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD;
|
||||
asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info);
|
||||
/* TDD.1.1 nRFreqInfo ARFCN */
|
||||
tDD_Info->nRFreqInfo.nRARFCN = tdd->freqinfo.arfcn;
|
||||
|
||||
/* TDD.1.2 F1AP_SUL_Information */
|
||||
|
||||
/* TDD.1.3 freqBandListNr */
|
||||
int bands = 1;
|
||||
for (int j = 0; j < bands; j++) {
|
||||
asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
|
||||
/* TDD.1.3.1 freqBandIndicatorNr*/
|
||||
nr_freqBandNrItem->freqBandIndicatorNr = tdd->freqinfo.band;
|
||||
/* TDD.1.3.2 supportedSULBandList*/
|
||||
}
|
||||
|
||||
/* TDD.2 transmission_Bandwidth */
|
||||
tDD_Info->transmission_Bandwidth.nRSCS = tdd->tbw.scs;
|
||||
tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(tdd->tbw.nrb);
|
||||
} else {
|
||||
AssertFatal(false, "unknown mode %d\n", c->mode);
|
||||
}
|
||||
|
||||
/* - measurementTimingConfiguration */
|
||||
char *measurementTimingConfiguration = c->measurement_timing_information;
|
||||
OCTET_STRING_fromBuf(&scell_info.measurementTimingConfiguration,
|
||||
measurementTimingConfiguration,
|
||||
strlen(measurementTimingConfiguration));
|
||||
|
||||
return scell_info;
|
||||
}
|
||||
|
||||
|
||||
static F1AP_GNB_DU_System_Information_t *encode_system_info(const f1ap_gnb_du_system_info_t *sys_info)
|
||||
{
|
||||
if (sys_info == NULL)
|
||||
return NULL; /* optional: can be NULL */
|
||||
|
||||
F1AP_GNB_DU_System_Information_t *enc_sys_info = calloc(1, sizeof(*enc_sys_info));
|
||||
AssertFatal(enc_sys_info != NULL, "out of memory\n");
|
||||
|
||||
AssertFatal(sys_info->mib != NULL, "MIB must be present in DU sys info\n");
|
||||
OCTET_STRING_fromBuf(&enc_sys_info->mIB_message, (const char *)sys_info->mib, sys_info->mib_length);
|
||||
|
||||
AssertFatal(sys_info->sib1 != NULL, "SIB1 must be present in DU sys info\n");
|
||||
OCTET_STRING_fromBuf(&enc_sys_info->sIB1_message, (const char *)sys_info->sib1, sys_info->sib1_length);
|
||||
|
||||
return enc_sys_info;
|
||||
}
|
||||
|
||||
// SETUP REQUEST
|
||||
int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_setup_req_t *setup_req)
|
||||
int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_setup_req_t *setup_req)
|
||||
{
|
||||
F1AP_F1AP_PDU_t pdu= {0};
|
||||
uint8_t *buffer;
|
||||
@@ -139,151 +272,16 @@ int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_setup_req_t *setup_req)
|
||||
for (int i=0; i<num_cells_available; i++) {
|
||||
/* mandatory */
|
||||
/* 4.1 served cells item */
|
||||
f1ap_served_cell_info_t *cell = &setup_req->cell[i].info;
|
||||
const f1ap_served_cell_info_t *cell = &setup_req->cell[i].info;
|
||||
const f1ap_gnb_du_system_info_t *sys_info = setup_req->cell[i].sys_info;
|
||||
asn1cSequenceAdd(ieCells->value.choice.GNB_DU_Served_Cells_List.list,
|
||||
F1AP_GNB_DU_Served_Cells_ItemIEs_t, duServedCell);
|
||||
duServedCell->id = F1AP_ProtocolIE_ID_id_GNB_DU_Served_Cells_Item;
|
||||
duServedCell->criticality = F1AP_Criticality_reject;
|
||||
duServedCell->value.present = F1AP_GNB_DU_Served_Cells_ItemIEs__value_PR_GNB_DU_Served_Cells_Item;
|
||||
F1AP_GNB_DU_Served_Cells_Item_t *gnb_du_served_cells_item=&duServedCell->value.choice.GNB_DU_Served_Cells_Item;
|
||||
/* 4.1.1 served cell Information */
|
||||
F1AP_Served_Cell_Information_t *served_cell_information= &gnb_du_served_cells_item->served_Cell_Information;
|
||||
addnRCGI(served_cell_information->nRCGI, cell);
|
||||
/* - nRPCI */
|
||||
served_cell_information->nRPCI = cell->nr_pci; // int 0..1007
|
||||
/* - fiveGS_TAC */
|
||||
if (cell->tac != NULL) {
|
||||
uint32_t tac=htonl(*cell->tac);
|
||||
asn1cCalloc(served_cell_information->fiveGS_TAC, netOrder);
|
||||
OCTET_STRING_fromBuf(netOrder, ((char *)&tac)+1, 3);
|
||||
}
|
||||
|
||||
/* - Configured_EPS_TAC */
|
||||
if(0) {
|
||||
served_cell_information->configured_EPS_TAC = (F1AP_Configured_EPS_TAC_t *)calloc(1, sizeof(F1AP_Configured_EPS_TAC_t));
|
||||
OCTET_STRING_fromBuf(served_cell_information->configured_EPS_TAC, "2", 2);
|
||||
}
|
||||
|
||||
/* servedPLMN information */
|
||||
asn1cSequenceAdd(served_cell_information->servedPLMNs.list, F1AP_ServedPLMNs_Item_t,servedPLMN_item);
|
||||
MCC_MNC_TO_PLMNID(cell->plmn.mcc, cell->plmn.mnc, cell->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity);
|
||||
// // /* - CHOICE NR-MODE-Info */
|
||||
F1AP_NR_Mode_Info_t *nR_Mode_Info= &served_cell_information->nR_Mode_Info;
|
||||
F1AP_ProtocolExtensionContainer_10696P34_t *p = calloc(1, sizeof(*p));
|
||||
servedPLMN_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *) p;
|
||||
asn1cSequenceAdd(p->list, F1AP_ServedPLMNs_ItemExtIEs_t , served_plmns_itemExtIEs);
|
||||
served_plmns_itemExtIEs->criticality = F1AP_Criticality_ignore;
|
||||
served_plmns_itemExtIEs->id = F1AP_ProtocolIE_ID_id_TAISliceSupportList;
|
||||
served_plmns_itemExtIEs->extensionValue.present = F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList;
|
||||
F1AP_SliceSupportList_t *slice_support_list = &served_plmns_itemExtIEs->extensionValue.choice.SliceSupportList;
|
||||
|
||||
/* get list of sst/sd from configuration file */
|
||||
paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC;
|
||||
paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0};
|
||||
char sstr[100];
|
||||
/* TODO: be sure that %d in the line below is at the right place */
|
||||
sprintf(sstr, "%s.[%d].%s.[0]", GNB_CONFIG_STRING_GNB_LIST, i, GNB_CONFIG_STRING_PLMN_LIST);
|
||||
config_getlist(config_get_if(), &SNSSAIParamList, SNSSAIParams, sizeofArray(SNSSAIParams), sstr);
|
||||
AssertFatal(SNSSAIParamList.numelt > 0, "no slice configuration found (snssaiList in the configuration file)\n");
|
||||
AssertFatal(SNSSAIParamList.numelt <= 1024, "maximum size for slice support list is 1024, see F1AP 38.473 9.3.1.37\n");
|
||||
for (int s = 0; s < SNSSAIParamList.numelt; s++) {
|
||||
uint32_t sst;
|
||||
uint32_t sd;
|
||||
bool has_sd;
|
||||
sst = *SNSSAIParamList.paramarray[s][GNB_SLICE_SERVICE_TYPE_IDX].uptr;
|
||||
has_sd = *SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr != 0xffffff;
|
||||
asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice);
|
||||
INT8_TO_OCTET_STRING(sst, &slice->sNSSAI.sST);
|
||||
if (has_sd) {
|
||||
sd = *SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr;
|
||||
asn1cCalloc(slice->sNSSAI.sD, tmp);
|
||||
INT24_TO_OCTET_STRING(sd, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (setup_req->cell[i].info.mode == F1AP_MODE_FDD) { // FDD
|
||||
const f1ap_fdd_info_t *fdd = &setup_req->cell[i].info.fdd;
|
||||
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD;
|
||||
asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info);
|
||||
/* FDD.1 UL NRFreqInfo */
|
||||
/* FDD.1.1 UL NRFreqInfo ARFCN */
|
||||
fDD_Info->uL_NRFreqInfo.nRARFCN = fdd->ul_freqinfo.arfcn; // Integer
|
||||
|
||||
/* FDD.1.2 F1AP_SUL_Information */
|
||||
|
||||
/* FDD.1.3 freqBandListNr */
|
||||
int fdd_ul_num_available_freq_Bands = 1;
|
||||
for (int fdd_ul_j=0; fdd_ul_j<fdd_ul_num_available_freq_Bands; fdd_ul_j++) {
|
||||
asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
|
||||
/* FDD.1.3.1 freqBandIndicatorNr*/
|
||||
nr_freqBandNrItem->freqBandIndicatorNr = fdd->ul_freqinfo.band;
|
||||
|
||||
/* FDD.1.3.2 supportedSULBandList*/
|
||||
} // for FDD : UL freq_Bands
|
||||
|
||||
/* FDD.2 DL NRFreqInfo */
|
||||
/* FDD.2.1 DL NRFreqInfo ARFCN */
|
||||
fDD_Info->dL_NRFreqInfo.nRARFCN = fdd->dl_freqinfo.arfcn; // Integer
|
||||
|
||||
/* FDD.2.2 F1AP_SUL_Information */
|
||||
|
||||
/* FDD.2.3 freqBandListNr */
|
||||
int fdd_dl_num_available_freq_Bands = 1;
|
||||
for (int fdd_dl_j=0; fdd_dl_j<fdd_dl_num_available_freq_Bands; fdd_dl_j++) {
|
||||
asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
|
||||
/* FDD.2.3.1 freqBandIndicatorNr*/
|
||||
nr_freqBandNrItem->freqBandIndicatorNr = fdd->dl_freqinfo.band;
|
||||
|
||||
/* FDD.2.3.2 supportedSULBandList*/
|
||||
} // for FDD : DL freq_Bands
|
||||
|
||||
/* FDD.3 UL Transmission Bandwidth */
|
||||
fDD_Info->uL_Transmission_Bandwidth.nRSCS = fdd->ul_tbw.scs;
|
||||
fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->ul_tbw.nrb);
|
||||
/* FDD.4 DL Transmission Bandwidth */
|
||||
fDD_Info->dL_Transmission_Bandwidth.nRSCS = fdd->dl_tbw.scs;
|
||||
fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->dl_tbw.nrb);
|
||||
} else if (setup_req->cell[i].info.mode == F1AP_MODE_TDD) { // TDD
|
||||
const f1ap_tdd_info_t *tdd = &setup_req->cell[i].info.tdd;
|
||||
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD;
|
||||
asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info);
|
||||
/* TDD.1 nRFreqInfo */
|
||||
/* TDD.1.1 nRFreqInfo ARFCN */
|
||||
tDD_Info->nRFreqInfo.nRARFCN = tdd->freqinfo.arfcn; // Integer
|
||||
|
||||
/* TDD.1.2 F1AP_SUL_Information */
|
||||
|
||||
/* TDD.1.3 freqBandListNr */
|
||||
int tdd_num_available_freq_Bands = 1;
|
||||
for (int j=0; j<tdd_num_available_freq_Bands; j++) {
|
||||
asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
|
||||
/* TDD.1.3.1 freqBandIndicatorNr*/
|
||||
nr_freqBandNrItem->freqBandIndicatorNr = tdd->freqinfo.band;
|
||||
/* TDD.1.3.2 supportedSULBandList*/
|
||||
} // for TDD : freq_Bands
|
||||
|
||||
/* TDD.2 transmission_Bandwidth */
|
||||
tDD_Info->transmission_Bandwidth.nRSCS = tdd->tbw.scs;
|
||||
tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(tdd->tbw.nrb);
|
||||
} else {
|
||||
AssertFatal(false, "unknown mode %d\n", setup_req->cell[i].info.mode);
|
||||
}
|
||||
|
||||
/* - measurementTimingConfiguration */
|
||||
char *measurementTimingConfiguration = cell->measurement_timing_information; // sept. 2018
|
||||
OCTET_STRING_fromBuf(&served_cell_information->measurementTimingConfiguration,
|
||||
measurementTimingConfiguration,
|
||||
strlen(measurementTimingConfiguration));
|
||||
|
||||
/* 4.1.2 gNB-DU System Information */
|
||||
if (setup_req->cell[i].sys_info != NULL) {
|
||||
asn1cCalloc(gnb_du_served_cells_item->gNB_DU_System_Information, gNB_DU_System_Information);
|
||||
const f1ap_gnb_du_system_info_t *sys_info = setup_req->cell[i].sys_info;
|
||||
AssertFatal(sys_info->mib != NULL, "MIB must be present in DU sys info\n");
|
||||
OCTET_STRING_fromBuf(&gNB_DU_System_Information->mIB_message, (const char *)sys_info->mib, sys_info->mib_length);
|
||||
AssertFatal(sys_info->sib1 != NULL, "SIB1 must be present in DU sys info\n");
|
||||
OCTET_STRING_fromBuf(&gNB_DU_System_Information->sIB1_message, (const char *)sys_info->sib1, sys_info->sib1_length);
|
||||
}
|
||||
F1AP_GNB_DU_Served_Cells_Item_t *scell_item = &duServedCell->value.choice.GNB_DU_Served_Cells_Item;
|
||||
scell_item->served_Cell_Information = encode_served_cell_info(cell);
|
||||
scell_item->gNB_DU_System_Information = encode_system_info(sys_info);
|
||||
}
|
||||
|
||||
/* mandatory */
|
||||
@@ -534,7 +532,7 @@ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint3
|
||||
gNB-DU Configuration Update
|
||||
*/
|
||||
|
||||
int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_setup_req_t *f1ap_setup_req)
|
||||
int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_t *upd)
|
||||
{
|
||||
F1AP_F1AP_PDU_t pdu= {0};
|
||||
uint8_t *buffer=NULL;
|
||||
@@ -546,227 +544,91 @@ int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_setup_req_t
|
||||
initMsg->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate;
|
||||
initMsg->criticality = F1AP_Criticality_reject;
|
||||
initMsg->value.present = F1AP_InitiatingMessage__value_PR_GNBDUConfigurationUpdate;
|
||||
F1AP_GNBDUConfigurationUpdate_t *out = &pdu.choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate;
|
||||
F1AP_GNBDUConfigurationUpdate_t *out = &initMsg->value.choice.GNBDUConfigurationUpdate;
|
||||
|
||||
/* mandatory */
|
||||
/* c1. Transaction ID (integer value) */
|
||||
asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie1);
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie1);
|
||||
ie1->id = F1AP_ProtocolIE_ID_id_TransactionID;
|
||||
ie1->criticality = F1AP_Criticality_reject;
|
||||
ie1->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_TransactionID;
|
||||
ie1->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0);
|
||||
ie1->value.choice.TransactionID = upd->transaction_id;
|
||||
|
||||
/* mandatory */
|
||||
/* c2. Served_Cells_To_Add */
|
||||
asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie2);
|
||||
ie2->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List;
|
||||
ie2->criticality = F1AP_Criticality_reject;
|
||||
ie2->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Add_List;
|
||||
if (upd->num_cells_to_add > 0) {
|
||||
AssertFatal(false, "code for adding cells not tested\n");
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie2);
|
||||
ie2->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List;
|
||||
ie2->criticality = F1AP_Criticality_reject;
|
||||
ie2->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Add_List;
|
||||
|
||||
for (int j=0; j<1; j++) {
|
||||
//
|
||||
asn1cSequenceAdd(ie2->value.choice.Served_Cells_To_Add_List.list, F1AP_Served_Cells_To_Add_ItemIEs_t, served_cells_to_add_item_ies);
|
||||
served_cells_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_Item;
|
||||
served_cells_to_add_item_ies->criticality = F1AP_Criticality_reject;
|
||||
served_cells_to_add_item_ies->value.present = F1AP_Served_Cells_To_Add_ItemIEs__value_PR_Served_Cells_To_Add_Item;
|
||||
F1AP_Served_Cells_To_Add_Item_t *served_cells_to_add_item= &served_cells_to_add_item_ies->value.choice.Served_Cells_To_Add_Item;
|
||||
F1AP_Served_Cell_Information_t *served_cell_information=&served_cells_to_add_item->served_Cell_Information;
|
||||
/* - nRCGI */
|
||||
addnRCGI(served_cell_information->nRCGI, &f1ap_setup_req->cell[j].info);
|
||||
/* - nRPCI */
|
||||
/* 2.1.1 serverd cell Information */
|
||||
f1ap_served_cell_info_t *cell = &f1ap_setup_req->cell[j].info;
|
||||
served_cell_information->nRPCI = cell->nr_pci; // int 0..1007
|
||||
/* - fiveGS_TAC */
|
||||
if (cell->tac != NULL) {
|
||||
uint32_t tac = htonl(*cell->tac);
|
||||
served_cell_information->fiveGS_TAC = calloc(1, sizeof(*served_cell_information->fiveGS_TAC));
|
||||
OCTET_STRING_fromBuf(served_cell_information->fiveGS_TAC, ((char *)&tac)+1, 3);
|
||||
for (int j=0; j < upd->num_cells_to_add; j++) {
|
||||
const f1ap_served_cell_info_t *cell = &upd->cell_to_add[j].info;
|
||||
const f1ap_gnb_du_system_info_t *sys_info = upd->cell_to_add[j].sys_info;
|
||||
asn1cSequenceAdd(ie2->value.choice.Served_Cells_To_Add_List.list, F1AP_Served_Cells_To_Add_ItemIEs_t, served_cells_to_add_item_ies);
|
||||
served_cells_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_Item;
|
||||
served_cells_to_add_item_ies->criticality = F1AP_Criticality_reject;
|
||||
served_cells_to_add_item_ies->value.present = F1AP_Served_Cells_To_Add_ItemIEs__value_PR_Served_Cells_To_Add_Item;
|
||||
F1AP_Served_Cells_To_Add_Item_t *served_cells_to_add_item= &served_cells_to_add_item_ies->value.choice.Served_Cells_To_Add_Item;
|
||||
served_cells_to_add_item->served_Cell_Information = encode_served_cell_info(cell);
|
||||
served_cells_to_add_item->gNB_DU_System_Information = encode_system_info(sys_info);
|
||||
}
|
||||
|
||||
/* - Configured_EPS_TAC */
|
||||
if(1) {
|
||||
served_cell_information->configured_EPS_TAC = (F1AP_Configured_EPS_TAC_t *)calloc(1, sizeof(F1AP_Configured_EPS_TAC_t));
|
||||
OCTET_STRING_fromBuf(served_cell_information->configured_EPS_TAC,"2", 2);
|
||||
}
|
||||
|
||||
asn1cSequenceAdd(served_cell_information->servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item);
|
||||
MCC_MNC_TO_PLMNID(cell->plmn.mcc, cell->plmn.mnc, cell->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity);
|
||||
// // /* - CHOICE NR-MODE-Info */
|
||||
F1AP_NR_Mode_Info_t *nR_Mode_Info=&served_cell_information->nR_Mode_Info;
|
||||
LOG_E(F1AP,"Here hardcoded values instead of values from configuration file\n");
|
||||
|
||||
if (cell->mode == F1AP_MODE_FDD) {
|
||||
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD;
|
||||
/* > FDD >> FDD Info */
|
||||
asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info);
|
||||
/* >>> UL NRFreqInfo */
|
||||
fDD_Info->uL_NRFreqInfo.nRARFCN = 999L;
|
||||
asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, ul_freqBandNrItem);
|
||||
ul_freqBandNrItem->freqBandIndicatorNr = 888L;
|
||||
asn1cSequenceAdd(ul_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, ul_supportedSULFreqBandItem);
|
||||
ul_supportedSULFreqBandItem->freqBandIndicatorNr = 777L;
|
||||
/* >>> DL NRFreqInfo */
|
||||
fDD_Info->dL_NRFreqInfo.nRARFCN = 666L;
|
||||
asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, dl_freqBandNrItem);
|
||||
dl_freqBandNrItem->freqBandIndicatorNr = 555L;
|
||||
asn1cSequenceAdd(dl_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, dl_supportedSULFreqBandItem);
|
||||
dl_supportedSULFreqBandItem->freqBandIndicatorNr = 444L;
|
||||
/* >>> UL Transmission Bandwidth */
|
||||
fDD_Info->uL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15;
|
||||
fDD_Info->uL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11;
|
||||
/* >>> DL Transmission Bandwidth */
|
||||
fDD_Info->dL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15;
|
||||
fDD_Info->dL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11;
|
||||
} else if (cell->mode == F1AP_MODE_TDD) { // TDD
|
||||
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD;
|
||||
/* > TDD >> TDD Info */
|
||||
asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info);
|
||||
/* >>> ARFCN */
|
||||
tDD_Info->nRFreqInfo.nRARFCN = 999L; // Integer
|
||||
asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
|
||||
nr_freqBandNrItem->freqBandIndicatorNr = 555L;
|
||||
asn1cSequenceAdd(nr_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, nr_supportedSULFreqBandItem);
|
||||
nr_supportedSULFreqBandItem->freqBandIndicatorNr = 444L;
|
||||
tDD_Info->transmission_Bandwidth.nRSCS= F1AP_NRSCS_scs15;
|
||||
tDD_Info->transmission_Bandwidth.nRNRB= F1AP_NRNRB_nrb11;
|
||||
} else {
|
||||
AssertFatal(false, "illegal mode %d\n", cell->mode);
|
||||
}
|
||||
|
||||
/* - measurementTimingConfiguration */
|
||||
char *measurementTimingConfiguration = "0"; // sept. 2018
|
||||
OCTET_STRING_fromBuf(&served_cell_information->measurementTimingConfiguration,
|
||||
measurementTimingConfiguration,
|
||||
strlen(measurementTimingConfiguration));
|
||||
/* 2.1.2 gNB-DU System Information */
|
||||
asn1cCalloc(served_cells_to_add_item->gNB_DU_System_Information, gNB_DU_System_Information);
|
||||
OCTET_STRING_fromBuf(&gNB_DU_System_Information->mIB_message, // sept. 2018
|
||||
"1",
|
||||
sizeof("1"));
|
||||
OCTET_STRING_fromBuf(&gNB_DU_System_Information->sIB1_message, // sept. 2018
|
||||
"1",
|
||||
sizeof("1"));
|
||||
}
|
||||
|
||||
/* mandatory */
|
||||
/* c3. Served_Cells_To_Modify */
|
||||
asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie3);
|
||||
ie3->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List;
|
||||
ie3->criticality = F1AP_Criticality_reject;
|
||||
ie3->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Modify_List;
|
||||
if (upd->num_cells_to_modify > 0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie3);
|
||||
ie3->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List;
|
||||
ie3->criticality = F1AP_Criticality_reject;
|
||||
ie3->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Modify_List;
|
||||
for (int i = 0; i < upd->num_cells_to_modify; i++) {
|
||||
const f1ap_served_cell_info_t *cell = &upd->cell_to_modify[i].info;
|
||||
const f1ap_gnb_du_system_info_t *sys_info = upd->cell_to_modify[i].sys_info;
|
||||
asn1cSequenceAdd(ie3->value.choice.Served_Cells_To_Modify_List.list, F1AP_Served_Cells_To_Modify_ItemIEs_t, served_cells_to_modify_item_ies);
|
||||
served_cells_to_modify_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_Item;
|
||||
served_cells_to_modify_item_ies->criticality = F1AP_Criticality_reject;
|
||||
served_cells_to_modify_item_ies->value.present = F1AP_Served_Cells_To_Modify_ItemIEs__value_PR_Served_Cells_To_Modify_Item;
|
||||
F1AP_Served_Cells_To_Modify_Item_t *served_cells_to_modify_item=&served_cells_to_modify_item_ies->value.choice.Served_Cells_To_Modify_Item;
|
||||
|
||||
for (int i=0; i<1; i++) {
|
||||
//
|
||||
f1ap_served_cell_info_t *cell = &f1ap_setup_req->cell[i].info;
|
||||
asn1cSequenceAdd(ie3->value.choice.Served_Cells_To_Modify_List.list, F1AP_Served_Cells_To_Modify_ItemIEs_t, served_cells_to_modify_item_ies);
|
||||
served_cells_to_modify_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_Item;
|
||||
served_cells_to_modify_item_ies->criticality = F1AP_Criticality_reject;
|
||||
served_cells_to_modify_item_ies->value.present = F1AP_Served_Cells_To_Modify_ItemIEs__value_PR_Served_Cells_To_Modify_Item;
|
||||
F1AP_Served_Cells_To_Modify_Item_t *served_cells_to_modify_item=&served_cells_to_modify_item_ies->value.choice.Served_Cells_To_Modify_Item;
|
||||
/* 3.1 oldNRCGI */
|
||||
//addnRGCI(served_cells_to_modify_item->oldNRCGI, f1ap_setup_req->cell[i]);
|
||||
/* 3.2.1 serverd cell Information */
|
||||
F1AP_Served_Cell_Information_t *served_cell_information= &served_cells_to_modify_item->served_Cell_Information;
|
||||
/* - nRCGI */
|
||||
//addnRGCI(served_cell_information->nRCGI,f1ap_setup_req->cell[i]);
|
||||
/* - nRPCI */
|
||||
served_cell_information->nRPCI = cell->nr_pci; // int 0..1007
|
||||
/* - fiveGS_TAC */
|
||||
asn1cCalloc(served_cell_information->fiveGS_TAC, tac );
|
||||
OCTET_STRING_fromBuf(tac,
|
||||
(const char *) &cell->tac,
|
||||
3);
|
||||
F1AP_NRCGI_t *oldNRCGI = &served_cells_to_modify_item->oldNRCGI;
|
||||
const f1ap_plmn_t *old_plmn = &upd->cell_to_modify[i].old_plmn;
|
||||
MCC_MNC_TO_PLMNID(old_plmn->mcc, old_plmn->mnc, old_plmn->mnc_digit_length, &oldNRCGI->pLMN_Identity);
|
||||
NR_CELL_ID_TO_BIT_STRING(upd->cell_to_modify[i].old_nr_cellid, &oldNRCGI->nRCellIdentity);
|
||||
|
||||
/* - Configured_EPS_TAC */
|
||||
if(1) {
|
||||
asn1cCalloc(served_cell_information->configured_EPS_TAC, tmp2);
|
||||
OCTET_STRING_fromBuf(tmp2,
|
||||
"2",
|
||||
2);
|
||||
served_cells_to_modify_item->served_Cell_Information = encode_served_cell_info(cell);
|
||||
served_cells_to_modify_item->gNB_DU_System_Information = encode_system_info(sys_info);
|
||||
}
|
||||
|
||||
asn1cSequenceAdd(served_cell_information->servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item);
|
||||
MCC_MNC_TO_PLMNID(cell->plmn.mcc, cell->plmn.mnc, cell->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity);
|
||||
// // /* - CHOICE NR-MODE-Info */
|
||||
F1AP_NR_Mode_Info_t *nR_Mode_Info= &served_cell_information->nR_Mode_Info;
|
||||
|
||||
if (cell->mode == F1AP_MODE_FDD) {
|
||||
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD;
|
||||
/* > FDD >> FDD Info */
|
||||
asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info);
|
||||
/* >>> UL NRFreqInfo */
|
||||
fDD_Info->uL_NRFreqInfo.nRARFCN = 999L;
|
||||
asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, ul_freqBandNrItem);
|
||||
ul_freqBandNrItem->freqBandIndicatorNr = 888L;
|
||||
asn1cSequenceAdd(ul_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, ul_supportedSULFreqBandItem);
|
||||
ul_supportedSULFreqBandItem->freqBandIndicatorNr = 777L;
|
||||
/* >>> DL NRFreqInfo */
|
||||
fDD_Info->dL_NRFreqInfo.nRARFCN = 666L;
|
||||
asn1cSequenceAdd(dl_freqBandNrItem->supportedSULBandList.list, F1AP_FreqBandNrItem_t, dl_freqBandNrItem);
|
||||
dl_freqBandNrItem->freqBandIndicatorNr = 555L;
|
||||
F1AP_SupportedSULFreqBandItem_t dl_supportedSULFreqBandItem;
|
||||
memset((void *)&dl_supportedSULFreqBandItem, 0, sizeof(F1AP_SupportedSULFreqBandItem_t));
|
||||
dl_supportedSULFreqBandItem.freqBandIndicatorNr = 444L;
|
||||
/* >>> UL Transmission Bandwidth */
|
||||
fDD_Info->uL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15;
|
||||
fDD_Info->uL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11;
|
||||
/* >>> DL Transmission Bandwidth */
|
||||
fDD_Info->dL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15;
|
||||
fDD_Info->dL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11;
|
||||
} else if (cell->mode == F1AP_MODE_TDD) { // TDD
|
||||
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD;
|
||||
/* > TDD >> TDD Info */
|
||||
asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info);
|
||||
/* >>> ARFCN */
|
||||
tDD_Info->nRFreqInfo.nRARFCN = 999L; // Integer
|
||||
asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
|
||||
nr_freqBandNrItem->freqBandIndicatorNr = 555L;
|
||||
asn1cSequenceAdd(nr_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, nr_supportedSULFreqBandItem);
|
||||
nr_supportedSULFreqBandItem->freqBandIndicatorNr = 444L;
|
||||
tDD_Info->transmission_Bandwidth.nRSCS= F1AP_NRSCS_scs15;
|
||||
tDD_Info->transmission_Bandwidth.nRNRB= F1AP_NRNRB_nrb11;
|
||||
} else {
|
||||
AssertFatal(false, "unknown mode %d\n", cell->mode);
|
||||
}
|
||||
|
||||
/* - measurementTimingConfiguration */
|
||||
char *measurementTimingConfiguration = "0"; // sept. 2018
|
||||
OCTET_STRING_fromBuf(&served_cell_information->measurementTimingConfiguration,
|
||||
measurementTimingConfiguration,
|
||||
strlen(measurementTimingConfiguration));
|
||||
/* 3.2.2 gNB-DU System Information */
|
||||
asn1cCalloc( served_cells_to_modify_item->gNB_DU_System_Information, gNB_DU_System_Information);
|
||||
OCTET_STRING_fromBuf(&gNB_DU_System_Information->mIB_message, // sept. 2018
|
||||
"1",
|
||||
sizeof("1"));
|
||||
OCTET_STRING_fromBuf(&gNB_DU_System_Information->sIB1_message, // sept. 2018
|
||||
"1",
|
||||
sizeof("1"));
|
||||
}
|
||||
|
||||
/* mandatory */
|
||||
/* c4. Served_Cells_To_Delete */
|
||||
asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie4);
|
||||
ie4->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List;
|
||||
ie4->criticality = F1AP_Criticality_reject;
|
||||
ie4->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Delete_List;
|
||||
|
||||
for (int i=0; i<1; i++) {
|
||||
//
|
||||
asn1cSequenceAdd(ie4->value.choice.Served_Cells_To_Delete_List.list, F1AP_Served_Cells_To_Delete_ItemIEs_t, served_cells_to_delete_item_ies);
|
||||
served_cells_to_delete_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_Item;
|
||||
served_cells_to_delete_item_ies->criticality = F1AP_Criticality_reject;
|
||||
served_cells_to_delete_item_ies->value.present = F1AP_Served_Cells_To_Delete_ItemIEs__value_PR_Served_Cells_To_Delete_Item;
|
||||
F1AP_Served_Cells_To_Delete_Item_t *served_cells_to_delete_item=&served_cells_to_delete_item_ies->value.choice.Served_Cells_To_Delete_Item;
|
||||
/* 3.1 oldNRCGI */
|
||||
addnRCGI(served_cells_to_delete_item->oldNRCGI, &f1ap_setup_req->cell[i].info);
|
||||
if (upd->num_cells_to_delete > 0) {
|
||||
asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie4);
|
||||
ie4->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List;
|
||||
ie4->criticality = F1AP_Criticality_reject;
|
||||
ie4->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Delete_List;
|
||||
AssertFatal(upd->num_cells_to_delete == 0, "code for deleting cells not tested\n");
|
||||
for (int i=0; i<upd->num_cells_to_delete; i++) {
|
||||
asn1cSequenceAdd(ie4->value.choice.Served_Cells_To_Delete_List.list, F1AP_Served_Cells_To_Delete_ItemIEs_t, served_cells_to_delete_item_ies);
|
||||
served_cells_to_delete_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_Item;
|
||||
served_cells_to_delete_item_ies->criticality = F1AP_Criticality_reject;
|
||||
served_cells_to_delete_item_ies->value.present = F1AP_Served_Cells_To_Delete_ItemIEs__value_PR_Served_Cells_To_Delete_Item;
|
||||
F1AP_Served_Cells_To_Delete_Item_t *served_cells_to_delete_item=&served_cells_to_delete_item_ies->value.choice.Served_Cells_To_Delete_Item;
|
||||
addnRCGI(served_cells_to_delete_item->oldNRCGI, &upd->cell_to_delete[i]);
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(upd->gNB_DU_ID == 0, "encoding of gNB-DU Id not handled yet\n");
|
||||
|
||||
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu);
|
||||
f1ap_itti_send_sctp_data_req(assoc_id, buffer, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ int DU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint3
|
||||
/*
|
||||
* F1 Setup
|
||||
*/
|
||||
int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_setup_req_t *setup_req);
|
||||
int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_setup_req_t *setup_req);
|
||||
|
||||
int DU_handle_F1_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
|
||||
|
||||
@@ -59,8 +59,7 @@ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint3
|
||||
/*
|
||||
* gNB-DU Configuration Update
|
||||
*/
|
||||
int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id,
|
||||
f1ap_setup_req_t *f1ap_du_data);
|
||||
int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_t *upd);
|
||||
|
||||
int DU_handle_gNB_DU_CONFIGURATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
|
||||
|
||||
|
||||
@@ -212,6 +212,8 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, const f1ap_in
|
||||
}
|
||||
|
||||
f1ap_itti_send_sctp_data_req(assoc_id, buffer, len);
|
||||
free(msg->rrc_container);
|
||||
free(tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,9 +34,10 @@
|
||||
#ifndef F1AP_DU_RRC_MESSAGE_TRANSFER_H_
|
||||
#define F1AP_DU_RRC_MESSAGE_TRANSFER_H_
|
||||
|
||||
#include "f1ap_common.h"
|
||||
#include <openair2/RRC/NR/MESSAGES/asn1_msg.h>
|
||||
|
||||
int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
|
||||
struct F1AP_F1AP_PDU;
|
||||
int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, struct F1AP_F1AP_PDU *pdu);
|
||||
|
||||
int DU_send_UL_NR_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, const f1ap_ul_rrc_message_t *msg);
|
||||
|
||||
|
||||
@@ -170,6 +170,10 @@ void *F1AP_DU_task(void *arg) {
|
||||
DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(assoc_id, &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg));
|
||||
break;
|
||||
|
||||
case F1AP_GNB_DU_CONFIGURATION_UPDATE:
|
||||
DU_send_gNB_DU_CONFIGURATION_UPDATE(assoc_id, &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg));
|
||||
break;
|
||||
|
||||
case TERMINATE_MESSAGE:
|
||||
LOG_W(F1AP, " *** Exiting F1AP thread\n");
|
||||
itti_exit_task();
|
||||
|
||||
@@ -40,24 +40,6 @@
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
|
||||
bool DURecvCb(protocol_ctxt_t *ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const mui_t muiP,
|
||||
const confirm_t confirmP,
|
||||
const sdu_size_t sdu_buffer_sizeP,
|
||||
unsigned char *const sdu_buffer_pP,
|
||||
const pdcp_transmission_mode_t modeP,
|
||||
const uint32_t *sourceL2Id,
|
||||
const uint32_t *destinationL2Id)
|
||||
{
|
||||
// The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue
|
||||
uint8_t *sdu = malloc16(sdu_buffer_sizeP);
|
||||
memcpy(sdu, sdu_buffer_pP, sdu_buffer_sizeP);
|
||||
du_rlc_data_req(ctxt_pP, srb_flagP, false, rb_idP, muiP, confirmP, sdu_buffer_sizeP, sdu);
|
||||
return true;
|
||||
}
|
||||
|
||||
int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
|
||||
{
|
||||
F1AP_UEContextSetupRequest_t *container;
|
||||
@@ -159,6 +141,22 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i
|
||||
drb_p->rlc_mode = RLC_MODE_TM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (drbs_tobesetup_item_p->qoSInformation.present == F1AP_QoSInformation_PR_choice_extension) {
|
||||
F1AP_QoSInformation_ExtIEs_t *ie =
|
||||
(F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetup_item_p->qoSInformation.choice.choice_extension;
|
||||
if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject
|
||||
&& ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) {
|
||||
F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information;
|
||||
|
||||
/* S-NSSAI */
|
||||
OCTET_STRING_TO_INT8(&dRB_Info->sNSSAI.sST, drb_p->nssai.sst);
|
||||
if (dRB_Info->sNSSAI.sD != NULL)
|
||||
memcpy((uint8_t *)&drb_p->nssai.sd, dRB_Info->sNSSAI.sD->buf, 3);
|
||||
else
|
||||
drb_p->nssai.sd = 0xffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,6 +303,7 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
|
||||
ie7->criticality = F1AP_Criticality_ignore;
|
||||
ie7->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List;
|
||||
for (int i=0; i< resp->drbs_to_be_setup_length; i++) {
|
||||
f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i];
|
||||
//
|
||||
asn1cSequenceAdd(ie7->value.choice.DRBs_Setup_List.list,
|
||||
F1AP_DRBs_Setup_ItemIEs_t, drbs_setup_item_ies);
|
||||
@@ -315,14 +314,17 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
|
||||
/* ADD */
|
||||
F1AP_DRBs_Setup_Item_t *drbs_setup_item=&drbs_setup_item_ies->value.choice.DRBs_Setup_Item;
|
||||
/* dRBID */
|
||||
drbs_setup_item->dRBID = resp->drbs_to_be_setup[i].drb_id;
|
||||
drbs_setup_item->dRBID = drb->drb_id;
|
||||
|
||||
/* OPTIONAL */
|
||||
/* lCID */
|
||||
//drbs_setup_item.lCID = (F1AP_LCID_t *)calloc(1, sizeof(F1AP_LCID_t));
|
||||
//drbs_setup_item.lCID = 1L;
|
||||
|
||||
for (int j=0; j<resp->drbs_to_be_setup[i].up_dl_tnl_length; j++) {
|
||||
for (int j=0; j<drb->up_dl_tnl_length; j++) {
|
||||
const f1ap_up_tnl_t *tnl = &drb->up_dl_tnl[j];
|
||||
DevAssert(tnl->teid > 0);
|
||||
|
||||
/* ADD */
|
||||
asn1cSequenceAdd(drbs_setup_item->dLUPTNLInformation_ToBeSetup_List.list,
|
||||
F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item);
|
||||
@@ -330,12 +332,9 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
|
||||
/* gTPTunnel */
|
||||
asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel);
|
||||
/* transportLayerAddress */
|
||||
struct sockaddr_in addr= {0};
|
||||
inet_pton(AF_INET, getCxt(0)->net_config.DU_f1_ip_address.ipv4_address, &addr.sin_addr.s_addr);
|
||||
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(addr.sin_addr.s_addr,
|
||||
&gTPTunnel->transportLayerAddress);
|
||||
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress);
|
||||
/* gTP_TEID */
|
||||
INT32_TO_OCTET_STRING(resp->drbs_to_be_setup[i].up_dl_tnl[j].teid, &gTPTunnel->gTP_TEID);
|
||||
INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID);
|
||||
} // for j
|
||||
} // for i
|
||||
|
||||
@@ -1008,7 +1007,6 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t
|
||||
DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item);
|
||||
DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item);
|
||||
f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID;
|
||||
newGtpuDeleteOneTunnel(0, f1ap_ue_context_modification_req->gNB_DU_ue_id, f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1166,20 +1164,8 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_cont
|
||||
drbs_setupmod_item->dRBID = resp->drbs_to_be_setup[i].drb_id;
|
||||
|
||||
for (int j=0; j<resp->drbs_to_be_setup[i].up_dl_tnl_length; j++) {
|
||||
f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i];
|
||||
transport_layer_addr_t tl_addr = {0};
|
||||
memcpy(tl_addr.buffer, &drb->up_ul_tnl[0].tl_address, sizeof(drb->up_ul_tnl[0].tl_address));
|
||||
tl_addr.length = sizeof(drb->up_ul_tnl[0].tl_address) * 8;
|
||||
drb->up_dl_tnl[j].teid = newGtpuCreateTunnel(getCxt(0)->gtpInst,
|
||||
resp->gNB_DU_ue_id,
|
||||
drb->drb_id,
|
||||
drb->drb_id,
|
||||
drb->up_ul_tnl[j].teid,
|
||||
-1, // no qfi
|
||||
tl_addr,
|
||||
drb->up_ul_tnl[0].port,
|
||||
DURecvCb,
|
||||
NULL);
|
||||
const f1ap_up_tnl_t *tnl = &resp->drbs_to_be_setup[i].up_dl_tnl[j];
|
||||
DevAssert(tnl->teid > 0);
|
||||
|
||||
/* ADD */
|
||||
asn1cSequenceAdd(drbs_setupmod_item->dLUPTNLInformation_ToBeSetup_List.list,
|
||||
@@ -1188,12 +1174,9 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_cont
|
||||
/* gTPTunnel */
|
||||
asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel);
|
||||
/* transportLayerAddress */
|
||||
struct sockaddr_in addr= {0};
|
||||
inet_pton(AF_INET, getCxt(0)->net_config.DU_f1_ip_address.ipv4_address, &addr.sin_addr.s_addr);
|
||||
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(addr.sin_addr.s_addr,
|
||||
&gTPTunnel->transportLayerAddress);
|
||||
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress);
|
||||
/* gTP_TEID */
|
||||
INT32_TO_OCTET_STRING(resp->drbs_to_be_setup[i].up_dl_tnl[j].teid, &gTPTunnel->gTP_TEID);
|
||||
INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID);
|
||||
} // for j
|
||||
} // for i
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ static const f1ap_message_processing_t f1ap_messages_processing[][3] = {
|
||||
{0, 0, 0}, /* Reset */
|
||||
{CU_handle_F1_SETUP_REQUEST, DU_handle_F1_SETUP_RESPONSE, DU_handle_F1_SETUP_FAILURE}, /* F1Setup */
|
||||
{0, 0, 0}, /* ErrorIndication */
|
||||
{0, 0, 0}, /* gNBDUConfigurationUpdate */
|
||||
{CU_handle_gNB_DU_CONFIGURATION_UPDATE, 0, 0}, /* gNBDUConfigurationUpdate */
|
||||
{DU_handle_gNB_CU_CONFIGURATION_UPDATE,
|
||||
CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE,
|
||||
CU_handle_gNB_CU_CONFIGURATION_UPDATE_FAILURE}, /* gNBCUConfigurationUpdate */
|
||||
|
||||
@@ -37,8 +37,8 @@ static pthread_mutex_t cu2du_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
void cu_init_f1_ue_data(void)
|
||||
{
|
||||
pthread_mutex_lock(&cu2du_mutex);
|
||||
DevAssert(cu2du_ue_mapping == NULL);
|
||||
cu2du_ue_mapping = hashtable_create(1319, NULL, free); // 1319 is prime, default hash func (unit), free()
|
||||
if (cu2du_ue_mapping == NULL) // hack: there is nothing to free this properly
|
||||
cu2du_ue_mapping = hashtable_create(1319, NULL, free); // 1319 is prime, default hash func (unit), free()
|
||||
DevAssert(cu2du_ue_mapping != NULL);
|
||||
pthread_mutex_unlock(&cu2du_mutex);
|
||||
}
|
||||
|
||||
@@ -1097,13 +1097,74 @@ static int read_du_cell_info(configmodule_interface_t *cfg,
|
||||
info->plmn.mnc_digit_length);
|
||||
info->nr_cellid = (uint64_t) * (GNBParamList.paramarray[0][GNB_NRCELLID_IDX].u64ptr);
|
||||
|
||||
LOG_W(GNB_APP, "no slices transported via F1 Setup Request!\n");
|
||||
info->num_ssi = 0;
|
||||
info->num_ssi = 1;
|
||||
paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC;
|
||||
checkedparam_t config_check_SNSSAIParams[] = SNSSAIPARAMS_CHECK;
|
||||
for (int J = 0; J < sizeof(SNSSAIParams) / sizeof(paramdef_t); ++J)
|
||||
SNSSAIParams[J].chkPptr = &(config_check_SNSSAIParams[J]);
|
||||
paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0};
|
||||
char snssaistr[MAX_OPTNAME_SIZE * 2 + 8];
|
||||
sprintf(snssaistr, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_PLMN_LIST, 0);
|
||||
config_getlist(config_get_if(), &SNSSAIParamList, SNSSAIParams, sizeof(SNSSAIParams) / sizeof(paramdef_t), snssaistr);
|
||||
AssertFatal(SNSSAIParamList.numelt == 1, "cannot handle no NSSAI or more than 1\n");
|
||||
info->sst = *SNSSAIParamList.paramarray[0][GNB_SLICE_SERVICE_TYPE_IDX].uptr;
|
||||
info->sd = *SNSSAIParamList.paramarray[0][GNB_SLICE_DIFFERENTIATOR_IDX].uptr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
|
||||
f1ap_tdd_info_t read_tdd_config(const NR_ServingCellConfigCommon_t *scc)
|
||||
{
|
||||
const NR_FrequencyInfoDL_t *dl = scc->downlinkConfigCommon->frequencyInfoDL;
|
||||
f1ap_tdd_info_t tdd = {
|
||||
.freqinfo.arfcn = dl->absoluteFrequencyPointA,
|
||||
.freqinfo.band = *dl->frequencyBandList.list.array[0],
|
||||
.tbw.scs = dl->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
|
||||
.tbw.nrb = dl->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,
|
||||
};
|
||||
return tdd;
|
||||
}
|
||||
|
||||
static f1ap_fdd_info_t read_fdd_config(const NR_ServingCellConfigCommon_t *scc)
|
||||
{
|
||||
const NR_FrequencyInfoDL_t *dl = scc->downlinkConfigCommon->frequencyInfoDL;
|
||||
const NR_FrequencyInfoUL_t *ul = scc->uplinkConfigCommon->frequencyInfoUL;
|
||||
f1ap_fdd_info_t fdd = {
|
||||
.dl_freqinfo.arfcn = dl->absoluteFrequencyPointA,
|
||||
.ul_freqinfo.arfcn = *ul->absoluteFrequencyPointA,
|
||||
.dl_tbw.scs = dl->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
|
||||
.ul_tbw.scs = ul->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
|
||||
.dl_tbw.nrb = dl->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,
|
||||
.ul_tbw.nrb = ul->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,
|
||||
.dl_freqinfo.band = *dl->frequencyBandList.list.array[0],
|
||||
.ul_freqinfo.band = *ul->frequencyBandList->list.array[0],
|
||||
};
|
||||
return fdd;
|
||||
}
|
||||
|
||||
f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1)
|
||||
{
|
||||
int buf_len = 3;
|
||||
f1ap_gnb_du_system_info_t *sys_info = calloc(1, sizeof(*sys_info));
|
||||
AssertFatal(sys_info != NULL, "out of memory\n");
|
||||
|
||||
sys_info->mib = calloc(buf_len, sizeof(*sys_info->mib));
|
||||
DevAssert(sys_info->mib != NULL);
|
||||
DevAssert(mib != NULL);
|
||||
sys_info->mib_length = encode_MIB_NR(mib, 0, sys_info->mib, buf_len);
|
||||
DevAssert(sys_info->mib_length == buf_len);
|
||||
|
||||
DevAssert(sib1 != NULL);
|
||||
NR_SIB1_t *bcch_SIB1 = sib1->message.choice.c1->choice.systemInformationBlockType1;
|
||||
sys_info->sib1 = calloc(NR_MAX_SIB_LENGTH / 8, sizeof(*sys_info->sib1));
|
||||
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_SIB1, NULL, (void *)bcch_SIB1, sys_info->sib1, NR_MAX_SIB_LENGTH / 8);
|
||||
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
|
||||
sys_info->sib1_length = (enc_rval.encoded + 7) / 8;
|
||||
|
||||
return sys_info;
|
||||
}
|
||||
|
||||
f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
|
||||
const char *name,
|
||||
const f1ap_served_cell_info_t *info,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
@@ -1128,27 +1189,14 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
|
||||
req->cell[0].info.nr_cellid);
|
||||
|
||||
req->cell[0].info.nr_pci = *scc->physCellId;
|
||||
struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
|
||||
if (scc->tdd_UL_DL_ConfigurationCommon) {
|
||||
LOG_I(GNB_APP, "ngran_DU: Configuring Cell %d for TDD\n", 0);
|
||||
req->cell[0].info.mode = F1AP_MODE_TDD;
|
||||
f1ap_tdd_info_t *tdd = &req->cell[0].info.tdd;
|
||||
tdd->freqinfo.arfcn = frequencyInfoDL->absoluteFrequencyPointA;
|
||||
tdd->tbw.scs = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
tdd->tbw.nrb = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
|
||||
tdd->freqinfo.band = *frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
req->cell[0].info.tdd = read_tdd_config(scc);
|
||||
} else {
|
||||
LOG_I(GNB_APP, "ngran_DU: Configuring Cell %d for FDD\n", 0);
|
||||
req->cell[0].info.mode = F1AP_MODE_FDD;
|
||||
f1ap_fdd_info_t *fdd = &req->cell[0].info.fdd;
|
||||
fdd->dl_freqinfo.arfcn = frequencyInfoDL->absoluteFrequencyPointA;
|
||||
fdd->ul_freqinfo.arfcn = *scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA;
|
||||
fdd->dl_tbw.scs = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
fdd->ul_tbw.scs = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
fdd->dl_tbw.nrb = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
|
||||
fdd->ul_tbw.nrb = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
|
||||
fdd->dl_freqinfo.band = *frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
fdd->ul_freqinfo.band = *scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0];
|
||||
req->cell[0].info.fdd = read_fdd_config(scc);
|
||||
}
|
||||
|
||||
req->cell[0].info.measurement_timing_information = "0";
|
||||
@@ -1157,22 +1205,7 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
|
||||
// in NSA we don't transmit SIB1, so cannot fill DU system information
|
||||
// so cannot send MIB either
|
||||
|
||||
int buf_len = 3; // this is what we assume in monolithic
|
||||
req->cell[0].sys_info = calloc(1, sizeof(*req->cell[0].sys_info));
|
||||
AssertFatal(req->cell[0].sys_info != NULL, "out of memory\n");
|
||||
f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info;
|
||||
sys_info->mib = calloc(buf_len, sizeof(*sys_info->mib));
|
||||
DevAssert(sys_info->mib != NULL);
|
||||
DevAssert(mib != NULL);
|
||||
sys_info->mib_length = encode_MIB_NR(mib, 0, sys_info->mib, buf_len);
|
||||
DevAssert(sys_info->mib_length == buf_len);
|
||||
|
||||
DevAssert(sib1 != NULL);
|
||||
NR_SIB1_t *bcch_SIB1 = sib1->message.choice.c1->choice.systemInformationBlockType1;
|
||||
sys_info->sib1 = calloc(NR_MAX_SIB_LENGTH / 8, sizeof(*sys_info->sib1));
|
||||
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_SIB1, NULL, (void *)bcch_SIB1, sys_info->sib1, NR_MAX_SIB_LENGTH / 8);
|
||||
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
|
||||
sys_info->sib1_length = (enc_rval.encoded + 7) / 8;
|
||||
req->cell[0].sys_info = get_sys_info(mib, sib1);
|
||||
}
|
||||
|
||||
int num = read_version(TO_STRING(NR_RRC_VERSION), &req->rrc_ver[0], &req->rrc_ver[1], &req->rrc_ver[2]);
|
||||
@@ -1569,7 +1602,6 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
|
||||
sprintf(aprefix,"%s.[%u].%s",GNB_CONFIG_STRING_GNB_LIST,i,GNB_CONFIG_STRING_SCTP_CONFIG);
|
||||
config_get(config_get_if(), SCTPParams, sizeofArray(SCTPParams), aprefix);
|
||||
LOG_I(GNB_APP,"F1AP: gNB_CU_id[%d] %d\n",k,rrc->node_id);
|
||||
rrc->node_name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr));
|
||||
LOG_I(GNB_APP,"F1AP: gNB_CU_name[%d] %s\n",k,rrc->node_name);
|
||||
rrc->eth_params_s.local_if_name = strdup(*(GNBParamList.paramarray[i][GNB_LOCAL_S_IF_NAME_IDX].strptr));
|
||||
rrc->eth_params_s.my_addr = strdup(*(GNBParamList.paramarray[i][GNB_LOCAL_S_ADDRESS_IDX].strptr));
|
||||
@@ -1583,6 +1615,7 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
|
||||
|
||||
|
||||
|
||||
rrc->node_name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr));
|
||||
rrc->nr_cellid = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr);
|
||||
|
||||
if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_mac") == 0) {
|
||||
@@ -1644,6 +1677,17 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
|
||||
AssertFatal((nrrrc_config.mnc_digit_length[l] == 2) ||
|
||||
(nrrrc_config.mnc_digit_length[l] == 3),"BAD MNC DIGIT LENGTH %d",
|
||||
nrrrc_config.mnc_digit_length[l]);
|
||||
paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC;
|
||||
checkedparam_t config_check_SNSSAIParams[] = SNSSAIPARAMS_CHECK;
|
||||
for (int J = 0; J < sizeof(SNSSAIParams) / sizeof(paramdef_t); ++J)
|
||||
SNSSAIParams[J].chkPptr = &(config_check_SNSSAIParams[J]);
|
||||
paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0};
|
||||
char snssaistr[MAX_OPTNAME_SIZE * 2 + 8];
|
||||
sprintf(snssaistr, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k, GNB_CONFIG_STRING_PLMN_LIST, l);
|
||||
config_getlist(config_get_if(), &SNSSAIParamList, SNSSAIParams, sizeof(SNSSAIParams) / sizeof(paramdef_t), snssaistr);
|
||||
AssertFatal(SNSSAIParamList.numelt == 1, "cannot handle no NSSAI or more than 1\n");
|
||||
nrrrc_config.sst = *SNSSAIParamList.paramarray[0][GNB_SLICE_SERVICE_TYPE_IDX].uptr;
|
||||
nrrrc_config.sd = *SNSSAIParamList.paramarray[0][GNB_SLICE_DIFFERENTIATOR_IDX].uptr;
|
||||
}
|
||||
nrrrc_config.enable_sdap = *GNBParamList.paramarray[i][GNB_ENABLE_SDAP_IDX].iptr;
|
||||
LOG_I(GNB_APP, "SDAP layer is %s\n", nrrrc_config.enable_sdap ? "enabled" : "disabled");
|
||||
|
||||
@@ -106,6 +106,12 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc);
|
||||
int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i);
|
||||
int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i);
|
||||
void wait_f1_setup_response(void);
|
||||
f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
|
||||
const char *name,
|
||||
const f1ap_served_cell_info_t *info,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
NR_BCCH_BCH_Message_t *mib,
|
||||
const NR_BCCH_DL_SCH_Message_t *sib1);
|
||||
int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update);
|
||||
MessageDef *RCconfig_NR_CU_E1(const E1_t *entity);
|
||||
ngran_node_t get_node_type(void);
|
||||
|
||||
@@ -370,10 +370,12 @@ static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddMo
|
||||
if (rlc_bearer2release_list) {
|
||||
for (int i = 0; i < rlc_bearer2release_list->list.count; i++) {
|
||||
for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) {
|
||||
if (sched_ctrl->dl_lc_ids[idx] == *rlc_bearer2release_list->list.array[i]) {
|
||||
const int lcid = *rlc_bearer2release_list->list.array[i];
|
||||
if (sched_ctrl->dl_lc_ids[idx] == lcid) {
|
||||
const int remaining_lcs = sched_ctrl->dl_lc_num - idx - 1;
|
||||
memmove(&sched_ctrl->dl_lc_ids[idx], &sched_ctrl->dl_lc_ids[idx + 1], sizeof(sched_ctrl->dl_lc_ids[idx]) * remaining_lcs);
|
||||
sched_ctrl->dl_lc_num--;
|
||||
LOG_I(NR_MAC, "remove LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -383,7 +385,7 @@ static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddMo
|
||||
if (rlc_bearer2add_list) {
|
||||
// keep lcids
|
||||
for (int i = 0; i < rlc_bearer2add_list->list.count; i++) {
|
||||
const int lcid = rlc_bearer2add_list->list.array[i]->logicalChannelIdentity;
|
||||
const uint8_t lcid = rlc_bearer2add_list->list.array[i]->logicalChannelIdentity;
|
||||
bool found = false;
|
||||
for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) {
|
||||
if (sched_ctrl->dl_lc_ids[idx] == lcid) {
|
||||
@@ -393,9 +395,19 @@ static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddMo
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
/* we assume that the first two are SRB bearers, and we add before
|
||||
* other DRB */
|
||||
uint8_t i = 0;
|
||||
/* go beyond all SRBs */
|
||||
while (i < sched_ctrl->dl_lc_num && sched_ctrl->dl_lc_ids[i] < 4)
|
||||
i++;
|
||||
uint8_t remaining_lcs = sched_ctrl->dl_lc_num - i;
|
||||
memmove(&sched_ctrl->dl_lc_ids[i + 1], &sched_ctrl->dl_lc_ids[i], sizeof(sched_ctrl->dl_lc_ids[i]) * remaining_lcs);
|
||||
sched_ctrl->dl_lc_ids[i] = lcid;
|
||||
|
||||
sched_ctrl->dl_lc_num++;
|
||||
sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num - 1] = lcid;
|
||||
LOG_D(NR_MAC, "Adding LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid);
|
||||
|
||||
LOG_I(NR_MAC, "Adding LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1683,7 +1683,8 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
|
||||
NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti);
|
||||
if (!UE) {
|
||||
LOG_E(NR_MAC, "want to generate Msg4, but rnti %04x not in the table\n", ra->rnti);
|
||||
LOG_E(NR_MAC, "want to generate Msg4, but rnti %04x not found. Abort RA\n", ra->rnti);
|
||||
nr_clear_ra_proc(0, 0, frameP, ra);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1936,7 +1937,7 @@ static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, s
|
||||
LOG_A(NR_MAC, "(UE RNTI 0x%04x) Received Ack of RA-Msg4. CBRA procedure succeeded!\n", ra->rnti);
|
||||
} else {
|
||||
LOG_I(NR_MAC, "%4d.%2d UE %04x: RA Procedure failed at Msg4!\n", frame, slot, ra->rnti);
|
||||
nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs);
|
||||
nr_mac_trigger_ul_failure(UE->rnti);
|
||||
}
|
||||
|
||||
// Pause scheduling according to:
|
||||
|
||||
@@ -330,7 +330,7 @@ static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_fram
|
||||
const int lcid = sched_ctrl->dl_lc_ids[i];
|
||||
const uint16_t rnti = UE->rnti;
|
||||
LOG_D(NR_MAC, "In %s: UE %x: LCID %d\n", __FUNCTION__, rnti, lcid);
|
||||
if (lcid == DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) {
|
||||
if (lcid >= DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) {
|
||||
continue;
|
||||
}
|
||||
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
||||
@@ -936,6 +936,9 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
NR_UEs_t *UE_info = &gNB_mac->UE_info;
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
|
||||
|
||||
const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
|
||||
gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE);
|
||||
|
||||
UE_iterator(UE_info->list, UE) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP;
|
||||
@@ -1237,6 +1240,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti),
|
||||
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock, TBS));
|
||||
UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize;
|
||||
gNB_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize;
|
||||
} else { /* initial transmission */
|
||||
LOG_D(NR_MAC, "Initial HARQ transmission in %d.%d\n", frame, slot);
|
||||
uint8_t *buf = (uint8_t *) harq->transportBlock;
|
||||
@@ -1353,6 +1357,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
UE->mac_stats.dl.num_mac_sdu += sdus;
|
||||
UE->mac_stats.dl.current_rbs = sched_pdsch->rbSize;
|
||||
UE->mac_stats.dl.total_sdu_bytes += dlsch_total_bytes;
|
||||
gNB_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize;
|
||||
|
||||
/* save retransmission information */
|
||||
harq->sched_pdsch = *sched_pdsch;
|
||||
|
||||
@@ -3064,15 +3064,22 @@ bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti)
|
||||
return sched_ctrl->release_timer == 0;
|
||||
}
|
||||
|
||||
void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing)
|
||||
void nr_mac_trigger_ul_failure(int rnti)
|
||||
{
|
||||
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti);
|
||||
if (UE == NULL) {
|
||||
LOG_E(NR_MAC, "could not find UE RNTI %04x\n", rnti);
|
||||
return;
|
||||
}
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
if (sched_ctrl->ul_failure) {
|
||||
/* already running */
|
||||
return;
|
||||
}
|
||||
sched_ctrl->ul_failure = true;
|
||||
// 30 seconds till triggering release request
|
||||
sched_ctrl->ul_failure_timer = 30000 << subcarrier_spacing;
|
||||
NR_SubcarrierSpacing_t subcarrier_spacing = UE->current_DL_BWP.scs;
|
||||
sched_ctrl->ul_failure_timer = 5000 << subcarrier_spacing;
|
||||
}
|
||||
|
||||
void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl)
|
||||
@@ -3097,7 +3104,7 @@ void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ct
|
||||
.gNB_CU_ue_id = ue_data.secondary_ue,
|
||||
.gNB_DU_ue_id = rnti,
|
||||
.cause = F1AP_CAUSE_RADIO_NETWORK,
|
||||
.cause_value = F1AP_CauseRadioNetwork_rl_failure_others,
|
||||
.cause_value = F1AP_CauseRadioNetwork_rl_failure_rlc,
|
||||
};
|
||||
nrmac->mac_rrc.ue_context_release_request(&request);
|
||||
}
|
||||
|
||||
@@ -680,7 +680,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
"UE %04x: Detected UL Failure on PUSCH after %d PUSCH DTX, stopping scheduling\n",
|
||||
UE->rnti,
|
||||
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt);
|
||||
nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
|
||||
nr_mac_trigger_ul_failure(UE->rnti);
|
||||
}
|
||||
}
|
||||
} else if(sduP) {
|
||||
|
||||
@@ -442,7 +442,7 @@ void nr_mac_trigger_release_timer(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierS
|
||||
bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti);
|
||||
void nr_mac_release_ue(gNB_MAC_INST *mac, int rnti);
|
||||
|
||||
void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing);
|
||||
void nr_mac_trigger_ul_failure(int rnti);
|
||||
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);
|
||||
|
||||
|
||||
@@ -23,8 +23,11 @@
|
||||
|
||||
#include "mac_proto.h"
|
||||
#include "openair2/F1AP/f1ap_ids.h"
|
||||
#include "openair2/F1AP/f1ap_common.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
#include "F1AP_CauseRadioNetwork.h"
|
||||
#include "openair3/ocp-gtpu/gtp_itf.h"
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
|
||||
#include "uper_decoder.h"
|
||||
#include "uper_encoder.h"
|
||||
@@ -34,6 +37,59 @@ const uint64_t qos_fiveqi[26] = {1, 2, 3, 4, 65, 66, 67, 71, 72, 73, 74, 76, 5,
|
||||
const uint64_t qos_priority[26] = {20, 40, 30, 50, 7, 20, 15, 56, 56, 56, 56, 56, 10,
|
||||
60, 70, 80, 90, 5, 55, 65, 68, 19, 22, 24, 21, 18};
|
||||
|
||||
static instance_t get_f1_gtp_instance(void)
|
||||
{
|
||||
const f1ap_cudu_inst_t *inst = getCxt(0);
|
||||
if (!inst)
|
||||
return -1; // means no F1
|
||||
return inst->gtpInst;
|
||||
}
|
||||
|
||||
static int drb_gtpu_create(instance_t instance,
|
||||
uint32_t ue_id,
|
||||
int incoming_id,
|
||||
int outgoing_id,
|
||||
int qfi,
|
||||
in_addr_t tlAddress, // only IPv4 now
|
||||
teid_t outgoing_teid,
|
||||
gtpCallback callBack,
|
||||
gtpCallbackSDAP callBackSDAP,
|
||||
gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp)
|
||||
{
|
||||
gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0};
|
||||
create_tunnel_req.incoming_rb_id[0] = incoming_id;
|
||||
create_tunnel_req.pdusession_id[0] = outgoing_id;
|
||||
memcpy(&create_tunnel_req.dst_addr[0].buffer, &tlAddress, sizeof(uint8_t) * 4);
|
||||
create_tunnel_req.dst_addr[0].length = 32;
|
||||
create_tunnel_req.outgoing_teid[0] = outgoing_teid;
|
||||
create_tunnel_req.outgoing_qfi[0] = qfi;
|
||||
create_tunnel_req.num_tunnels = 1;
|
||||
create_tunnel_req.ue_id = ue_id;
|
||||
|
||||
// we use gtpv1u_create_ngu_tunnel because it returns the interface
|
||||
// address and port of the interface; apart from that, we also might call
|
||||
// newGtpuCreateTunnel() directly
|
||||
return gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, create_tunnel_resp, callBack, callBackSDAP);
|
||||
}
|
||||
|
||||
bool DURecvCb(protocol_ctxt_t *ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const mui_t muiP,
|
||||
const confirm_t confirmP,
|
||||
const sdu_size_t sdu_buffer_sizeP,
|
||||
unsigned char *const sdu_buffer_pP,
|
||||
const pdcp_transmission_mode_t modeP,
|
||||
const uint32_t *sourceL2Id,
|
||||
const uint32_t *destinationL2Id)
|
||||
{
|
||||
// The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue
|
||||
uint8_t *sdu = malloc16(sdu_buffer_sizeP);
|
||||
memcpy(sdu, sdu_buffer_pP, sdu_buffer_sizeP);
|
||||
du_rlc_data_req(ctxt_pP, srb_flagP, false, rb_idP, muiP, confirmP, sdu_buffer_sizeP, sdu);
|
||||
return true;
|
||||
}
|
||||
|
||||
static long get_lcid_from_drbid(int drb_id)
|
||||
{
|
||||
return drb_id + 3; /* LCID is DRB + 3 */
|
||||
@@ -88,6 +144,12 @@ void f1_setup_failure(const f1ap_setup_failure_t *failure)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *ack)
|
||||
{
|
||||
(void) ack;
|
||||
LOG_I(MAC, "received gNB-DU configuration update acknowledge\n");
|
||||
}
|
||||
|
||||
static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_setup_t *srb)
|
||||
{
|
||||
long priority = srb->srb_id; // high priority for SRB
|
||||
@@ -133,6 +195,7 @@ static int handle_ue_context_drbs_setup(int rnti,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
{
|
||||
DevAssert(req_drbs != NULL && resp_drbs != NULL && cellGroupConfig != NULL);
|
||||
instance_t f1inst = get_f1_gtp_instance();
|
||||
|
||||
/* Note: the actual GTP tunnels are created in the F1AP breanch of
|
||||
* ue_context_*_response() */
|
||||
@@ -140,12 +203,32 @@ static int handle_ue_context_drbs_setup(int rnti,
|
||||
AssertFatal(*resp_drbs != NULL, "out of memory\n");
|
||||
for (int i = 0; i < drbs_len; i++) {
|
||||
const f1ap_drb_to_be_setup_t *drb = &req_drbs[i];
|
||||
f1ap_drb_to_be_setup_t *resp_drb = &(*resp_drbs)[i];
|
||||
NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb);
|
||||
nr_rlc_add_drb(rnti, drb->drb_id, rlc_BearerConfig);
|
||||
|
||||
(*resp_drbs)[i] = *drb;
|
||||
*resp_drb = *drb;
|
||||
// just put same number of tunnels in DL as in UL
|
||||
(*resp_drbs)[i].up_dl_tnl_length = drb->up_ul_tnl_length;
|
||||
DevAssert(drb->up_ul_tnl_length == 1);
|
||||
resp_drb->up_dl_tnl_length = drb->up_ul_tnl_length;
|
||||
|
||||
if (f1inst >= 0) { // we actually use F1-U
|
||||
int qfi = -1; // don't put PDU session marker in GTP
|
||||
gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0};
|
||||
int ret = drb_gtpu_create(f1inst,
|
||||
rnti,
|
||||
drb->drb_id,
|
||||
drb->drb_id,
|
||||
qfi,
|
||||
drb->up_ul_tnl[0].tl_address,
|
||||
drb->up_ul_tnl[0].teid,
|
||||
DURecvCb,
|
||||
NULL,
|
||||
&resp_f1);
|
||||
AssertFatal(ret >= 0, "Unable to create GTP Tunnel for F1-U\n");
|
||||
memcpy(&resp_drb->up_dl_tnl[0].tl_address, &resp_f1.gnb_addr.buffer, 4);
|
||||
resp_drb->up_dl_tnl[0].teid = resp_f1.gnb_NGu_teid[0];
|
||||
}
|
||||
|
||||
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
|
||||
DevAssert(ret == 0);
|
||||
@@ -159,6 +242,7 @@ static int handle_ue_context_drbs_release(int rnti,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
{
|
||||
DevAssert(req_drbs != NULL && cellGroupConfig != NULL);
|
||||
instance_t f1inst = get_f1_gtp_instance();
|
||||
|
||||
cellGroupConfig->rlc_BearerToReleaseList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToReleaseList));
|
||||
AssertFatal(cellGroupConfig->rlc_BearerToReleaseList != NULL, "out of memory\n");
|
||||
@@ -178,6 +262,8 @@ static int handle_ue_context_drbs_release(int rnti,
|
||||
}
|
||||
if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) {
|
||||
nr_rlc_release_entity(rnti, lcid);
|
||||
if (f1inst >= 0)
|
||||
newGtpuDeleteOneTunnel(f1inst, rnti, drb->rb_id);
|
||||
asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1);
|
||||
long *plcid = malloc(sizeof(*plcid));
|
||||
AssertFatal(plcid != NULL, "out of memory\n");
|
||||
@@ -552,6 +638,10 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
instance_t f1inst = get_f1_gtp_instance();
|
||||
if (f1inst >= 0)
|
||||
newGtpuDeleteAllTunnels(f1inst, cmd->gNB_DU_ue_id);
|
||||
|
||||
if (UE->UE_sched_ctrl.ul_failure || cmd->rrc_container_length == 0) {
|
||||
/* The UE is already not connected anymore or we have nothing to forward*/
|
||||
nr_mac_release_ue(mac, cmd->gNB_DU_ue_id);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
void f1_setup_response(const f1ap_setup_resp_t *resp);
|
||||
void f1_setup_failure(const f1ap_setup_failure_t *failure);
|
||||
void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *ack);
|
||||
NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig);
|
||||
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);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "f1ap_messages_types.h"
|
||||
|
||||
typedef void (*f1_setup_request_func_t)(const f1ap_setup_req_t* req);
|
||||
typedef void (*gnb_du_configuration_update_t)(const f1ap_gnb_du_configuration_update_t *upd);
|
||||
|
||||
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,
|
||||
|
||||
@@ -66,6 +66,51 @@ static void f1_setup_request_direct(const f1ap_setup_req_t *req)
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
|
||||
}
|
||||
|
||||
static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_update_t *upd)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE);
|
||||
msg->ittiMsgHeader.originInstance = -1; // means monolithic
|
||||
f1ap_gnb_du_configuration_update_t *f1ap_msg = &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg);
|
||||
DevAssert(upd->gNB_DU_ID == NULL);
|
||||
f1ap_msg->transaction_id = upd->transaction_id;
|
||||
DevAssert(upd->num_cells_to_add == 0);
|
||||
DevAssert(upd->num_cells_to_delete == 0);
|
||||
|
||||
f1ap_msg->num_cells_to_modify = upd->num_cells_to_modify;
|
||||
for (int n = 0; n < upd->num_cells_to_modify; ++n) {
|
||||
f1ap_msg->cell_to_modify[n].old_nr_cellid = upd->cell_to_modify[n].old_nr_cellid;
|
||||
f1ap_msg->cell_to_modify[n].info = upd->cell_to_modify[n].info; // copy most fields
|
||||
if (upd->cell_to_modify[n].info.tac) {
|
||||
f1ap_msg->cell_to_modify[n].info.tac = malloc(sizeof(*f1ap_msg->cell_to_modify[n].info.tac));
|
||||
AssertFatal(f1ap_msg->cell_to_modify[n].info.tac != NULL, "out of memory\n");
|
||||
*f1ap_msg->cell_to_modify[n].info.tac = *upd->cell_to_modify[n].info.tac;
|
||||
}
|
||||
if (upd->cell_to_modify[n].info.measurement_timing_information)
|
||||
f1ap_msg->cell_to_modify[n].info.measurement_timing_information = strdup(upd->cell_to_modify[n].info.measurement_timing_information);
|
||||
|
||||
if (upd->cell_to_modify[n].sys_info) {
|
||||
f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info;
|
||||
f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info));
|
||||
AssertFatal(copy_sys_info != NULL, "out of memory\n");
|
||||
f1ap_msg->cell_to_modify[n].sys_info = copy_sys_info;
|
||||
|
||||
copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t));
|
||||
AssertFatal(copy_sys_info->mib != NULL, "out of memory\n");
|
||||
memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length);
|
||||
copy_sys_info->mib_length = orig_sys_info->mib_length;
|
||||
|
||||
if (orig_sys_info->sib1_length > 0) {
|
||||
copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t));
|
||||
AssertFatal(copy_sys_info->sib1 != NULL, "out of memory\n");
|
||||
memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length);
|
||||
copy_sys_info->sib1_length = orig_sys_info->sib1_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp)
|
||||
{
|
||||
DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length);
|
||||
@@ -227,6 +272,7 @@ static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const
|
||||
void mac_rrc_ul_direct_init(struct nr_mac_rrc_ul_if_s *mac_rrc)
|
||||
{
|
||||
mac_rrc->f1_setup_request = f1_setup_request_direct;
|
||||
mac_rrc->gnb_du_configuration_update = gnb_du_configuration_update_direct;
|
||||
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;
|
||||
|
||||
@@ -100,6 +100,39 @@ static void f1_setup_request_f1ap(const f1ap_setup_req_t *req)
|
||||
itti_send_msg_to_task(TASK_DU_F1, 0, msg);
|
||||
}
|
||||
|
||||
static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_update_t *upd)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE);
|
||||
f1ap_gnb_du_configuration_update_t *f1_upd = &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg);
|
||||
f1_upd->transaction_id = upd->transaction_id;
|
||||
AssertFatal(upd->num_cells_to_add == 0, "gNB-DU config update: cells to add not supported\n");
|
||||
f1_upd->num_cells_to_modify = upd->num_cells_to_modify;
|
||||
for (int n = 0; n < upd->num_cells_to_modify; ++n) {
|
||||
f1_upd->cell_to_modify[n].old_plmn = upd->cell_to_modify[n].old_plmn;
|
||||
f1_upd->cell_to_modify[n].old_nr_cellid = upd->cell_to_modify[n].old_nr_cellid;
|
||||
f1_upd->cell_to_modify[n].info = upd->cell_to_modify[n].info;
|
||||
if (upd->cell_to_modify[n].sys_info) {
|
||||
f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info;
|
||||
f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info));
|
||||
f1_upd->cell_to_modify[n].sys_info = copy_sys_info;
|
||||
|
||||
copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t));
|
||||
AssertFatal(copy_sys_info->mib != NULL, "out of memory\n");
|
||||
memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length);
|
||||
copy_sys_info->mib_length = orig_sys_info->mib_length;
|
||||
|
||||
if (orig_sys_info->sib1_length > 0) {
|
||||
copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t));
|
||||
AssertFatal(copy_sys_info->sib1 != NULL, "out of memory\n");
|
||||
memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length);
|
||||
copy_sys_info->sib1_length = orig_sys_info->sib1_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
AssertFatal(upd->num_cells_to_delete == 0, "gNB-DU config update: cells to add not supported\n");
|
||||
itti_send_msg_to_task(TASK_DU_F1, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp)
|
||||
{
|
||||
DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length);
|
||||
@@ -239,6 +272,7 @@ static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1
|
||||
void mac_rrc_ul_f1ap_init(struct nr_mac_rrc_ul_if_s *mac_rrc)
|
||||
{
|
||||
mac_rrc->f1_setup_request = f1_setup_request_f1ap;
|
||||
mac_rrc->gnb_du_configuration_update = gnb_du_configuration_update_f1ap;
|
||||
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;
|
||||
|
||||
@@ -684,6 +684,7 @@ typedef struct NR_bler_options {
|
||||
|
||||
typedef struct nr_mac_rrc_ul_if_s {
|
||||
f1_setup_request_func_t f1_setup_request;
|
||||
gnb_du_configuration_update_t gnb_du_configuration_update;
|
||||
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;
|
||||
@@ -743,6 +744,11 @@ typedef struct f1_config_t {
|
||||
uint32_t gnb_id; // associated gNB's ID, not used in DU itself
|
||||
} f1_config_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t total_prb_aggregate;
|
||||
uint64_t used_prb_aggregate;
|
||||
} mac_stats_t;
|
||||
|
||||
/*! \brief top level eNB MAC structure */
|
||||
typedef struct gNB_MAC_INST_s {
|
||||
/// Ethernet parameters for northbound midhaul interface
|
||||
@@ -862,6 +868,8 @@ typedef struct gNB_MAC_INST_s {
|
||||
|
||||
pthread_mutex_t sched_lock;
|
||||
|
||||
mac_stats_t mac_stats;
|
||||
|
||||
} gNB_MAC_INST;
|
||||
|
||||
#endif /*__LAYER2_NR_MAC_GNB_H__ */
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "openair2/E1AP/e1ap_common.h"
|
||||
#include "openair2/F1AP/f1ap_common.h"
|
||||
|
||||
static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const pdu_session_to_setup_t *pdu)
|
||||
void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const pdu_session_to_setup_t *pdu)
|
||||
{
|
||||
for (int i=0; i < pdu->numDRB2Setup; i++) {
|
||||
const DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i;
|
||||
@@ -90,7 +90,7 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const
|
||||
}
|
||||
}
|
||||
|
||||
static int drb_gtpu_create(instance_t instance,
|
||||
int drb_gtpu_create(instance_t instance,
|
||||
uint32_t ue_id,
|
||||
int incoming_id,
|
||||
int outgoing_id,
|
||||
@@ -124,7 +124,7 @@ static instance_t get_n3_gtp_instance(void)
|
||||
return inst->gtpInstN3;
|
||||
}
|
||||
|
||||
static instance_t get_f1_gtp_instance(void)
|
||||
instance_t get_f1_gtp_instance(void)
|
||||
{
|
||||
const f1ap_cudu_inst_t *inst = getCxt(0);
|
||||
if (!inst)
|
||||
|
||||
@@ -1194,6 +1194,12 @@ void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id)
|
||||
drb->delete_entity(drb);
|
||||
ue->drb[drb_id - 1] = NULL;
|
||||
LOG_I(PDCP, "release DRB %d of UE %ld\n", drb_id, ue_id);
|
||||
int sessionId = 1;
|
||||
nr_sdap_entity_t *sdap = nr_sdap_get_entity(ue_id, sessionId); /* default */
|
||||
if (sdap == NULL)
|
||||
LOG_E(PDCP, "no SDAP entity for UE %ld PDU session ID %d\n", ue_id, sessionId);
|
||||
else
|
||||
sdap->has_second_bearer = 0;
|
||||
}
|
||||
else
|
||||
LOG_E(PDCP, "Attempting to release DRB%d but it is not configured\n", drb_id);
|
||||
|
||||
@@ -1765,7 +1765,7 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
/* log SDUs rejected, at most once per second */
|
||||
if (entity->sdu_rejected != 0
|
||||
&& entity->t_current > entity->t_log_buffer_full + 1000) {
|
||||
LOG_E(RLC, "%s:%d:%s: warning: %d SDU rejected, SDU buffer full\n",
|
||||
LOG_W(RLC, "%s:%d:%s: warning: %d SDU rejected, SDU buffer full\n",
|
||||
__FILE__, __LINE__, __FUNCTION__,
|
||||
entity->sdu_rejected);
|
||||
entity->sdu_rejected = 0;
|
||||
|
||||
@@ -78,14 +78,15 @@ static int generate_tx_pdu(nr_rlc_entity_tm_t *entity, char *buffer, int size)
|
||||
entity->tx_size -= sdu->size;
|
||||
entity->common.stats.txpdu_pkts++;
|
||||
entity->common.stats.txpdu_bytes += size;
|
||||
|
||||
/* No need to 'zero' time-of-arrival;
|
||||
Segmented packets do need to be duplicated in time-sensitive use cases */
|
||||
if (entity->common.avg_time_is_on) {
|
||||
/*
|
||||
if (sdu->sdu->time_of_arrival) {
|
||||
uint64_t time_now = time_average_now();
|
||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
||||
// set time_of_arrival to 0 so as to update stats only once
|
||||
sdu->sdu->time_of_arrival = 0;
|
||||
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
|
||||
}
|
||||
*/
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size -= sdu->size;
|
||||
|
||||
@@ -521,13 +521,15 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
|
||||
entity->common.stats.txpdu_pkts++;
|
||||
entity->common.stats.txpdu_bytes += size;
|
||||
|
||||
/* No need to 'zero' time-of-arrival;
|
||||
Segmented packets do need to be duplicated in time-sensitive use cases */
|
||||
if (entity->common.avg_time_is_on) {
|
||||
/*
|
||||
if (sdu->sdu->time_of_arrival) {
|
||||
uint64_t time_now = time_average_now();
|
||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
||||
// set time_of_arrival to 0 so as to update stats only once
|
||||
sdu->sdu->time_of_arrival = 0;
|
||||
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
|
||||
}
|
||||
*/
|
||||
|
||||
nr_rlc_free_sdu_segment(sdu);
|
||||
|
||||
|
||||
@@ -569,6 +569,7 @@ rb_found:
|
||||
#endif
|
||||
}
|
||||
|
||||
extern void nr_mac_trigger_ul_failure(int rnti);
|
||||
static void max_retx_reached(void *_ue, nr_rlc_entity_t *entity)
|
||||
{
|
||||
nr_rlc_ue_t *ue = _ue;
|
||||
@@ -615,15 +616,7 @@ rb_found:
|
||||
if (!is_enb)
|
||||
return;
|
||||
|
||||
#if 0
|
||||
msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION);
|
||||
RLC_SDU_INDICATION(msg).rnti = ue->rnti;
|
||||
RLC_SDU_INDICATION(msg).is_successful = 0;
|
||||
RLC_SDU_INDICATION(msg).srb_id = rb_id;
|
||||
RLC_SDU_INDICATION(msg).message_id = -1;
|
||||
/* TODO: accept more than 1 instance? here we send to instance id 0 */
|
||||
itti_send_msg_to_task(TASK_RRC_ENB, 0, msg);
|
||||
#endif
|
||||
nr_mac_trigger_ul_failure(ue->rnti);
|
||||
}
|
||||
|
||||
void nr_rlc_reestablish_entity(int rnti, int lc_id)
|
||||
|
||||
@@ -55,17 +55,7 @@ static bool resp_freelist_inited = false;
|
||||
|
||||
void init_sched_response(void)
|
||||
{
|
||||
/* init only once */
|
||||
if (pthread_mutex_lock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_lock failed\n");
|
||||
if (resp_freelist_inited) {
|
||||
if (pthread_mutex_unlock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_unlock failed\n");
|
||||
return;
|
||||
}
|
||||
resp_freelist_inited = true;
|
||||
if (pthread_mutex_unlock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_unlock failed\n");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < N_RESP - 1; i++)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
typedef void (*f1_setup_response_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_resp_t *resp);
|
||||
typedef void (*f1_setup_failure_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_failure_t *fail);
|
||||
typedef void (*gnb_du_configuration_update_ack_func_t)(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack);
|
||||
|
||||
typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req);
|
||||
typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req);
|
||||
|
||||
@@ -36,6 +36,12 @@ static void f1_setup_failure_direct(sctp_assoc_t assoc_id, const f1ap_setup_fail
|
||||
f1_setup_failure(fail);
|
||||
}
|
||||
|
||||
static void gnb_du_configuration_update_ack_direct(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack)
|
||||
{
|
||||
AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id);
|
||||
gnb_du_configuration_update_acknowledge(ack);
|
||||
}
|
||||
|
||||
static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req)
|
||||
{
|
||||
AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id);
|
||||
@@ -76,6 +82,7 @@ void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc)
|
||||
{
|
||||
mac_rrc->f1_setup_response = f1_setup_response_direct;
|
||||
mac_rrc->f1_setup_failure = f1_setup_failure_direct;
|
||||
mac_rrc->gnb_du_configuration_update_acknowledge = gnb_du_configuration_update_ack_direct;
|
||||
mac_rrc->ue_context_setup_request = ue_context_setup_request_direct;
|
||||
mac_rrc->ue_context_modification_request = ue_context_modification_request_direct;
|
||||
mac_rrc->ue_context_modification_confirm = ue_context_modification_confirm_direct;
|
||||
|
||||
@@ -44,6 +44,15 @@ static void f1_setup_failure_f1ap(sctp_assoc_t assoc_id, const f1ap_setup_failur
|
||||
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
|
||||
}
|
||||
|
||||
static void gnb_du_configuration_update_ack_f1ap(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE);
|
||||
msg->ittiMsgHeader.originInstance = assoc_id;
|
||||
f1ap_gnb_du_configuration_update_acknowledge_t *f1ap_msg = &F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg);
|
||||
*f1ap_msg = *ack;
|
||||
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
|
||||
}
|
||||
|
||||
static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_REQ);
|
||||
@@ -194,6 +203,7 @@ void mac_rrc_dl_f1ap_init(nr_mac_rrc_dl_if_t *mac_rrc)
|
||||
{
|
||||
mac_rrc->f1_setup_response = f1_setup_response_f1ap;
|
||||
mac_rrc->f1_setup_failure = f1_setup_failure_f1ap;
|
||||
mac_rrc->gnb_du_configuration_update_acknowledge = gnb_du_configuration_update_ack_f1ap;
|
||||
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;
|
||||
|
||||
@@ -829,6 +829,10 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc
|
||||
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay){
|
||||
|
||||
//TODO change to accomodate for SRS
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count > 0) {
|
||||
LOG_W(RRC, "%s(): already have pusch_TimeDomainAllocationList members, not adding more\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
|
||||
const int k2 = min_fb_delay;
|
||||
|
||||
@@ -346,6 +346,7 @@ typedef struct {
|
||||
typedef struct nr_mac_rrc_dl_if_s {
|
||||
f1_setup_response_func_t f1_setup_response;
|
||||
f1_setup_failure_func_t f1_setup_failure;
|
||||
gnb_du_configuration_update_ack_func_t gnb_du_configuration_update_acknowledge;
|
||||
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;
|
||||
|
||||
@@ -122,6 +122,20 @@ mui_t rrc_gNB_mui = 0;
|
||||
} \
|
||||
}
|
||||
|
||||
typedef struct deliver_ue_ctxt_release_data_t {
|
||||
gNB_RRC_INST *rrc;
|
||||
f1ap_ue_context_release_cmd_t *release_cmd;
|
||||
sctp_assoc_t assoc_id;
|
||||
} deliver_ue_ctxt_release_data_t;
|
||||
static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id)
|
||||
{
|
||||
DevAssert(deliver_pdu_data != NULL);
|
||||
deliver_ue_ctxt_release_data_t *data = deliver_pdu_data;
|
||||
data->release_cmd->rrc_container = (uint8_t*) buf;
|
||||
data->release_cmd->rrc_container_length = size;
|
||||
data->rrc->mac_rrc.ue_context_release_command(data->assoc_id, data->release_cmd);
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------------------------------------------------///
|
||||
///---------------------------------------------------------------------------------------------------------------///
|
||||
|
||||
@@ -1834,7 +1848,18 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p)
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[instance];
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, req->gNB_CU_ue_id);
|
||||
if (!ue_context_p) {
|
||||
LOG_E(RRC, "could not find UE context for CU UE ID %u, aborting transaction\n", req->gNB_CU_ue_id);
|
||||
LOG_W(RRC, "could not find UE context for CU UE ID %u: auto-generate release command\n", req->gNB_CU_ue_id);
|
||||
uint8_t buffer[RRC_BUF_SIZE] = {0};
|
||||
int size = do_NR_RRCRelease(buffer, RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(0));
|
||||
f1ap_ue_context_release_cmd_t ue_context_release_cmd = {
|
||||
.gNB_CU_ue_id = req->gNB_CU_ue_id,
|
||||
.gNB_DU_ue_id = req->gNB_DU_ue_id,
|
||||
.cause = F1AP_CAUSE_RADIO_NETWORK,
|
||||
.cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release
|
||||
.srb_id = DCCH,
|
||||
};
|
||||
deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd};
|
||||
nr_pdcp_data_req_srb(req->gNB_CU_ue_id, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2280,6 +2305,7 @@ void *rrc_gnb_task(void *args_p) {
|
||||
switch (ITTI_MSG_ID(msg_p)) {
|
||||
case TERMINATE_MESSAGE:
|
||||
LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n");
|
||||
timer_remove(stats_timer_id);
|
||||
itti_exit_task();
|
||||
break;
|
||||
|
||||
@@ -2368,6 +2394,11 @@ void *rrc_gnb_task(void *args_p) {
|
||||
rrc_CU_process_f1_lost_connection(RC.nrrrc[0], &F1AP_LOST_CONNECTION(msg_p), msg_p->ittiMsgHeader.originInstance);
|
||||
break;
|
||||
|
||||
case F1AP_GNB_DU_CONFIGURATION_UPDATE:
|
||||
AssertFatal(!NODE_IS_DU(RC.nrrrc[instance]->node_type), "should not receive F1AP_SETUP_REQUEST in DU!\n");
|
||||
rrc_gNB_process_f1_du_configuration_update(&F1AP_GNB_DU_CONFIGURATION_UPDATE(msg_p), msg_p->ittiMsgHeader.originInstance);
|
||||
break;
|
||||
|
||||
/* Messages from X2AP */
|
||||
case X2AP_ENDC_SGNB_ADDITION_REQ:
|
||||
LOG_I(NR_RRC, "Received ENDC sgNB addition request from X2AP \n");
|
||||
@@ -2534,20 +2565,6 @@ rrc_gNB_generate_UECapabilityEnquiry(
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue, DCCH, buffer, size);
|
||||
}
|
||||
|
||||
typedef struct deliver_ue_ctxt_release_data_t {
|
||||
gNB_RRC_INST *rrc;
|
||||
f1ap_ue_context_release_cmd_t *release_cmd;
|
||||
sctp_assoc_t assoc_id;
|
||||
} deliver_ue_ctxt_release_data_t;
|
||||
static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id)
|
||||
{
|
||||
DevAssert(deliver_pdu_data != NULL);
|
||||
deliver_ue_ctxt_release_data_t *data = deliver_pdu_data;
|
||||
data->release_cmd->rrc_container = (uint8_t*) buf;
|
||||
data->release_cmd->rrc_container_length = size;
|
||||
data->rrc->mac_rrc.ue_context_release_command(data->assoc_id, data->release_cmd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
* Generate the RRC Connection Release to UE.
|
||||
@@ -2600,6 +2617,255 @@ rrc_gNB_generate_RRCRelease(
|
||||
/* UE will be freed after UE context release complete */
|
||||
}
|
||||
|
||||
static pdu_session_to_setup_t fill_pdu_session(const rrc_pdu_session_param_t *session, const drb_t *rrc_drb)
|
||||
{
|
||||
pdu_session_to_setup_t pdu = {0};
|
||||
pdu.sessionId = session->param.pdusession_id;
|
||||
pdu.numDRB2Setup = 1;
|
||||
DRB_nGRAN_to_setup_t *drb = &pdu.DRBnGRanList[0];
|
||||
drb->id = rrc_drb->drb_id;
|
||||
|
||||
const struct sdap_config_s *sdap_config = &rrc_drb->cnAssociation.sdap_config;
|
||||
drb->defaultDRB = sdap_config->defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false;
|
||||
drb->sDAP_Header_UL = sdap_config->sdap_HeaderUL;
|
||||
drb->sDAP_Header_DL = sdap_config->sdap_HeaderDL;
|
||||
drb->numQosFlow2Setup = 1;
|
||||
|
||||
const struct pdcp_config_s *pdcp_config = &rrc_drb->pdcp_config;
|
||||
drb->pDCP_SN_Size_UL = pdcp_config->pdcp_SN_SizeUL;
|
||||
drb->pDCP_SN_Size_DL = pdcp_config->pdcp_SN_SizeDL;
|
||||
drb->discardTimer = pdcp_config->discardTimer;
|
||||
drb->reorderingTimer = pdcp_config->t_Reordering;
|
||||
|
||||
drb->rLC_Mode = E1AP_RLC_Mode_rlc_am; //rrc->configuration.um_on_default_drb ? E1AP_RLC_Mode_rlc_um_bidirectional : E1AP_RLC_Mode_rlc_am;
|
||||
|
||||
drb->numCellGroups = 1; // assume one cell group associated with a DRB
|
||||
|
||||
for (int k=0; k < drb->numCellGroups; k++) {
|
||||
cell_group_t *cellGroup = drb->cellGroupList + k;
|
||||
cellGroup->id = 0; // MCG
|
||||
}
|
||||
|
||||
drb->numQosFlow2Setup = session->param.nb_qos;
|
||||
for (int k=0; k < drb->numQosFlow2Setup; k++) {
|
||||
qos_flow_to_setup_t *qos_flow = drb->qosFlows + k;
|
||||
const pdusession_level_qos_parameter_t *qos_session = session->param.qos + k;
|
||||
|
||||
qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics;
|
||||
qos_flow->qfi = qos_session->qfi;
|
||||
qos_char->qos_type = qos_session->fiveQI_type;
|
||||
if (qos_char->qos_type == dynamic) {
|
||||
qos_char->dynamic.fiveqi = qos_session->fiveQI;
|
||||
qos_char->dynamic.qos_priority_level = qos_session->qos_priority;
|
||||
} else {
|
||||
qos_char->non_dynamic.fiveqi = qos_session->fiveQI;
|
||||
qos_char->non_dynamic.qos_priority_level = qos_session->qos_priority;
|
||||
}
|
||||
|
||||
ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority;
|
||||
const ngap_allocation_retention_priority_t *rent_priority_in = &qos_session->allocation_retention_priority;
|
||||
rent_priority->priority_level = rent_priority_in->priority_level;
|
||||
rent_priority->preemption_capability = rent_priority_in->pre_emp_capability;
|
||||
rent_priority->preemption_vulnerability = rent_priority_in->pre_emp_vulnerability;
|
||||
}
|
||||
|
||||
return pdu;
|
||||
}
|
||||
|
||||
static int get_single_ue_rnti(void)
|
||||
{
|
||||
rrc_gNB_ue_context_t *ue_context_p = NULL;
|
||||
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(RC.nrrrc[0]->rrc_ue_head)) {
|
||||
return ue_context_p->ue_context.rnti;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern instance_t get_f1_gtp_instance(void);
|
||||
void rrc_gNB_trigger_new_bearer(int rnti)
|
||||
{
|
||||
/* get RRC and UE */
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
if (rnti < 0)
|
||||
rnti = get_single_ue_rnti();
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti_any_du(rrc, rnti);
|
||||
if (ue_context_p == NULL) {
|
||||
LOG_E(RRC, "unknown UE RNTI %04x\n", rnti);
|
||||
return;
|
||||
}
|
||||
gNB_RRC_UE_t *ue = &ue_context_p->ue_context;
|
||||
|
||||
/* get the existing PDU sessoin */
|
||||
if (ue->nb_of_pdusessions < 1) {
|
||||
LOG_E(RRC, "no PDU session set up yet, cannot create additional bearer\n");
|
||||
return;
|
||||
}
|
||||
const rrc_pdu_session_param_t *session = &ue->pduSession[0];
|
||||
DevAssert(session->param.nb_qos == 1);
|
||||
|
||||
if (ue->established_drbs[0].status != DRB_INACTIVE
|
||||
&& ue->established_drbs[1].status != DRB_INACTIVE) {
|
||||
LOG_E(RRC, "already have two established bearers, aborting\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int drb_id = 2;
|
||||
drb_t *rrc_drb = generateDRB(ue,
|
||||
drb_id,
|
||||
session,
|
||||
rrc->configuration.enable_sdap,
|
||||
rrc->security.do_drb_integrity,
|
||||
rrc->security.do_drb_ciphering);
|
||||
|
||||
/* the only thing E1 can do as of now, is to generate new PDU sessions. This
|
||||
* includes SDAP, and GTP/NG-U, but we don't want that. therefore, use PDCP
|
||||
* and GTP/F1-U directly below */
|
||||
|
||||
/* generate dummy PDU session, from which we generate DRB info, used to
|
||||
* initialize PDCP */
|
||||
pdu_session_to_setup_t pdu = fill_pdu_session(session, rrc_drb);
|
||||
|
||||
pdu.integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed;
|
||||
pdu.confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed;
|
||||
|
||||
NR_DRB_ToAddModList_t DRB_configList = {0};
|
||||
extern void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const pdu_session_to_setup_t *pdu);
|
||||
fill_DRB_configList_e1(&DRB_configList, &pdu);
|
||||
|
||||
uint8_t enc_key[16];
|
||||
nr_derive_key(UP_ENC_ALG, ue->ciphering_algorithm, ue->kgnb, enc_key);
|
||||
uint8_t int_key[16];
|
||||
nr_derive_key(UP_INT_ALG, ue->integrity_algorithm, ue->kgnb, int_key);
|
||||
|
||||
nr_pdcp_add_drbs(true, // set this to notify PDCP that his not UE
|
||||
ue->rrc_ue_id,
|
||||
&DRB_configList,
|
||||
(ue->integrity_algorithm << 4) | ue->ciphering_algorithm,
|
||||
enc_key,
|
||||
int_key);
|
||||
|
||||
/* initialize F1 GTP, if necessary */
|
||||
instance_t f1inst = get_f1_gtp_instance();
|
||||
uint8_t tlAddress[4] = {0};
|
||||
long teid = 0;
|
||||
if (f1inst >= 0) { /* we have F1(-U) */
|
||||
teid_t dummy_teid = 0xffff; // we will update later with answer from DU
|
||||
in_addr_t dummy_address = {0}; // IPv4, updated later with answer from DU
|
||||
gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0};
|
||||
int qfi = -1; // don't put PDU session marker in GTP
|
||||
extern int drb_gtpu_create(instance_t instance, uint32_t ue_id, int incoming_id, int outgoing_id,
|
||||
int qfi, in_addr_t tlAddress, teid_t outgoing_teid,
|
||||
gtpCallback callBack, gtpCallbackSDAP callBackSDAP, gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp);
|
||||
int ret = drb_gtpu_create(f1inst,
|
||||
ue->rrc_ue_id,
|
||||
rrc_drb->drb_id,
|
||||
rrc_drb->drb_id,
|
||||
qfi,
|
||||
dummy_address,
|
||||
dummy_teid,
|
||||
cu_f1u_data_req,
|
||||
NULL,
|
||||
&resp_f1);
|
||||
AssertFatal(ret >= 0, "Unable to create GTP Tunnel for F1-U\n");
|
||||
memcpy(tlAddress, &resp_f1.gnb_addr.buffer, 4);
|
||||
teid = resp_f1.gnb_NGu_teid[0];
|
||||
}
|
||||
|
||||
int xid = rrc_gNB_get_next_transaction_identifier(0);
|
||||
/* associate the new bearer to it */
|
||||
ue->xids[xid] = RRC_DEDICATED_RECONF;
|
||||
ue->pduSession[0].xid = xid; // hack: fake xid for ongoing PDU session
|
||||
LOG_W(RRC, "trigger new bearer %d for UE %04x xid %d\n", rrc_drb->drb_id, ue->rnti, xid);
|
||||
|
||||
/* as noted above, cannot go via E1, but reuse E1 setup response handler to
|
||||
* set up the DRB via F1 (and then the reconfiguration) */
|
||||
e1ap_bearer_setup_resp_t resp = {
|
||||
.gNB_cu_cp_ue_id = ue->rrc_ue_id,
|
||||
.gNB_cu_up_ue_id = ue->rrc_ue_id,
|
||||
.numPDUSessions = 1,
|
||||
.pduSession[0].id = session->param.pdusession_id,
|
||||
.pduSession[0].numDRBSetup = 1,
|
||||
.pduSession[0].DRBnGRanList[0].id = drb_id,
|
||||
.pduSession[0].DRBnGRanList[0].numQosFlowSetup = 1,
|
||||
.pduSession[0].DRBnGRanList[0].qosFlows[0].qfi = session->param.qos[0].qfi,
|
||||
};
|
||||
if (f1inst >= 0) { /* we have F1(-U) */
|
||||
DRB_nGRAN_setup_t *resp_drb = &resp.pduSession[0].DRBnGRanList[0];
|
||||
resp_drb->numUpParam = 1;
|
||||
memcpy(&resp_drb->UpParamList[0].tlAddress, tlAddress, 4);
|
||||
resp_drb->UpParamList[0].teId = teid;
|
||||
}
|
||||
rrc_gNB_process_e1_bearer_context_setup_resp(&resp, 0);
|
||||
}
|
||||
|
||||
void rrc_gNB_trigger_release_bearer(int rnti)
|
||||
{
|
||||
/* get RRC and UE */
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
if (rnti < 0)
|
||||
rnti = get_single_ue_rnti();
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti_any_du(rrc, rnti);
|
||||
if (ue_context_p == NULL) {
|
||||
LOG_E(RRC, "unknown UE RNTI %04x\n", rnti);
|
||||
return;
|
||||
}
|
||||
gNB_RRC_UE_t *ue = &ue_context_p->ue_context;
|
||||
|
||||
if (ue->established_drbs[1].status == DRB_INACTIVE) {
|
||||
LOG_E(RRC, "no second bearer, aborting\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// don't use E1: bearer release is not implemented, call directly
|
||||
// into PDCP/SDAP and then send corresponding message via F1
|
||||
|
||||
int drb_id = 2;
|
||||
ue->established_drbs[1].status = DRB_INACTIVE;
|
||||
ue->DRB_ReleaseList = calloc(1, sizeof(*ue->DRB_ReleaseList));
|
||||
AssertFatal(ue->DRB_ReleaseList != NULL, "out of memory\n");
|
||||
NR_DRB_Identity_t *asn1_drb = malloc(sizeof(*asn1_drb));
|
||||
AssertFatal(asn1_drb != NULL, "out of memory\n");
|
||||
int idx = 0;
|
||||
NR_DRB_ToAddModList_t *drb_list = createDRBlist(ue, false);
|
||||
while (idx < drb_list->list.count) {
|
||||
const NR_DRB_ToAddMod_t *drbc = drb_list->list.array[idx];
|
||||
if (drbc->drb_Identity == drb_id)
|
||||
break;
|
||||
++idx;
|
||||
}
|
||||
if (idx < drb_list->list.count) {
|
||||
nr_pdcp_release_drb(rnti, drb_id);
|
||||
asn_sequence_del(&drb_list->list, idx, 1);
|
||||
}
|
||||
*asn1_drb = drb_id;
|
||||
asn1cSeqAdd(&ue->DRB_ReleaseList->list, asn1_drb);
|
||||
|
||||
instance_t f1inst = get_f1_gtp_instance();
|
||||
if (f1inst >= 0)
|
||||
newGtpuDeleteOneTunnel(f1inst, ue->rrc_ue_id, drb_id);
|
||||
nr_pdcp_release_drb(ue->rrc_ue_id, drb_id);
|
||||
|
||||
f1ap_drb_to_be_released_t drbs_to_be_released[1] = {{.rb_id = drb_id}};
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data);
|
||||
f1ap_ue_context_modif_req_t ue_context_modif_req = {
|
||||
.gNB_CU_ue_id = ue->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
.plmn.mcc = rrc->configuration.mcc[0],
|
||||
.plmn.mnc = rrc->configuration.mnc[0],
|
||||
.plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0],
|
||||
.nr_cellid = rrc->nr_cellid,
|
||||
.servCellId = 0, /* TODO: correct value? */
|
||||
.srbs_to_be_setup_length = 0,
|
||||
.srbs_to_be_setup = NULL,
|
||||
.drbs_to_be_setup_length = 0,
|
||||
.drbs_to_be_setup = NULL,
|
||||
.drbs_to_be_released_length = 1,
|
||||
.drbs_to_be_released = drbs_to_be_released,
|
||||
};
|
||||
rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req);
|
||||
}
|
||||
|
||||
int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint32_t tmsi, uint8_t paging_drx)
|
||||
{
|
||||
instance_t instance = 0;
|
||||
|
||||
@@ -48,6 +48,39 @@ static bool rrc_gNB_plmn_matches(const gNB_RRC_INST *rrc, const f1ap_served_cell
|
||||
&& conf->mnc[0] == info->plmn.mnc;
|
||||
}
|
||||
|
||||
static bool extract_sys_info(const f1ap_gnb_du_system_info_t *sys_info, NR_BCCH_BCH_Message_t **mib, NR_SIB1_t **sib1)
|
||||
{
|
||||
DevAssert(sys_info != NULL);
|
||||
DevAssert(mib != NULL);
|
||||
DevAssert(sib1 != NULL);
|
||||
|
||||
asn_dec_rval_t dec_rval =
|
||||
uper_decode_complete(NULL, &asn_DEF_NR_BCCH_BCH_Message, (void **)mib, sys_info->mib, sys_info->mib_length);
|
||||
if (dec_rval.code != RC_OK || (*mib)->message.present != NR_BCCH_BCH_MessageType_PR_mib
|
||||
|| (*mib)->message.choice.messageClassExtension == NULL) {
|
||||
LOG_E(RRC, "Failed to decode NR_BCCH_BCH_MESSAGE (%zu bits) of DU\n", dec_rval.consumed);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, *mib);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sys_info->sib1) {
|
||||
dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_SIB1, (void **)sib1, sys_info->sib1, sys_info->sib1_length);
|
||||
if (dec_rval.code != RC_OK) {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, *mib);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SIB1, *sib1);
|
||||
LOG_E(RRC, "Failed to decode NR_SIB1 (%zu bits), rejecting DU\n", dec_rval.consumed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1))
|
||||
xer_fprint(stdout, &asn_DEF_NR_BCCH_BCH_Message, *mib);
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1))
|
||||
xer_fprint(stdout, &asn_DEF_NR_SIB1, *sib1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
{
|
||||
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
|
||||
@@ -110,35 +143,17 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
}
|
||||
}
|
||||
|
||||
// if there is no system info or no SIB1 and we run in SA mode, we cannot handle it
|
||||
const f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info;
|
||||
NR_BCCH_BCH_Message_t *mib = NULL;
|
||||
NR_SIB1_t *sib1 = NULL;
|
||||
|
||||
if (sys_info != NULL && sys_info->mib != NULL && !(sys_info->sib1 == NULL && get_softmodem_params()->sa)) {
|
||||
asn_dec_rval_t dec_rval =
|
||||
uper_decode_complete(NULL, &asn_DEF_NR_BCCH_BCH_Message, (void **)&mib, sys_info->mib, sys_info->mib_length);
|
||||
if (dec_rval.code != RC_OK || mib->message.present != NR_BCCH_BCH_MessageType_PR_mib
|
||||
|| mib->message.choice.messageClassExtension == NULL) {
|
||||
LOG_E(RRC, "Failed to decode NR_BCCH_BCH_MESSAGE (%zu bits) of DU, rejecting DU\n", dec_rval.consumed);
|
||||
if (!extract_sys_info(sys_info, &mib, &sib1)) {
|
||||
LOG_W(RRC, "rejecting DU ID %ld\n", req->gNB_DU_id);
|
||||
f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error};
|
||||
rrc->mac_rrc.f1_setup_failure(assoc_id, &fail);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, mib);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sys_info->sib1) {
|
||||
dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_SIB1, (void **)&sib1, sys_info->sib1, sys_info->sib1_length);
|
||||
if (dec_rval.code != RC_OK) {
|
||||
LOG_E(RRC, "Failed to decode NR_SIB1 (%zu bits) of DU, rejecting DU\n", dec_rval.consumed);
|
||||
f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error};
|
||||
rrc->mac_rrc.f1_setup_failure(assoc_id, &fail);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SIB1, sib1);
|
||||
return;
|
||||
}
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1))
|
||||
xer_fprint(stdout, &asn_DEF_NR_SIB1, sib1);
|
||||
}
|
||||
}
|
||||
LOG_I(RRC, "Accepting DU %ld (%s), sending F1 Setup Response\n", req->gNB_DU_id, req->gNB_DU_name);
|
||||
LOG_I(RRC, "DU uses RRC version %u.%u.%u\n", req->rrc_ver[0], req->rrc_ver[1], req->rrc_ver[2]);
|
||||
@@ -154,12 +169,11 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
du->setup_req = calloc(1,sizeof(*du->setup_req));
|
||||
AssertFatal(du->setup_req != NULL, "out of memory\n");
|
||||
*du->setup_req = *req;
|
||||
if (mib != NULL && sib1 != NULL) {
|
||||
du->mib = mib->message.choice.mib;
|
||||
mib->message.choice.mib = NULL;
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_MessageType, mib);
|
||||
du->sib1 = sib1;
|
||||
}
|
||||
DevAssert(mib != NULL);
|
||||
du->mib = mib->message.choice.mib;
|
||||
mib->message.choice.mib = NULL;
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_MessageType, mib);
|
||||
du->sib1 = sib1;
|
||||
RB_INSERT(rrc_du_tree, &rrc->dus, du);
|
||||
rrc->num_dus++;
|
||||
|
||||
@@ -178,28 +192,6 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
if (rrc->node_name != NULL)
|
||||
resp.gNB_CU_name = strdup(rrc->node_name);
|
||||
rrc->mac_rrc.f1_setup_response(assoc_id, &resp);
|
||||
|
||||
/*
|
||||
MessageDef *msg_p2 = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE);
|
||||
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).gNB_CU_name = rrc->node_name;
|
||||
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].plmn.mcc = rrc->configuration.mcc[0];
|
||||
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].plmn.mnc = rrc->configuration.mnc[0];
|
||||
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0];
|
||||
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].nr_cellid = rrc->nr_cellid;
|
||||
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].nrpci = req->cell[0].info.nr_pci;
|
||||
int num_SI = 0;
|
||||
|
||||
if (rrc->carrier.SIB23) {
|
||||
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].SI_container[2] = rrc->carrier.SIB23;
|
||||
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].SI_container_length[2] = rrc->carrier.sizeof_SIB23;
|
||||
num_SI++;
|
||||
}
|
||||
|
||||
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].num_SI = num_SI;
|
||||
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).num_cells_to_activate = 1;
|
||||
// send
|
||||
itti_send_msg_to_task(TASK_CU_F1, 0, msg_p2);
|
||||
*/
|
||||
}
|
||||
|
||||
static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id)
|
||||
@@ -221,6 +213,103 @@ static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id)
|
||||
return count;
|
||||
}
|
||||
|
||||
static void update_cell_info(nr_rrc_du_container_t *du, const f1ap_served_cell_info_t *new_ci)
|
||||
{
|
||||
DevAssert(du != NULL);
|
||||
DevAssert(new_ci != NULL);
|
||||
|
||||
AssertFatal(du->setup_req->num_cells_available == 1, "expected 1 cell for DU, but has %d\n", du->setup_req->num_cells_available);
|
||||
f1ap_served_cell_info_t *ci = &du->setup_req->cell[0].info;
|
||||
|
||||
ci->nr_cellid = new_ci->nr_cellid;
|
||||
ci->nr_pci = new_ci->nr_pci;
|
||||
if (new_ci->tac != NULL)
|
||||
*ci->tac = *new_ci->tac;
|
||||
ci->num_ssi = new_ci->num_ssi;
|
||||
ci->sst = new_ci->sst;
|
||||
ci->sd = new_ci->sd;
|
||||
ci->mode = new_ci->mode;
|
||||
if (ci->mode == F1AP_MODE_TDD)
|
||||
ci->tdd = new_ci->tdd;
|
||||
else
|
||||
ci->fdd = new_ci->fdd;
|
||||
}
|
||||
|
||||
void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update_t *conf_up, sctp_assoc_t assoc_id)
|
||||
{
|
||||
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
DevAssert(rrc);
|
||||
|
||||
// check:
|
||||
// - it is one cell
|
||||
// - PLMN and Cell ID matches
|
||||
// - no previous DU with the same ID
|
||||
// else reject
|
||||
|
||||
nr_rrc_du_container_t *du = get_du_by_assoc_id(rrc, assoc_id);
|
||||
AssertError(du != NULL, return, "no DU found for assoc_id %d\n", assoc_id);
|
||||
|
||||
const f1ap_served_cell_info_t *info = &du->setup_req->cell[0].info;
|
||||
if(conf_up->num_cells_to_add > 0){
|
||||
// Here we check if the number of cell limit is respectet, otherwise send failure
|
||||
LOG_W(RRC, "du_configuration_update->cells_to_add_list is not supported yet");
|
||||
}
|
||||
|
||||
if(conf_up->num_cells_to_modify > 0){
|
||||
// here the old nrcgi is used to find the cell information, if it exist then we modify consequently otherwise we fail
|
||||
AssertFatal(conf_up->num_cells_to_modify == 1, "cannot handle more than one cell!\n");
|
||||
|
||||
if (info->nr_cellid != conf_up->cell_to_modify[0].old_nr_cellid) {
|
||||
LOG_W(RRC, "no cell with ID %ld found, ignoring gNB-DU configuration update\n", conf_up->cell_to_modify[0].old_nr_cellid);
|
||||
return;
|
||||
}
|
||||
|
||||
// verify the new plmn of the cell
|
||||
if (!rrc_gNB_plmn_matches(rrc, &conf_up->cell_to_modify[0].info)) {
|
||||
LOG_W(RRC, "PLMN does not match, ignoring gNB-DU configuration update\n");
|
||||
return;
|
||||
}
|
||||
|
||||
update_cell_info(du, &conf_up->cell_to_modify[0].info);
|
||||
|
||||
const f1ap_gnb_du_system_info_t *sys_info = conf_up->cell_to_modify[0].sys_info;
|
||||
|
||||
if (sys_info != NULL && sys_info->mib != NULL && !(sys_info->sib1 == NULL && get_softmodem_params()->sa)) {
|
||||
// MIB is mandatory, so will be overwritten. SIB1 is optional, so will
|
||||
// only be overwritten if present in sys_info
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MIB, du->mib);
|
||||
if (sys_info->sib1 != NULL) {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SIB1, du->sib1);
|
||||
du->sib1 = NULL;
|
||||
}
|
||||
|
||||
NR_BCCH_BCH_Message_t *mib = NULL;
|
||||
|
||||
if (!extract_sys_info(sys_info, &mib, &du->sib1)) {
|
||||
LOG_W(RRC, "cannot update sys_info for DU %ld\n", du->setup_req->gNB_DU_id);
|
||||
} else {
|
||||
DevAssert(mib != NULL);
|
||||
du->mib = mib->message.choice.mib;
|
||||
mib->message.choice.mib = NULL;
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_MessageType, mib);
|
||||
LOG_I(RRC, "update system information of DU %ld\n", du->setup_req->gNB_DU_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(conf_up->num_cells_to_delete > 0){
|
||||
// delete the cell and send cell to desactive IE in the response.
|
||||
LOG_W(RRC, "du_configuration_update->cells_to_delete_list is not supported yet");
|
||||
}
|
||||
|
||||
|
||||
/* Send DU Configuration Acknowledgement */
|
||||
f1ap_gnb_du_configuration_update_acknowledge_t ack = {.transaction_id = conf_up->transaction_id};
|
||||
|
||||
rrc->mac_rrc.gnb_du_configuration_update_acknowledge(assoc_id, &ack);
|
||||
}
|
||||
|
||||
void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id)
|
||||
{
|
||||
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
|
||||
@@ -276,5 +365,18 @@ void dump_du_info(const gNB_RRC_INST *rrc, FILE *f)
|
||||
}
|
||||
const f1ap_served_cell_info_t *info = &sr->cell[0].info;
|
||||
fprintf(f, ": nrCellID %ld, PCI %d\n", info->nr_cellid, info->nr_pci);
|
||||
|
||||
if (info->mode == F1AP_MODE_TDD) {
|
||||
const f1ap_nr_frequency_info_t *fi = &info->tdd.freqinfo;
|
||||
const f1ap_transmission_bandwidth_t *tb = &info->tdd.tbw;
|
||||
fprintf(f, " TDD: band %d ARFCN %d SCS %d (kHz) PRB %d\n", fi->band, fi->arfcn, 15 * (1 << tb->scs), tb->nrb);
|
||||
} else {
|
||||
const f1ap_nr_frequency_info_t *dfi = &info->fdd.dl_freqinfo;
|
||||
const f1ap_transmission_bandwidth_t *dtb = &info->fdd.dl_tbw;
|
||||
fprintf(f, " FDD: DL band %d ARFCN %d SCS %d (kHz) PRB %d\n", dfi->band, dfi->arfcn, 15 * ( 1 << dtb->scs), dtb->nrb);
|
||||
const f1ap_nr_frequency_info_t *ufi = &info->fdd.ul_freqinfo;
|
||||
const f1ap_transmission_bandwidth_t *utb = &info->fdd.ul_tbw;
|
||||
fprintf(f, " UL band %d ARFCN %d SCS %d (kHz) PRB %d\n", ufi->band, ufi->arfcn, 15 * (1 << utb->scs), utb->nrb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,11 @@ struct f1ap_setup_req_s;
|
||||
struct f1ap_lost_connection_t;
|
||||
struct gNB_RRC_INST_s;
|
||||
struct nr_rrc_du_container_t;
|
||||
struct f1ap_gnb_du_configuration_update_s;
|
||||
|
||||
void rrc_gNB_process_f1_setup_req(struct f1ap_setup_req_s *req, sctp_assoc_t assoc_id);
|
||||
void rrc_CU_process_f1_lost_connection(struct gNB_RRC_INST_s *rrc, struct f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id);
|
||||
void rrc_gNB_process_f1_du_configuration_update(struct f1ap_gnb_du_configuration_update_s *conf_up, sctp_assoc_t assoc_id);
|
||||
|
||||
struct nr_rrc_du_container_t *get_du_for_ue(struct gNB_RRC_INST_s *rrc, uint32_t ue_id);
|
||||
struct nr_rrc_du_container_t *get_du_by_assoc_id(struct gNB_RRC_INST_s *rrc, sctp_assoc_t assoc_id);
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
#include <openair3/ocp-gtpu/gtp_itf.h>
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
@@ -56,6 +63,50 @@ void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_s
|
||||
return;
|
||||
}
|
||||
|
||||
/* \brief returns 1 for packets matching criteria, otherwise 1. Criteria is:
|
||||
* - TCP packet AND dport != 10101 AND dport != 5201 AND second bearer
|
||||
* - UDP packet AND dport != 10101 AND dport != 5201 AND dport != 2153 AND dport != 2153 AND second bearer
|
||||
* - ICMP
|
||||
*/
|
||||
static int analyze_packet_inc(nr_sdap_entity_t *entity, const unsigned char *sdu_buffer)
|
||||
{
|
||||
// mir
|
||||
// Naive L4/L3 packet classifier
|
||||
struct iphdr* hdr = (struct iphdr*)sdu_buffer;
|
||||
|
||||
if(hdr->protocol == IPPROTO_TCP){
|
||||
struct tcphdr* tcp = (struct tcphdr*)((uint32_t*)hdr + hdr->ihl);
|
||||
//uint16_t const src_port = ntohs(tcp->source);
|
||||
uint16_t const dst_port = ntohs(tcp->dest);
|
||||
//printf("TCP pkt src_port %d dst_port %d \n", src_port, dst_port);
|
||||
|
||||
if (entity->is_gnb && entity->has_second_bearer && dst_port != 10101 && dst_port != 5201) {
|
||||
return 1;
|
||||
}
|
||||
//printf("TCP\n");
|
||||
} else if(hdr->protocol == IPPROTO_UDP){
|
||||
struct udphdr *udp = (struct udphdr *)((uint32_t*)hdr + hdr->ihl);
|
||||
//uint16_t const src_port = ntohs(udp->source);
|
||||
uint16_t const dst_port = ntohs(udp->dest);
|
||||
//printf("UDP pkt src_port %d dst_port %d \n", src_port, dst_port);
|
||||
if (entity->is_gnb && entity->has_second_bearer && dst_port != 10101 && dst_port != 5201 && dst_port != 2154 && dst_port != 2153) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
} else if(hdr->protocol == IPPROTO_ICMP){
|
||||
//printf("Ping packet detected \n");
|
||||
if (entity->is_gnb && entity->has_second_bearer) {
|
||||
return 1;
|
||||
}
|
||||
//printf("ping\n");
|
||||
//cnt++;
|
||||
} else {
|
||||
printf("undetected header\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity,
|
||||
protocol_ctxt_t *ctxt_p,
|
||||
const srb_flag_t srb_flag,
|
||||
@@ -91,7 +142,9 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity,
|
||||
}
|
||||
|
||||
if(!pdcp_ent_has_sdap){
|
||||
LOG_D(SDAP, "TX - DRB ID: %ld does not have SDAP\n", entity->qfi2drb_table[qfi].drb_id);
|
||||
LOG_W(SDAP, "TX - DRB ID: %ld does not have SDAP\n", entity->qfi2drb_table[qfi].drb_id);
|
||||
|
||||
sdap_drb_id += analyze_packet_inc(entity, sdu_buffer);
|
||||
ret = nr_pdcp_data_req_drb(ctxt_p,
|
||||
srb_flag,
|
||||
sdap_drb_id,
|
||||
@@ -103,6 +156,7 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity,
|
||||
sourceL2Id,
|
||||
destinationL2Id);
|
||||
|
||||
|
||||
if(!ret)
|
||||
LOG_E(SDAP, "%s:%d:%s: PDCP refused PDU\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
@@ -114,6 +168,8 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity,
|
||||
return 0;
|
||||
}
|
||||
|
||||
sdap_drb_id += analyze_packet_inc(entity, sdu_buffer);
|
||||
|
||||
if(ctxt_p->enb_flag) { // gNB
|
||||
offset = SDAP_HDR_LENGTH;
|
||||
/*
|
||||
@@ -415,11 +471,12 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb,
|
||||
uint8_t mappedQFIs2AddCount)
|
||||
{
|
||||
if (nr_sdap_get_entity(ue_id, pdusession_id)) {
|
||||
LOG_E(SDAP, "SDAP Entity for UE already exists with RNTI/UE ID: %lu and PDU SESSION ID: %d\n", ue_id, pdusession_id);
|
||||
LOG_I(SDAP, "SDAP Entity for UE already exists with RNTI/UE ID: %lu and PDU SESSION ID: %d\n", ue_id, pdusession_id);
|
||||
nr_sdap_entity_t *existing_sdap_entity = nr_sdap_get_entity(ue_id, pdusession_id);
|
||||
rb_id_t pdcp_entity = existing_sdap_entity->default_drb;
|
||||
if(!is_gnb)
|
||||
nr_sdap_ue_qfi2drb_config(existing_sdap_entity, pdcp_entity, ue_id, mapped_qfi_2_add, mappedQFIs2AddCount, drb_identity, has_sdap_rx, has_sdap_tx);
|
||||
existing_sdap_entity->has_second_bearer = 1;
|
||||
return existing_sdap_entity;
|
||||
}
|
||||
|
||||
@@ -433,6 +490,7 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb,
|
||||
|
||||
sdap_entity->ue_id = ue_id;
|
||||
sdap_entity->pdusession_id = pdusession_id;
|
||||
sdap_entity->is_gnb = is_gnb;
|
||||
|
||||
sdap_entity->tx_entity = nr_sdap_tx_entity;
|
||||
sdap_entity->rx_entity = nr_sdap_rx_entity;
|
||||
|
||||
@@ -79,6 +79,8 @@ void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_s
|
||||
typedef struct nr_sdap_entity_s {
|
||||
ue_id_t ue_id;
|
||||
rb_id_t default_drb;
|
||||
int is_gnb;
|
||||
int has_second_bearer;
|
||||
int pdusession_id;
|
||||
qfi2drb_t qfi2drb_table[SDAP_MAX_QFI];
|
||||
|
||||
|
||||
@@ -670,6 +670,15 @@ static int startServer(openair0_device *device) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rfsimulator_end(openair0_device *device);
|
||||
static void stopServer(openair0_device *device)
|
||||
{
|
||||
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
|
||||
DevAssert(t != NULL);
|
||||
rfsimulator_end(device);
|
||||
close(t->listen_sock);
|
||||
}
|
||||
|
||||
static int startClient(openair0_device *device) {
|
||||
rfsimulator_state_t *t = device->priv;
|
||||
t->role = SIMU_ROLE_CLIENT;
|
||||
@@ -1047,10 +1056,11 @@ static void rfsimulator_end(openair0_device *device) {
|
||||
rfsimulator_state_t* s = device->priv;
|
||||
for (int i = 0; i < MAX_FD_RFSIMU; i++) {
|
||||
buffer_t *b = &s->buf[i];
|
||||
if (b->conn_sock >= 0 )
|
||||
close(b->conn_sock);
|
||||
if (b->conn_sock >= 0 ) {
|
||||
removeCirBuf(s, b->conn_sock);
|
||||
}
|
||||
}
|
||||
close(s->epollfd);
|
||||
//close(s->epollfd); // don't close as we cannot restart with startServer()/startClient()
|
||||
}
|
||||
static int rfsimulator_stop(openair0_device *device) {
|
||||
return 0;
|
||||
@@ -1084,7 +1094,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
device->trx_start_func = rfsimulator->role == SIMU_ROLE_SERVER ? startServer : startClient;
|
||||
device->trx_get_stats_func = rfsimulator_get_stats;
|
||||
device->trx_reset_stats_func = rfsimulator_reset_stats;
|
||||
device->trx_end_func = rfsimulator_end;
|
||||
device->trx_end_func = rfsimulator->role == SIMU_ROLE_SERVER ? stopServer : rfsimulator_end;
|
||||
device->trx_stop_func = rfsimulator_stop;
|
||||
device->trx_set_freq_func = rfsimulator_set_freq;
|
||||
device->trx_set_gains_func = rfsimulator_set_gains;
|
||||
|
||||
Reference in New Issue
Block a user