Merge branch 'integration_2025_w24' into 'develop'
Integration: `2025.w24` Closes #965 See merge request oai/openairinterface5g!3476 * !3354 Preparation Work for N2 Handover * !3383 Add configurable values of NR RLC and NR PDCP to the configuration file * !3468 Resolve "SSB frequency at gnb.sa.band78.fr1.24PRB.usrpb210.conf is invalid" * !3466 YAML related updates * !3460 SRS configuration * !3474 Fix AMF selection fallback by PLMN ID when no UE identity is present or matching * !3473 Fix various bugs and inconsistencies in config read, SCTP, ITTI, GTP * !3169 NR RU improvements for analog beamforming * !3456 CI: update config for AW2S pipeline * !3369 Add Security Mode Reject lib/unit test and adopt in stack * !3457 Fix NR reestablishment * !3412 [E2 agent] E2AP README update and OAI-FlexRIC CI pipeline improvements
This commit is contained in:
+8
-7
@@ -300,14 +300,15 @@ add_definitions(-DHAVE_NETINET_IN_H)
|
||||
set(E2_AGENT "OFF" CACHE STRING "O-RAN-compliant E2 Agent")
|
||||
set_property(CACHE E2_AGENT PROPERTY STRINGS "ON" "OFF")
|
||||
|
||||
set(E2AP_VERSION "E2AP_V2" CACHE STRING "E2AP version")
|
||||
set_property(CACHE E2AP_VERSION PROPERTY STRINGS "E2AP_V1" "E2AP_V2" "E2AP_V3")
|
||||
message(STATUS "Selected E2AP_VERSION: ${E2AP_VERSION}")
|
||||
|
||||
set(KPM_VERSION "KPM_V2_03" CACHE STRING "The KPM SM version to use")
|
||||
set_property(CACHE KPM_VERSION PROPERTY STRINGS "KPM_V2_03" "KPM_V3_00")
|
||||
message(STATUS "Selected KPM Version: ${KPM_VERSION}")
|
||||
if (E2_AGENT)
|
||||
set(E2AP_VERSION "E2AP_V2" CACHE STRING "E2AP version")
|
||||
set_property(CACHE E2AP_VERSION PROPERTY STRINGS "E2AP_V1" "E2AP_V2" "E2AP_V3")
|
||||
message(STATUS "Selected E2AP version: ${E2AP_VERSION}")
|
||||
|
||||
set(KPM_VERSION "KPM_V2_03" CACHE STRING "The KPM SM version to use")
|
||||
set_property(CACHE KPM_VERSION PROPERTY STRINGS "KPM_V2_03" "KPM_V3_00")
|
||||
message(STATUS "Selected KPM version: ${KPM_VERSION}")
|
||||
endif()
|
||||
|
||||
add_boolean_option(ENABLE_IMSCOPE OFF "Enable phy scope based on imgui" OFF)
|
||||
add_boolean_option(ENABLE_IMSCOPE_RECORD OFF "Enable recording IQ data for imscope" OFF)
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
#define DL_ARFCN 631296
|
||||
#define TDD 1
|
||||
|
||||
log_options: "all.level=warn,all.max_size=0,nas.level=debug,nas.max_size=1,rrc.level=debug,rrc.max_size=1",
|
||||
log_options: "all.level=debug,all.max_size=0,nas.level=debug,nas.max_size=1,rrc.level=debug,rrc.max_size=1",
|
||||
log_filename: "/tmp/ue.log",
|
||||
|
||||
/* Enable remote API and Web interface */
|
||||
com_addr: "0.0.0.0:9002",
|
||||
|
||||
include "rf_driver_20/1chan.cfg",
|
||||
include "rf_driver/config.cfg",
|
||||
|
||||
/* If true, allow the simulation of several UEs at the same time and
|
||||
allow dynamic UE creation from remote API */
|
||||
@@ -22,7 +22,6 @@ allow dynamic UE creation from remote API */
|
||||
cell_groups: [{
|
||||
group_type: "nr",
|
||||
multi_ue: true,
|
||||
ldpc_max_its:8,
|
||||
cells: [{
|
||||
rf_port: 0,
|
||||
bandwidth: 20,
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/* Parameters for SDR device version 2023-06-10
|
||||
* Copyright (C) 2015-2023 Amarisoft
|
||||
*/
|
||||
|
||||
#if !defined(N_CELL)
|
||||
#define N_CELL 1
|
||||
#endif
|
||||
|
||||
#if N_ANTENNA_DL <= 2
|
||||
#define N_CHAN N_CELL
|
||||
#else
|
||||
#define N_CHAN 2*N_CELL
|
||||
#endif
|
||||
|
||||
rf_driver: {
|
||||
name: "sdr",
|
||||
|
||||
/* list of devices. 'dev0' is always the master. */
|
||||
#if N_CHAN == 1
|
||||
args: "dev0=/dev/sdr0",
|
||||
#elif N_CHAN == 2
|
||||
args: "dev0=/dev/sdr0,dev1=/dev/sdr1",
|
||||
#elif N_CHAN == 3
|
||||
args: "dev0=/dev/sdr0,dev1=/dev/sdr1,dev2=/dev/sdr2",
|
||||
#elif N_CHAN == 4
|
||||
args: "dev0=/dev/sdr0,dev1=/dev/sdr1,dev2=/dev/sdr2,dev3=/dev/sdr3",
|
||||
#elif N_CHAN == 6
|
||||
args: "dev0=/dev/sdr0,dev1=/dev/sdr1,dev2=/dev/sdr2,dev3=/dev/sdr3,dev4=/dev/sdr4,dev5=/dev/sdr5",
|
||||
#else
|
||||
args: "",
|
||||
#endif
|
||||
|
||||
/* synchronisation source: internal, gps, external (default = internal) */
|
||||
// sync: "gps",
|
||||
//rx_antenna:"rx", // force to use the RX connector in TDD as RX antenna
|
||||
|
||||
/* PCIe jitter. decrease it to reduce latency */
|
||||
fifo_tx_time: 50,
|
||||
//rx_latency: 30,
|
||||
},
|
||||
|
||||
#if 0
|
||||
tx_pad_duration:300,
|
||||
#endif
|
||||
|
||||
tx_gain: 75.0, /* TX gain (in dB) */
|
||||
rx_gain: 55.0, /* RX gain (in dB) */
|
||||
+40
-38
@@ -147,125 +147,127 @@ ltebox-nepes:
|
||||
|
||||
amarisoft_ue:
|
||||
Host: amariue
|
||||
InitScript: /root/lteue-linux-2023-10-27/ue/lteue /root/oaicicd/ran_sa_aw2s_asue/aw2s-multi-00102-20.cfg &
|
||||
TermScript: /root/2023-10-27/libs/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
|
||||
InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue/aw2s-multi-00102-20.cfg &
|
||||
TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
|
||||
NetworkScript: ip netns exec ue1 ip a show dev pdn0
|
||||
amarisoft_ue_2x2:
|
||||
Host: amariue
|
||||
InitScript: /root/lteue-linux-2023-10-27/ue/lteue /root/oaicicd/ran_sa_aw2s_asue_2x2/aw2s-multi-00102-2x2-v2.cfg &
|
||||
TermScript: /root/2023-10-27/libs/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
|
||||
InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_2x2/aw2s-multi-00102-2x2-v2.cfg &
|
||||
TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
|
||||
NetworkScript: ip netns exec ue1 ip a show dev pdn0
|
||||
amarisoft_ue_fhi72:
|
||||
Host: amariue
|
||||
InitScript: /root/lteue-linux-2023-10-27/ue/lteue /root/oaicicd/ran_sa_fhi72_asue_2x2_benetel550/fhi72-multi-20897-2x2.cfg &
|
||||
TermScript: /root/2023-10-27/libs/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
|
||||
InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_fhi72_asue_2x2_benetel550/fhi72-multi-20897-2x2.cfg &
|
||||
TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
|
||||
amarisoft_ue_1:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":1}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":1}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":1}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":1}'
|
||||
NetworkScript: ip netns exec ue1 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue1
|
||||
MTU: 1500
|
||||
amarisoft_ue_2:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":2}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":2}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":2}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":2}'
|
||||
NetworkScript: ip netns exec ue2 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue2
|
||||
MTU: 1500
|
||||
amarisoft_ue_3:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":3}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":3}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":3}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":3}'
|
||||
NetworkScript: ip netns exec ue3 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue3
|
||||
MTU: 1500
|
||||
amarisoft_ue_4:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":4}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":4}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":4}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":4}'
|
||||
NetworkScript: ip netns exec ue4 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue4
|
||||
MTU: 1500
|
||||
amarisoft_ue_5:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":5}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":5}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":5}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":5}'
|
||||
NetworkScript: ip netns exec ue5 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue5
|
||||
MTU: 1500
|
||||
amarisoft_ue_6:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":6}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":6}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":6}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":6}'
|
||||
NetworkScript: ip netns exec ue6 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue6
|
||||
MTU: 1500
|
||||
amarisoft_ue_7:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":7}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":7}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":7}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":7}'
|
||||
NetworkScript: ip netns exec ue7 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue7
|
||||
MTU: 1500
|
||||
amarisoft_ue_8:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":8}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":8}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":8}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":8}'
|
||||
NetworkScript: ip netns exec ue8 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue8
|
||||
MTU: 1500
|
||||
amarisoft_ue_9:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":9}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":9}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":9}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":9}'
|
||||
NetworkScript: ip netns exec ue9 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue9
|
||||
MTU: 1500
|
||||
amarisoft_ue_10:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":10}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":10}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":10}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":10}'
|
||||
NetworkScript: ip netns exec ue10 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue10
|
||||
MTU: 1500
|
||||
amarisoft_ue_11:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":11}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":11}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":11}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":11}'
|
||||
NetworkScript: ip netns exec ue11 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue11
|
||||
MTU: 1500
|
||||
amarisoft_ue_12:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":12}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":12}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":12}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":12}'
|
||||
NetworkScript: ip netns exec ue12 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue12
|
||||
MTU: 1500
|
||||
amarisoft_ue_13:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":13}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":13}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":13}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":13}'
|
||||
NetworkScript: ip netns exec ue13 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue13
|
||||
MTU: 1500
|
||||
amarisoft_ue_14:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":14}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":14}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":14}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":14}'
|
||||
NetworkScript: ip netns exec ue14 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue14
|
||||
MTU: 1500
|
||||
amarisoft_ue_15:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":15}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":15}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":15}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":15}'
|
||||
NetworkScript: ip netns exec ue15 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue15
|
||||
MTU: 1500
|
||||
amarisoft_ue_16:
|
||||
Host: amariue
|
||||
AttachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":16}'
|
||||
DetachScript: /root/2023-10-27/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":16}'
|
||||
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":16}'
|
||||
DetachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":16}'
|
||||
NetworkScript: ip netns exec ue16 ip a show dev pdn0
|
||||
CmdPrefix: ip netns exec ue16
|
||||
MTU: 1500
|
||||
|
||||
@@ -58,6 +58,14 @@ gNBs =
|
||||
}
|
||||
);
|
||||
|
||||
pdcp = {
|
||||
drb = {
|
||||
sn_size = "len18bits"
|
||||
t_reordering = "ms100"
|
||||
discard_timer = "infinity"
|
||||
}
|
||||
}
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
|
||||
@@ -163,6 +163,31 @@ gNBs =
|
||||
}
|
||||
);
|
||||
|
||||
rlc = {
|
||||
srb = {
|
||||
t_poll_retransmit = "ms45"
|
||||
t_reassembly = "ms25"
|
||||
t_status_prohibit = "ms0"
|
||||
poll_pdu = "infinity"
|
||||
poll_byte = "infinity"
|
||||
max_retx_threshold = "t8"
|
||||
sn_field_length = "size12"
|
||||
}
|
||||
drb_am = {
|
||||
t_poll_retransmit = "ms45"
|
||||
t_reassembly = "ms15"
|
||||
t_status_prohibit = "ms15"
|
||||
poll_pdu = "p64"
|
||||
poll_byte = "kB500"
|
||||
max_retx_threshold = "t32"
|
||||
sn_field_length = "size18"
|
||||
}
|
||||
drb_um = {
|
||||
t_reassembly = "ms15"
|
||||
sn_field_length = "size12"
|
||||
}
|
||||
}
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
|
||||
@@ -21,7 +21,6 @@ gNBs =
|
||||
|
||||
sib1_tda = 15;
|
||||
min_rxtxtime = 6;
|
||||
beam_weights = [0]; // single SSB -> one analog beam
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
@@ -179,6 +178,7 @@ MACRLCs = ({
|
||||
set_analog_beamforming = 1;
|
||||
beam_duration = 1;
|
||||
beams_per_period = 1;
|
||||
beam_weights = [0]; // single SSB -> one analog beam
|
||||
});
|
||||
|
||||
L1s = (
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
000001
|
||||
000002
|
||||
000003
|
||||
002001
|
||||
010000
|
||||
000004
|
||||
333333
|
||||
@@ -40,7 +39,6 @@
|
||||
010002
|
||||
010003
|
||||
020005
|
||||
010013
|
||||
002006
|
||||
444444
|
||||
100002
|
||||
@@ -50,12 +48,6 @@
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="002001">
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep</desc>
|
||||
<idle_sleep_time_in_sec>10</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
<testCase id="111110">
|
||||
<class>Pull_Local_Registry</class>
|
||||
<desc>Pull Images from Local Registry</desc>
|
||||
@@ -173,43 +165,39 @@
|
||||
</testCase>
|
||||
|
||||
<testCase id="010000">
|
||||
<class>Custom_Command</class>
|
||||
<class>Deploy_Object</class>
|
||||
<desc>RC monitoring</desc>
|
||||
<node>localhost</node>
|
||||
<command_fail>yes</command_fail>
|
||||
<command>docker exec oai-flexric bash -c "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_rc_moni" > ../cmake_targets/log/5g_rfsimulator_flexric/rc-moni-010000.log</command>
|
||||
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_flexric</yaml_path>
|
||||
<services>xapp-rc-moni</services>
|
||||
<eNB_instance>0</eNB_instance>
|
||||
<eNB_serverId>0</eNB_serverId>
|
||||
</testCase>
|
||||
|
||||
<testCase id="010001">
|
||||
<class>Custom_Command</class>
|
||||
<class>Deploy_Object</class>
|
||||
<desc>KPM monitoring</desc>
|
||||
<node>localhost</node>
|
||||
<command_fail>yes</command_fail>
|
||||
<command>docker exec oai-flexric bash -c "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_kpm_moni" > ../cmake_targets/log/5g_rfsimulator_flexric/kpm-moni-010001.log</command>
|
||||
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_flexric</yaml_path>
|
||||
<services>xapp-kpm-moni</services>
|
||||
<eNB_instance>0</eNB_instance>
|
||||
<eNB_serverId>0</eNB_serverId>
|
||||
</testCase>
|
||||
|
||||
<testCase id="010002">
|
||||
<class>Custom_Command</class>
|
||||
<class>Deploy_Object</class>
|
||||
<desc>KPM monitoring and RC control</desc>
|
||||
<node>localhost</node>
|
||||
<command_fail>yes</command_fail>
|
||||
<command>docker exec oai-flexric bash -c "stdbuf -o0 /usr/local/flexric/xApp/c/kpm_rc/xapp_kpm_rc" > ../cmake_targets/log/5g_rfsimulator_flexric/kpm_rc-010002.log</command>
|
||||
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_flexric</yaml_path>
|
||||
<services>xapp-kpm-rc</services>
|
||||
<eNB_instance>0</eNB_instance>
|
||||
<eNB_serverId>0</eNB_serverId>
|
||||
</testCase>
|
||||
|
||||
<testCase id="010003">
|
||||
<class>Custom_Command</class>
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Custom SMs monitoring</desc>
|
||||
<node>localhost</node>
|
||||
<command_fail>yes</command_fail>
|
||||
<command>docker exec oai-flexric bash -c "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_moni" > ../cmake_targets/log/5g_rfsimulator_flexric/sms-moni-010003.log</command>
|
||||
</testCase>
|
||||
|
||||
<testCase id="010013">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Custom SMs monitoring</desc>
|
||||
<node>localhost</node>
|
||||
<command_fail>yes</command_fail>
|
||||
<command>docker exec oai-flexric bash -c "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_moni" > ../cmake_targets/log/5g_rfsimulator_flexric/sms-moni-010013.log</command>
|
||||
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_flexric</yaml_path>
|
||||
<services>xapp-gtp-mac-rlc-pdcp-moni</services>
|
||||
<eNB_instance>0</eNB_instance>
|
||||
<eNB_serverId>0</eNB_serverId>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[NEAR-RIC]
|
||||
NEAR_RIC_IP = 192.168.70.150
|
||||
|
||||
[XAPP]
|
||||
DB_PATH = /flexric/db/
|
||||
DB_NAME = xapp_rnis_db
|
||||
DB_DIR = /tmp/
|
||||
|
||||
@@ -7,12 +7,79 @@ services:
|
||||
ipv4_address: 192.168.70.150
|
||||
volumes:
|
||||
- ./conf/flexric.conf:/usr/local/etc/flexric/flexric.conf
|
||||
- sharedXappLibs:/usr/local/lib/flexric/
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep nearRT-RIC"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
|
||||
xapp-rc-moni:
|
||||
image: ${REGISTRY:-oaisoftwarealliance}/oai-flexric:${FLEXRIC_TAG:-develop}
|
||||
command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_rc_moni"
|
||||
container_name: xapp-rc-moni
|
||||
depends_on:
|
||||
- oai-flexric
|
||||
- oai-gnb
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.70.154
|
||||
volumes:
|
||||
- ./conf/flexric.conf:/usr/local/etc/flexric/flexric.conf
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep xapp_rc_moni"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
|
||||
xapp-kpm-moni:
|
||||
image: ${REGISTRY:-oaisoftwarealliance}/oai-flexric:${FLEXRIC_TAG:-develop}
|
||||
command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_kpm_moni"
|
||||
container_name: xapp-kpm-moni
|
||||
depends_on:
|
||||
- oai-flexric
|
||||
- oai-gnb
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.70.155
|
||||
volumes:
|
||||
- ./conf/flexric.conf:/usr/local/etc/flexric/flexric.conf
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep xapp_kpm_moni"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
|
||||
xapp-kpm-rc:
|
||||
image: ${REGISTRY:-oaisoftwarealliance}/oai-flexric:${FLEXRIC_TAG:-develop}
|
||||
command: "stdbuf -o0 /usr/local/flexric/xApp/c/kpm_rc/xapp_kpm_rc"
|
||||
container_name: xapp-kpm-rc
|
||||
depends_on:
|
||||
- oai-flexric
|
||||
- oai-gnb
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.70.156
|
||||
volumes:
|
||||
- ./conf/flexric.conf:/usr/local/etc/flexric/flexric.conf
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep xapp_kpm_rc"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
|
||||
xapp-gtp-mac-rlc-pdcp-moni:
|
||||
image: ${REGISTRY:-oaisoftwarealliance}/oai-flexric:${FLEXRIC_TAG:-develop}
|
||||
command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_moni"
|
||||
container_name: xapp-gtp-mac-rlc-pdcp-moni
|
||||
depends_on:
|
||||
- oai-flexric
|
||||
- oai-gnb
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.70.157
|
||||
volumes:
|
||||
- ./conf/flexric.conf:/usr/local/etc/flexric/flexric.conf
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep -f xapp_gtp_mac_rlc_pdcp_moni"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
|
||||
oai-gnb:
|
||||
image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop}
|
||||
privileged: true
|
||||
@@ -27,7 +94,6 @@ services:
|
||||
ipv4_address: 192.168.70.151
|
||||
volumes:
|
||||
- ../../conf_files/gnb.sa.band78.106prb.rfsim.flexric.conf:/opt/oai-gnb/etc/gnb.conf
|
||||
- sharedXappLibs:/usr/local/lib/flexric/
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep nr-softmodem"
|
||||
interval: 10s
|
||||
@@ -72,9 +138,6 @@ services:
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
sharedXappLibs:
|
||||
|
||||
networks:
|
||||
public_net:
|
||||
name: oai-cn5g-public-net
|
||||
|
||||
@@ -308,3 +308,63 @@ void config_assign_int(configmodule_interface_t *cfg, paramdef_t *cfgoptions, ch
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns the default value to a configuration parameter if available.
|
||||
*
|
||||
* This function checks the type of the parameter and assigns its default value
|
||||
* if it is defined. It handles various parameter types, including strings, integers,
|
||||
* arrays, doubles, IPv4 addresses, and lists. If the parameter is marked with
|
||||
* PARAMFLAG_DONOTREAD, it is ignored.
|
||||
*
|
||||
* @param[in] cfg Pointer to the configuration module interface.
|
||||
* @param[in] cfgoption Pointer to the parameter definition structure.
|
||||
* @param[in] prefix Optional prefix for the parameter name (can be NULL).
|
||||
* @return 1 if the default value was set, 0 if ignored, or -1 on error/unsupported type.
|
||||
*/
|
||||
int config_common_getdefault(configmodule_interface_t *cfg, paramdef_t *cfgoption, char *prefix)
|
||||
{
|
||||
if( (cfgoption->paramflags & PARAMFLAG_DONOTREAD) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(cfgoption->type) {
|
||||
case TYPE_STRING:
|
||||
return config_setdefault_string(cfg, cfgoption, prefix);
|
||||
|
||||
case TYPE_STRINGLIST:
|
||||
return config_setdefault_stringlist(cfg, cfgoption, prefix);
|
||||
|
||||
case TYPE_UINT8:
|
||||
case TYPE_INT8:
|
||||
case TYPE_UINT16:
|
||||
case TYPE_INT16:
|
||||
case TYPE_UINT32:
|
||||
case TYPE_INT32:
|
||||
case TYPE_MASK:
|
||||
return config_setdefault_int(cfg, cfgoption, prefix);
|
||||
|
||||
case TYPE_UINT64:
|
||||
case TYPE_INT64:
|
||||
return config_setdefault_int64(cfg, cfgoption, prefix);
|
||||
|
||||
case TYPE_UINTARRAY:
|
||||
case TYPE_INTARRAY:
|
||||
return config_setdefault_intlist(cfg, cfgoption, prefix);
|
||||
|
||||
case TYPE_DOUBLE:
|
||||
return config_setdefault_double(cfg, cfgoption, prefix);
|
||||
|
||||
case TYPE_IPV4ADDR:
|
||||
return config_setdefault_ipv4addr(cfg, cfgoption, prefix);
|
||||
|
||||
case TYPE_LIST:
|
||||
// No default value for list type
|
||||
fprintf(stderr,"[CONFIG] %s.%s TYPE_LIST has no default value\n", prefix, cfgoption->optname);
|
||||
return -1;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"[CONFIG] %s.%s type %i not supported\n", prefix, cfgoption->optname, cfgoption->type);
|
||||
return -1;
|
||||
} /* switch on param type */
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ int config_setdefault_double(configmodule_interface_t *cfg, paramdef_t *cfgoptio
|
||||
int config_setdefault_ipv4addr(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix);
|
||||
void *config_allocate_new(configmodule_interface_t *cfg, int sz, bool autoFree);
|
||||
void config_assign_int(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *fullname, int val);
|
||||
int config_common_getdefault(configmodule_interface_t *cfg, paramdef_t *cfgoption, char *prefix);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
#define PARAMFLAG_PARAMSETDEF (1 << 17) // parameter has been set to default value in get functions
|
||||
|
||||
/* checkedparam_t is possibly used in paramdef_t for specific parameter value validation */
|
||||
#define CONFIG_MAX_NUMCHECKVAL 20
|
||||
#define CONFIG_MAX_NUMCHECKVAL 64
|
||||
typedef struct paramdef paramdef_t;
|
||||
typedef struct configmodule_interface configmodule_interface_t;
|
||||
typedef union checkedparam {
|
||||
@@ -169,7 +169,6 @@ typedef struct paramlist_def {
|
||||
|
||||
/* Macros to get parameters with the config module API */
|
||||
#define GET_PARAMS(param_def, param_desc, prefix) \
|
||||
printf("Reading '%s' section from the config file\n", #param_def); \
|
||||
paramdef_t param_def[] = param_desc; \
|
||||
config_get(config_get_if(), param_def, sizeofArray(param_def), prefix);
|
||||
|
||||
|
||||
@@ -356,7 +356,7 @@ int config_libconfig_get(configmodule_interface_t *cfg, paramdef_t *cfgoptions,
|
||||
snprintf( *cfgoptions[i].strptr , cfgoptions[i].numelt, "%s", str);
|
||||
printf_params(cfg, "[LIBCONFIG] %s: \"%s\"\n", cfgpath, *cfgoptions[i].strptr);
|
||||
} else {
|
||||
defval = config_setdefault_string(cfg, &cfgoptions[i], prefix);
|
||||
defval = config_common_getdefault(cfg, &cfgoptions[i], prefix);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -367,7 +367,7 @@ int config_libconfig_get(configmodule_interface_t *cfg, paramdef_t *cfgoptions,
|
||||
if ( setting != NULL) {
|
||||
read_strlist(cfg, &cfgoptions[i], setting, cfgpath);
|
||||
} else {
|
||||
defval = config_setdefault_stringlist(cfg, &(cfgoptions[i]), prefix);
|
||||
defval = config_common_getdefault(cfg, &(cfgoptions[i]), prefix);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -383,7 +383,7 @@ int config_libconfig_get(configmodule_interface_t *cfg, paramdef_t *cfgoptions,
|
||||
config_check_valptr(cfg, &(cfgoptions[i]), sizeof(*cfgoptions[i].iptr), 1);
|
||||
config_assign_int(cfg, &(cfgoptions[i]), cfgpath, u);
|
||||
} else {
|
||||
defval = config_setdefault_int(cfg, &(cfgoptions[i]), prefix);
|
||||
defval = config_common_getdefault(cfg, &(cfgoptions[i]), prefix);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -401,7 +401,7 @@ int config_libconfig_get(configmodule_interface_t *cfg, paramdef_t *cfgoptions,
|
||||
printf_params(cfg, "[LIBCONFIG] %s: %ld\n", cfgpath, *cfgoptions[i].i64ptr);
|
||||
}
|
||||
} else {
|
||||
defval = config_setdefault_int64(cfg, &(cfgoptions[i]), prefix);
|
||||
defval = config_common_getdefault(cfg, &(cfgoptions[i]), prefix);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -413,7 +413,7 @@ int config_libconfig_get(configmodule_interface_t *cfg, paramdef_t *cfgoptions,
|
||||
if ( setting != NULL) {
|
||||
read_intarray(cfg, &cfgoptions[i], setting, cfgpath);
|
||||
} else {
|
||||
defval = config_setdefault_intlist(cfg, &(cfgoptions[i]), prefix);
|
||||
defval = config_common_getdefault(cfg, &(cfgoptions[i]), prefix);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -424,14 +424,14 @@ int config_libconfig_get(configmodule_interface_t *cfg, paramdef_t *cfgoptions,
|
||||
*cfgoptions[i].dblptr = dbl;
|
||||
printf_params(cfg, "[LIBCONFIG] %s: %lf\n", cfgpath, *(cfgoptions[i].dblptr));
|
||||
} else {
|
||||
defval = config_setdefault_double(cfg, &(cfgoptions[i]), prefix);
|
||||
defval = config_common_getdefault(cfg, &(cfgoptions[i]), prefix);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TYPE_IPV4ADDR:
|
||||
if ( !config_lookup_string(&(libconfig_privdata.cfg),cfgpath, (const char **)&str)) {
|
||||
defval = config_setdefault_ipv4addr(cfg, &(cfgoptions[i]), prefix);
|
||||
defval = config_common_getdefault(cfg, &(cfgoptions[i]), prefix);
|
||||
} else {
|
||||
int rst = config_assign_ipv4addr(cfg, cfgoptions, str);
|
||||
|
||||
|
||||
@@ -25,8 +25,7 @@ extern "C" {
|
||||
#include "common/config/config_userapi.h"
|
||||
void *config_allocate_new(configmodule_interface_t *cfg, int sz, bool autoFree);
|
||||
void config_check_valptr(configmodule_interface_t *cfg, paramdef_t *cfgoptions, int elt_sz, int nb_elt);
|
||||
#include "../config_userapi.h"
|
||||
#include "../config_common.h"
|
||||
int config_common_getdefault(configmodule_interface_t *cfg, paramdef_t *cfgoption, char *prefix);
|
||||
}
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
@@ -44,71 +43,6 @@ class YamlConfig {
|
||||
}
|
||||
};
|
||||
|
||||
void SetDefault(configmodule_interface_t *cfg, paramdef_t *param)
|
||||
{
|
||||
switch (param->type) {
|
||||
case TYPE_INT:
|
||||
*param->iptr = param->defintval;
|
||||
break;
|
||||
case TYPE_UINT:
|
||||
*param->uptr = param->defuintval;
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
if (param->defstrval != nullptr) {
|
||||
if (param->numelt == 0) {
|
||||
config_check_valptr(cfg, param, 1, strlen(param->defstrval) + 1);
|
||||
}
|
||||
sprintf(*param->strptr, "%s", param->defstrval);
|
||||
}
|
||||
break;
|
||||
case TYPE_INT8:
|
||||
*param->i8ptr = param->defintval;
|
||||
break;
|
||||
case TYPE_UINT8:
|
||||
*param->u8ptr = param->defuintval;
|
||||
break;
|
||||
case TYPE_INT16:
|
||||
*param->i16ptr = param->defintval;
|
||||
break;
|
||||
case TYPE_UINT16:
|
||||
*param->u16ptr = param->defuintval;
|
||||
break;
|
||||
case TYPE_INT64:
|
||||
*param->i64ptr = param->defint64val;
|
||||
break;
|
||||
case TYPE_UINT64:
|
||||
*param->u64ptr = param->defint64val;
|
||||
break;
|
||||
case TYPE_DOUBLE:
|
||||
*param->dblptr = param->defdblval;
|
||||
break;
|
||||
case TYPE_MASK:
|
||||
*param->uptr = param->defuintval;
|
||||
break;
|
||||
case TYPE_STRINGLIST:
|
||||
if (param->defstrlistval != nullptr) {
|
||||
param->strlistptr = param->defstrlistval;
|
||||
}
|
||||
break;
|
||||
case TYPE_INTARRAY:
|
||||
if (param->defintarrayval) {
|
||||
param->iptr = param->defintarrayval;
|
||||
}
|
||||
break;
|
||||
case TYPE_UINTARRAY:
|
||||
if (param->defintarrayval) {
|
||||
param->uptr = (uint32_t *)param->defintarrayval;
|
||||
}
|
||||
break;
|
||||
case TYPE_IPV4ADDR:
|
||||
config_setdefault_ipv4addr(cfg, param, param->defstrval);
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "Unhandled type %d", param->type);
|
||||
}
|
||||
param->paramflags |= PARAMFLAG_PARAMSETDEF;
|
||||
}
|
||||
|
||||
void SetNonDefault(configmodule_interface_t *cfg, const YAML::Node &node, paramdef_t *param)
|
||||
{
|
||||
auto optname = std::string(param->optname);
|
||||
@@ -207,14 +141,12 @@ void SetNonDefault(configmodule_interface_t *cfg, const YAML::Node &node, paramd
|
||||
param->paramflags |= PARAMFLAG_PARAMSET;
|
||||
}
|
||||
|
||||
void GetParams(configmodule_interface_t *cfg, const YAML::Node &node, paramdef_t *params, int num_params)
|
||||
void GetParam(configmodule_interface_t *cfg, const YAML::Node &node, paramdef_t *param)
|
||||
{
|
||||
for (auto i = 0; i < num_params; i++) {
|
||||
if (node && node[std::string(params[i].optname)]) {
|
||||
SetNonDefault(cfg, node, ¶ms[i]);
|
||||
} else {
|
||||
SetDefault(cfg, ¶ms[i]);
|
||||
}
|
||||
if (node && node[std::string(param->optname)]) {
|
||||
SetNonDefault(cfg, node, param);
|
||||
} else {
|
||||
config_common_getdefault(cfg, param, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +161,15 @@ extern "C" int config_yaml_init(configmodule_interface_t *cfg)
|
||||
pthread_mutex_init(&cfg->memBlocks_mutex, NULL);
|
||||
memset(cfg->oneBlock, 0, sizeof(cfg->oneBlock));
|
||||
|
||||
config_yaml::config = new config_yaml::YamlConfig(std::string(cfgP[0]));
|
||||
try {
|
||||
config_yaml::config = new config_yaml::YamlConfig(std::string(cfgP[0]));
|
||||
} catch (const YAML::BadFile &e) {
|
||||
fprintf(stderr, "[CONFIG] Error loading YAML file '%s': %s\n", cfgP[0], e.what());
|
||||
return -1;
|
||||
} catch (const YAML::Exception &e) {
|
||||
fprintf(stderr, "[CONFIG] Error parsing YAML file '%s': %s\n", cfgP[0], e.what());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -249,14 +189,14 @@ YAML::Node find_node(const std::string &prefix, YAML::Node node)
|
||||
if (key.at(0) == '[' && key.back() == ']') {
|
||||
// The key is an index to a sequence
|
||||
if (!current.IsSequence()) {
|
||||
throw std::invalid_argument("Incorrect yaml file structure");
|
||||
throw std::invalid_argument("Expected a sequence at " + key);
|
||||
}
|
||||
int index = std::stoi(key.substr(1, key.size() - 2));
|
||||
current = current[index];
|
||||
continue;
|
||||
}
|
||||
if (!current.IsMap()) {
|
||||
throw std::invalid_argument("Incorrect yaml file structure");
|
||||
throw std::invalid_argument("Expected a map at " + key);
|
||||
}
|
||||
if (!current[key]) {
|
||||
return config_yaml::invalid_node;
|
||||
@@ -272,8 +212,14 @@ extern "C" int config_yaml_get(configmodule_interface_t *cfg, paramdef_t *cfgopt
|
||||
if (prefix != nullptr) {
|
||||
p = std::string(prefix);
|
||||
}
|
||||
auto node = find_node(p, YAML::Clone(config_yaml::config->config));
|
||||
if (node == config_yaml::invalid_node) {
|
||||
YAML::Node node;
|
||||
try {
|
||||
node = find_node(p, YAML::Clone(config_yaml::config->config));
|
||||
if (node == config_yaml::invalid_node) {
|
||||
return -1;
|
||||
}
|
||||
} catch (const std::invalid_argument &e) {
|
||||
fprintf(stderr, "[CONFIG] Error finding node '%s': %s\n", p.c_str(), e.what());
|
||||
return -1;
|
||||
}
|
||||
for (auto i = 0; i < numoptions; i++) {
|
||||
@@ -282,7 +228,14 @@ extern "C" int config_yaml_get(configmodule_interface_t *cfg, paramdef_t *cfgopt
|
||||
config_check_valptr(cfg, &cfgoptions[i], sizeof(void *), 1);
|
||||
}
|
||||
}
|
||||
config_yaml::GetParams(cfg, node, cfgoptions, numoptions);
|
||||
for (int i = 0; i < numoptions; i++) {
|
||||
try {
|
||||
config_yaml::GetParam(cfg, node, &cfgoptions[i]);
|
||||
} catch (const YAML::Exception &e) {
|
||||
fprintf(stderr, "[CONFIG] Config error: prefix: %s, setting: %s, error: %s\n", p.c_str(), cfgoptions[i].optname, e.what());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return numoptions;
|
||||
}
|
||||
|
||||
@@ -323,7 +276,14 @@ extern "C" int config_yaml_getlist(configmodule_interface_t *cfg,
|
||||
}
|
||||
}
|
||||
|
||||
config_yaml::GetParams(cfg, node[i], ParamList->paramarray[i], numparams);
|
||||
for (int j = 0; j < numparams; j++) {
|
||||
try {
|
||||
config_yaml::GetParam(cfg, node[i], &ParamList->paramarray[i][j]);
|
||||
} catch (const YAML::Exception &e) {
|
||||
fprintf(stderr, "[CONFIG] Config error: prefix: %s, setting: %s, error: %s\n", path, ParamList->paramarray[i][j].optname, e.what());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,3 +11,5 @@ configure_file(test_list_of_mappings.yml test_list_of_mappings.yml COPYONLY)
|
||||
configure_file(test_int_array.yaml test_int_array.yaml COPYONLY)
|
||||
configure_file(test_read_mapping_as_list.yaml test_read_mapping_as_list.yaml COPYONLY)
|
||||
configure_file(test_ipv4.yaml test_ipv4.yaml COPYONLY)
|
||||
configure_file(test_read_str_as_int.yaml test_read_str_as_int.yaml COPYONLY)
|
||||
configure_file(malformed.yaml malformed.yaml COPYONLY)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
test:
|
||||
-
|
||||
bad_file:
|
||||
- "testvalue1"
|
||||
- "testvalue2"
|
||||
- "testvalue3"
|
||||
- "testvalue4"
|
||||
- "testvalue5"
|
||||
- "testvalue6"
|
||||
- "testvalue7"
|
||||
- "testvalue8"
|
||||
- "testvalue9"
|
||||
- "testvalue10" - yaml error
|
||||
@@ -0,0 +1,2 @@
|
||||
test:
|
||||
var: "test_var"
|
||||
@@ -78,8 +78,9 @@ TEST(yaml_config, yaml_get_existing_values) {
|
||||
uint16_t value;
|
||||
p.type = TYPE_UINT16;
|
||||
p.u16ptr = &value;
|
||||
p.paramflags = PARAMFLAG_MANDATORY;
|
||||
char prefix[] = "test";
|
||||
config_yaml_get(cfg, &p, 1, prefix);
|
||||
EXPECT_EQ(config_yaml_get(cfg, &p, 1, prefix), 1);
|
||||
EXPECT_EQ(value, i);
|
||||
}
|
||||
|
||||
@@ -94,7 +95,7 @@ TEST(yaml_config, yaml_get_non_existing_values) {
|
||||
cfg->cfgP[0] = strdup("test1.yaml");
|
||||
EXPECT_EQ(config_yaml_init(cfg), 0);
|
||||
|
||||
// Testing paremters present in the test node
|
||||
// Testing parameters not present in the test node
|
||||
paramdef_t p = {0};
|
||||
for (auto i = 4; i <= 5; i++) {
|
||||
sprintf(p.optname, "%s%d", "value", i);
|
||||
@@ -421,6 +422,43 @@ TEST(yaml_config, test_read_ipv4) {
|
||||
free(p.defstrval);
|
||||
}
|
||||
|
||||
TEST(yaml_config, yaml_read_str_as_int) {
|
||||
configmodule_interface_t *cfg = static_cast<configmodule_interface_t*>(calloc(1, sizeof(*cfg)));
|
||||
cfg->cfgP[0] = strdup("test_read_str_as_int.yaml");
|
||||
EXPECT_EQ(config_yaml_init(cfg), 0);
|
||||
|
||||
// Testing paremters present in the test node
|
||||
paramdef_t p = {0};
|
||||
uint16_t value;
|
||||
p.type = TYPE_UINT16;
|
||||
p.u16ptr = &value;
|
||||
p.paramflags = PARAMFLAG_MANDATORY;
|
||||
char prefix[] = "test";
|
||||
sprintf(p.optname, "%s", "var");
|
||||
EXPECT_EQ(config_yaml_get(cfg, &p, 1, prefix), -1);
|
||||
|
||||
|
||||
config_yaml_end(cfg);
|
||||
free(cfg->cfgP[0]);
|
||||
end_configmodule(cfg);
|
||||
}
|
||||
|
||||
TEST(yaml_config, yaml_open_non_existing_file) {
|
||||
configmodule_interface_t *cfg = static_cast<configmodule_interface_t*>(calloc(1, sizeof(*cfg)));
|
||||
cfg->cfgP[0] = strdup("non_existing_file.yaml");
|
||||
EXPECT_EQ(config_yaml_init(cfg), -1);
|
||||
free(cfg->cfgP[0]);
|
||||
end_configmodule(cfg);
|
||||
}
|
||||
|
||||
TEST(yaml_config, malformed_file) {
|
||||
configmodule_interface_t *cfg = static_cast<configmodule_interface_t*>(calloc(1, sizeof(*cfg)));
|
||||
cfg->cfgP[0] = strdup("malformed.yaml");
|
||||
EXPECT_EQ(config_yaml_init(cfg), -1);
|
||||
free(cfg->cfgP[0]);
|
||||
end_configmodule(cfg);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
logInit();
|
||||
|
||||
@@ -34,6 +34,9 @@ SOFTWARE.
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define FOR_EACH_SEQ_ARR(type, var, arr) \
|
||||
for (type var = seq_arr_front(arr); var != seq_arr_end(arr); var = seq_arr_next(arr, var))
|
||||
|
||||
typedef struct seq_arr_s {
|
||||
uint8_t* data;
|
||||
size_t size;
|
||||
|
||||
@@ -475,41 +475,5 @@ typedef struct timer_elm_s {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void log_scheduler(const char* label)
|
||||
{
|
||||
int policy = sched_getscheduler(0);
|
||||
struct sched_param param;
|
||||
if (sched_getparam(0, ¶m) == -1)
|
||||
{
|
||||
LOG_E(HW, "sched_getparam: %s\n", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
|
||||
cpu_set_t cpu_set;
|
||||
if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) == -1)
|
||||
{
|
||||
LOG_E(HW, "sched_getaffinity: %s\n", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (num_cpus < 1)
|
||||
{
|
||||
LOG_E(HW, "sysconf(_SC_NPROCESSORS_ONLN): %s\n", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
char buffer[num_cpus];
|
||||
for (int i = 0; i < num_cpus; i++)
|
||||
{
|
||||
buffer[i] = CPU_ISSET(i, &cpu_set) ? 'Y' : '-';
|
||||
}
|
||||
|
||||
LOG_A(HW, "Scheduler policy=%d priority=%d affinity=[%d]%.*s label=%s\n",
|
||||
policy,
|
||||
param.sched_priority,
|
||||
num_cpus,
|
||||
num_cpus,
|
||||
buffer,
|
||||
label);
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
|
||||
@@ -566,7 +566,6 @@ int timer_remove(long timer_id);
|
||||
int signal_handle(int *end);
|
||||
int signal_mask(void);
|
||||
|
||||
void log_scheduler(const char *label);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7,34 +7,6 @@
|
||||
#include <errno.h>
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
|
||||
const char *hexdump(const void *data, size_t data_len, char *out, size_t out_len)
|
||||
{
|
||||
char *p = out;
|
||||
char *endp = out + out_len;
|
||||
const uint8_t *q = data;
|
||||
snprintf(p, endp - p, "[%zu]", data_len);
|
||||
p += strlen(p);
|
||||
for (size_t i = 0; i < data_len; ++i)
|
||||
{
|
||||
if (p >= endp)
|
||||
{
|
||||
static const char ellipses[] = "...";
|
||||
char *s = endp - sizeof(ellipses);
|
||||
if (s >= p)
|
||||
{
|
||||
strcpy(s, ellipses);
|
||||
}
|
||||
break;
|
||||
}
|
||||
snprintf(p, endp - p, " %02X", *q++);
|
||||
p += strlen(p);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
** **
|
||||
** Name: hex_char_to_hex_value() **
|
||||
|
||||
@@ -109,8 +109,6 @@ static inline void *malloc_or_fail(size_t size)
|
||||
#define PAGE_MASK 0xfffff000
|
||||
#define virt_to_phys(x) (x)
|
||||
|
||||
const char *hexdump(const void *data, size_t data_len, char *out, size_t out_len);
|
||||
|
||||
// Converts an hexadecimal ASCII coded digit into its value. **
|
||||
int hex_char_to_hex_value (char c);
|
||||
// Converts an hexadecimal ASCII coded string into its value.**
|
||||
|
||||
@@ -10,6 +10,8 @@ There are three main beamforming techinques: analog, digital and hybrid. The nam
|
||||
|
||||
The presence of a limited number of predefined beams at RU poses constraints to the scheduler at gNB. As a matter of fact, the scheduler can serve only a limited number of beams, depending on the RU characteristics (possibly only 1), in a given time scale, that also depends on the RU characteristics (e.g. 1 slot or 1 symbol). This limitation doesn't exist for digital beamforming.
|
||||
|
||||
Analog beamforming implementation also allows to enable distributed antenna systems (DAS), where each beam corrisponds to one antenna (or a set of antennas) of the system. In this scenario, the scheduler constaint is alleviated because normally the number of concurrent beams allowed equals the total number of beams.
|
||||
|
||||
# Configuration file fields for analog beamforming
|
||||
|
||||
A set of parameters in configuration files controls the implementation of analog beamforming and instructs the scheduler on how to behave in such scenarios. Since most notably this technique in 5G is employed in FR2, the configuration file example currently available is a RFsim one for band 261. [Config file example](../ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf)
|
||||
@@ -18,8 +20,9 @@ In the `MACRLC` section of configuration files, there are three new parameters:
|
||||
- `set_analog_beamforming` can be set to 1 or 0 to activate or desactivate analog beamforming (default value is 0)
|
||||
- `beam_duration` is the number of slots (currently minimum duration of a beam) the scheduler is tied to a beam (default value is 1)
|
||||
- `beams_per_period` is the number of concurrent beams the RU can handle in the beam duration (default value is 1)
|
||||
- `beam_weights` is a vector field containing the set of beam indices to be provided by the OAI L1 to the RU is also required. In current implementation, the number of beam indices should be equal to the number of SSBs transmitted
|
||||
|
||||
In the `gNBs` section of the configuration file, under the phyisical parameters, a vector field containing the set of beam indices to be provided by the OAI L1 to the RU is also required. This field is called `beam_weights`. In current implementation, the number of beam indices should be equal to the number of SSBs transmitted.
|
||||
DAS is enabled by setting to 1 the parameter `enable_das` in the L1 section of the configuration file. In case of DAS enabled, the field `beam_weights` in `MACRLC` section can be omitted.
|
||||
|
||||
# Implementation in OAI scheduler
|
||||
|
||||
@@ -28,3 +31,28 @@ This matrix contains the beams already allocated in a given slot, to flag the sc
|
||||
To this goal, we extended the virtual resource block (VRB) map by one dimension to also contain information per allocated beam. As said, the scheduler can independently schedule users in a number of beams up to `beams_per_period` concurrently.
|
||||
|
||||
It is important to note that in current implementation, there are several periodical channels, e.g. PRACH or PUCCH for CSI et cetera, that have the precendence in being assigned a beam, that is because the scheduling is automatic, set in RRC configuration, and not up to the scheduler. For these instances, we assume the beam is available (if not there are assertions to stop the process). For data channels, the currently implemented PF scheduler is used. The only modification is that a UE can be served only if there is a free beam available or the one of the beams already in use correspond to that UE beam.
|
||||
|
||||
# FAPI implementation
|
||||
|
||||
To be noted that in our implementation analog beamforming is only supported in non-split/monolithic mode because we don't support yet SCF P19 interface that would be needed to manage these procedure in a split scenario with SCF FAPI.
|
||||
|
||||
In `config_request` structure, a vendor extension (`nfapi_nr_analog_beamforming_ve_t`) configures the lower layers at initialization with the following information:
|
||||
- `analog_bf_vendor_ext` which can assume values 1 or 0 for enabling or disabling analog beamforming
|
||||
- `num_beams_period_vendor_ext` which corresponds to the configuration parameter `beams_per_period`
|
||||
- `total_num_beams_vendor_ext` which corresponds to the number of beams configured in `beam_weights`
|
||||
- `analog_beam_list` which contains the RU beamforming indices configured in `beam_weights`
|
||||
|
||||
Additionally, L2 provides in each channel FAPI message information about the beam index. Small Cell Forum (SCF) FAPI provides in its PHY API specifications for the channels only a field for digital beamforming as part of the `precoding_and_beamforming` stucture. Therefore without a better option, we are currently using that one to store the internal analog beamforming index. This is the index used internally by the code to progressively identify the beam with a value from 0 to `total_num_beams_vendor_ext`.
|
||||
|
||||
# L1 implementation
|
||||
|
||||
To handle multiple concurrent beams, the buffers containing Tx and Rx data in frequency domain (`txdataF` and `rxdataF`) have been extended by one dimension to contain multiple concurrent beams to be transmitted/received.
|
||||
The function `beam_index_allocation`, called by every L1 channel, is responsible to match the FAPI analog beam index to the RU beam index and to store the latter `beam_id` structure, which allocates the beams per symbol, despite L2 only supporting beam change at slot level. At the same time, the function returns the concurrent beam index, to be used to store data in frequency domain buffers. While doing so, the function also checks if there is room for current beam in the list of concurrent beams, which should always be the case, if L2 properly allocated the channels.
|
||||
|
||||
In case of DAS, since each beam corresponds to a specific antenna port, the `beam_index_allocation` function is simplified in the sense that the beam index corresponds to the antenna port index of the frequency domain buffers.
|
||||
|
||||
# RU implementation
|
||||
|
||||
The implementation is still work in progress.
|
||||
|
||||
The first dimension of the Tx and Rx buffers that used to contain the number of Tx/Rx antennas, it is now extended to contain the number of parallel streams which is the number of antennas multiplied by the number of concurrent beams.
|
||||
|
||||
@@ -61,7 +61,7 @@ RUN /bin/sh oaienv && \
|
||||
--gNB \
|
||||
--build-lib 'telnetsrv enbscope uescope nrscope' \
|
||||
-t oran_fhlib_5g --cmake-opt -Dxran_LOCATION=/opt/phy/fhi_lib/lib \
|
||||
--build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION" &&\
|
||||
--build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION" &&\
|
||||
# Mainly to see if the sanitize option was perfectly executed
|
||||
ldd ran_build/build/nr-softmodem && \
|
||||
ldd ran_build/build/liboran_fhlib_5g.so && \
|
||||
@@ -72,7 +72,6 @@ RUN mkdir -p openair2/E2AP/flexric/build && \
|
||||
cd openair2/E2AP/flexric/build && \
|
||||
scl enable gcc-toolset-13 "\
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Release \
|
||||
-DXAPP_MULTILANGUAGE=OFF \
|
||||
-DKPM_VERSION=$KPM_VERSION \
|
||||
-DE2AP_VERSION=$E2AP_VERSION .. &&\
|
||||
ninja && \
|
||||
|
||||
@@ -71,7 +71,7 @@ RUN /bin/sh oaienv && \
|
||||
--gNB \
|
||||
--build-lib "telnetsrv enbscope uescope nrscope" \
|
||||
-t oran_fhlib_5g --cmake-opt -Dxran_LOCATION=/opt/phy/fhi_lib/lib \
|
||||
--build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
|
||||
--build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
|
||||
$BUILD_OPTION && \
|
||||
# Mainly to see if the sanitize option was perfectly executed
|
||||
ldd ran_build/build/nr-softmodem && \
|
||||
@@ -82,7 +82,6 @@ RUN /bin/sh oaienv && \
|
||||
RUN mkdir -p openair2/E2AP/flexric/build && \
|
||||
cd openair2/E2AP/flexric/build && \
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Release \
|
||||
-DXAPP_MULTILANGUAGE=OFF \
|
||||
-DKPM_VERSION=$KPM_VERSION \
|
||||
-DE2AP_VERSION=$E2AP_VERSION \
|
||||
-DCMAKE_C_COMPILER=gcc-12 \
|
||||
|
||||
@@ -41,8 +41,7 @@ RUN /bin/sh oaienv && \
|
||||
scl enable gcc-toolset-13 "\
|
||||
CXXFLAGS='-Werror -fstack-protector-strong' CFLAGS='-Werror -fstack-protector-strong' ./build_oai -c --ninja \
|
||||
--eNB --gNB --RU --UE --nrUE \
|
||||
--build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF --cmake-opt \
|
||||
-DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
|
||||
--build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
|
||||
--build-lib 'telnetsrv enbscope uescope nrscope' \
|
||||
--build-tool-opt -k10 \
|
||||
-w USRP -t Ethernet \
|
||||
@@ -57,7 +56,6 @@ RUN mkdir -p openair2/E2AP/flexric/build && \
|
||||
cd openair2/E2AP/flexric/build && \
|
||||
scl enable gcc-toolset-13 "\
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Release \
|
||||
-DXAPP_MULTILANGUAGE=OFF \
|
||||
-DKPM_VERSION=$KPM_VERSION \
|
||||
-DE2AP_VERSION=$E2AP_VERSION .. &&\
|
||||
ninja && \
|
||||
|
||||
@@ -43,7 +43,7 @@ RUN /bin/sh oaienv && \
|
||||
--eNB --gNB --RU --UE --nrUE \
|
||||
--build-lib "telnetsrv enbscope uescope nrscope" \
|
||||
-w USRP -t Ethernet \
|
||||
--build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
|
||||
--build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
|
||||
--noavx512 \
|
||||
--build-tool-opt -k10 \
|
||||
--cmake-opt -DCMAKE_C_FLAGS="-Werror" --cmake-opt -DCMAKE_CXX_FLAGS="-Werror" $BUILD_OPTION && \
|
||||
@@ -57,7 +57,6 @@ RUN /bin/sh oaienv && \
|
||||
RUN mkdir -p openair2/E2AP/flexric/build && \
|
||||
cd openair2/E2AP/flexric/build && \
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Release \
|
||||
-DXAPP_MULTILANGUAGE=OFF \
|
||||
-DKPM_VERSION=$KPM_VERSION \
|
||||
-DE2AP_VERSION=$E2AP_VERSION \
|
||||
-DCMAKE_C_COMPILER=gcc-12 \
|
||||
|
||||
@@ -1740,8 +1740,6 @@ void *UE_thread(void *arg) {
|
||||
oai_exit=1;
|
||||
}
|
||||
|
||||
log_scheduler(__func__);
|
||||
|
||||
while (!oai_exit) {
|
||||
AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
|
||||
int instance_cnt_synch = UE->proc.instance_cnt_synch;
|
||||
|
||||
+12
-16
@@ -360,32 +360,29 @@ void term_gNB_Tpool(int inst) {
|
||||
}
|
||||
|
||||
/// eNB kept in function name for nffapi calls, TO FIX
|
||||
void init_eNB_afterRU(void) {
|
||||
int inst,ru_id,i,aa;
|
||||
PHY_VARS_gNB *gNB;
|
||||
|
||||
for (inst=0; inst<RC.nb_nr_L1_inst; inst++) {
|
||||
gNB = RC.gNB[inst];
|
||||
|
||||
void init_eNB_afterRU(void)
|
||||
{
|
||||
for (int inst = 0; inst < RC.nb_nr_L1_inst; inst++) {
|
||||
PHY_VARS_gNB *gNB = RC.gNB[inst];
|
||||
phy_init_nr_gNB(gNB);
|
||||
|
||||
// map antennas and PRACH signals to gNB RX
|
||||
if (0) AssertFatal(gNB->num_RU>0,"Number of RU attached to gNB %d is zero\n",gNB->Mod_id);
|
||||
|
||||
LOG_D(NR_PHY, "Mapping RX ports from %d RUs to gNB %d\n", gNB->num_RU, gNB->Mod_id);
|
||||
|
||||
for (ru_id=0,aa=0; ru_id<gNB->num_RU; ru_id++) {
|
||||
int aa = 0;
|
||||
for (int ru_id = 0; ru_id < gNB->num_RU; ru_id++) {
|
||||
AssertFatal(gNB->RU_list[ru_id]->common.rxdataF != NULL, "RU %d : common.rxdataF is NULL\n", gNB->RU_list[ru_id]->idx);
|
||||
AssertFatal(gNB->RU_list[ru_id]->prach_rxsigF != NULL, "RU %d : prach_rxsigF is NULL\n", gNB->RU_list[ru_id]->idx);
|
||||
|
||||
for (i=0; i<gNB->RU_list[ru_id]->nb_rx; aa++,i++) {
|
||||
LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n",gNB->RU_list[ru_id]->idx,i,aa);
|
||||
for (int i = 0; i < gNB->RU_list[ru_id]->nb_rx; aa++, i++) {
|
||||
LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n", gNB->RU_list[ru_id]->idx, i, aa);
|
||||
gNB->prach_vars.rxsigF[aa] = gNB->RU_list[ru_id]->prach_rxsigF[0][i];
|
||||
// TODO hardcoded beam to 0, still need to understand how to handle this properly
|
||||
gNB->common_vars.rxdataF[0][aa] = (c16_t *)gNB->RU_list[ru_id]->common.rxdataF[i];
|
||||
for (int b = 0; b < gNB->RU_list[ru_id]->num_beams_period; b++) {
|
||||
int idx = i + b * gNB->RU_list[ru_id]->nb_rx;
|
||||
gNB->common_vars.rxdataF[b][aa] = (c16_t *)gNB->RU_list[ru_id]->common.rxdataF[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: review this code, there is something wrong.
|
||||
* In monolithic mode, we come here with nb_antennas_rx == 0
|
||||
* (not tested in other modes).
|
||||
@@ -393,7 +390,6 @@ void init_eNB_afterRU(void) {
|
||||
//init_precoding_weights(RC.gNB[inst]);
|
||||
init_gNB_Tpool(inst);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+48
-51
@@ -240,20 +240,20 @@ int connect_rau(RU_t *ru) {
|
||||
void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
|
||||
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
int offset = ru->nr_frame_parms->get_samples_slot_timestamp(slot,ru->nr_frame_parms,0);
|
||||
void *buffs[ru->nb_tx];
|
||||
for (int aid=0;aid<ru->nb_tx;aid++) buffs[aid] = (void*)&ru->common.txdata[aid][offset];
|
||||
void *buffs[ru->nb_tx];
|
||||
for (int aid = 0; aid < ru->nb_tx; aid++)
|
||||
buffs[aid] = (void*)&ru->common.txdata[aid][offset];
|
||||
struct timespec txmeas;
|
||||
clock_gettime(CLOCK_MONOTONIC, &txmeas);
|
||||
LOG_D(NR_PHY,"IF5 TX %d.%d, TS %llu, buffs[0] %p, buffs[1] %p ener0 %f dB, tx start %d\n",frame,slot,(unsigned long long)timestamp,buffs[0],buffs[1],
|
||||
10*log10((double)signal_energy(buffs[0],ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms))),(int)txmeas.tv_nsec);
|
||||
ru->ifdevice.trx_write_func2(&ru->ifdevice,
|
||||
timestamp,
|
||||
timestamp,
|
||||
buffs,
|
||||
0,
|
||||
ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms),
|
||||
0,
|
||||
ru->nb_tx);
|
||||
|
||||
0,
|
||||
ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms),
|
||||
0,
|
||||
ru->nb_tx);
|
||||
}
|
||||
|
||||
// southbound IF4p5 fronthaul
|
||||
@@ -591,33 +591,28 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
openair0_config_t *cfg = &ru->openair0_cfg;
|
||||
void *rxp[ru->nb_rx];
|
||||
unsigned int rxs;
|
||||
int i;
|
||||
uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp);
|
||||
uint32_t samples_per_slot_prev ;
|
||||
openair0_timestamp ts,old_ts;
|
||||
AssertFatal(*slot<fp->slots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame);
|
||||
uint32_t samples_per_slot = fp->get_samples_per_slot(*slot, fp);
|
||||
AssertFatal(*slot < fp->slots_per_frame && *slot >= 0, "slot %d is illegal (%d)\n", *slot, fp->slots_per_frame);
|
||||
|
||||
start_meas(&ru->rx_fhaul);
|
||||
for (i=0; i<ru->nb_rx; i++)
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)];
|
||||
int nb = ru->nb_rx * ru->num_beams_period;
|
||||
void *rxp[nb];
|
||||
for (int i = 0; i < nb; i++)
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot, fp, 0)];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
|
||||
old_ts = proc->timestamp_rx;
|
||||
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",samples_per_slot,*slot,rxp[0]);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1);
|
||||
openair0_timestamp old_ts = proc->timestamp_rx;
|
||||
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n", samples_per_slot, *slot, rxp[0]);
|
||||
|
||||
openair0_timestamp ts;
|
||||
unsigned int rxs;
|
||||
if(emulate_rf) {
|
||||
wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
|
||||
release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
|
||||
rxs = samples_per_slot;
|
||||
ts = old_ts + rxs;
|
||||
} else {
|
||||
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
|
||||
&ts,
|
||||
rxp,
|
||||
samples_per_slot,
|
||||
ru->nb_rx);
|
||||
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, &ts, rxp, samples_per_slot, nb);
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
|
||||
@@ -629,7 +624,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n", samples_per_slot, rxs);
|
||||
|
||||
if (proc->first_rx != 1) {
|
||||
samples_per_slot_prev = fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp);
|
||||
uint32_t samples_per_slot_prev = fp->get_samples_per_slot((*slot - 1) % fp->slots_per_frame, fp);
|
||||
|
||||
if (proc->timestamp_rx - old_ts != samples_per_slot_prev) {
|
||||
LOG_D(PHY,
|
||||
@@ -752,8 +747,6 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
void *txp[ru->nb_tx];
|
||||
int i;
|
||||
T(T_ENB_PHY_OUTPUT_SIGNAL,
|
||||
T_INT(0),
|
||||
T_INT(0),
|
||||
@@ -820,7 +813,9 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot);
|
||||
|
||||
for (i = 0; i < ru->nb_tx; i++)
|
||||
int nt = ru->nb_tx * ru->num_beams_period;
|
||||
void *txp[nt];
|
||||
for (int i = 0; i < nt; i++)
|
||||
txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot, fp, 0)] - sf_extension * sizeof(int32_t);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp + ru->ts_offset) & 0xffffffff);
|
||||
@@ -830,12 +825,12 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
timestamp + ru->ts_offset - sf_extension,
|
||||
txp,
|
||||
siglen + sf_extension,
|
||||
ru->nb_tx, flags);
|
||||
nt,
|
||||
flags);
|
||||
LOG_D(PHY,
|
||||
"[TXPATH] RU %d aa %d tx_rf, writing to TS %llu, %d.%d, unwrapped_frame %d, slot %d, flags %d, siglen+sf_extension %d, "
|
||||
"[TXPATH] RU %d tx_rf, writing to TS %llu, %d.%d, unwrapped_frame %d, slot %d, flags %d, siglen+sf_extension %d, "
|
||||
"returned %d, E %f\n",
|
||||
ru->idx,
|
||||
i,
|
||||
(long long unsigned int)(timestamp + ru->ts_offset - sf_extension),
|
||||
frame,
|
||||
slot,
|
||||
@@ -851,7 +846,6 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
|
||||
static void fill_rf_config(RU_t *ru, char *rf_config_file)
|
||||
{
|
||||
int i;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nfapi_nr_config_request_scf_t *config = &ru->config; //tmp index
|
||||
openair0_config_t *cfg = &ru->openair0_cfg;
|
||||
@@ -877,13 +871,14 @@ static void fill_rf_config(RU_t *ru, char *rf_config_file)
|
||||
AssertFatal(ru->nb_rx > 0 && ru->nb_rx <= 8, "openair0 does not support more than 8 antennas\n");
|
||||
|
||||
cfg->Mod_id = 0;
|
||||
cfg->num_rb_dl=N_RB;
|
||||
cfg->tx_num_channels=ru->nb_tx;
|
||||
cfg->rx_num_channels=ru->nb_rx;
|
||||
cfg->num_rb_dl = N_RB;
|
||||
cfg->tx_num_channels = ru->nb_tx * ru->num_beams_period;
|
||||
cfg->rx_num_channels = ru->nb_rx * ru->num_beams_period;
|
||||
cfg->num_distributed_ru = ru->num_beams_period;
|
||||
LOG_I(PHY,"Setting RF config for N_RB %d, NB_RX %d, NB_TX %d\n",cfg->num_rb_dl,cfg->rx_num_channels,cfg->tx_num_channels);
|
||||
LOG_I(PHY,"tune_offset %.0f Hz, sample_rate %.0f Hz\n",cfg->tune_offset,cfg->sample_rate);
|
||||
|
||||
for (i=0; i<ru->nb_tx; i++) {
|
||||
for (int i = 0; i < ru->nb_tx * ru->num_beams_period; i++) {
|
||||
if (ru->if_frequency == 0) {
|
||||
cfg->tx_freq[i] = (double)fp->dl_CarrierFreq;
|
||||
} else if (ru->if_freq_offset) {
|
||||
@@ -898,7 +893,7 @@ static void fill_rf_config(RU_t *ru, char *rf_config_file)
|
||||
i, cfg->tx_gain[i],cfg->tx_freq[i]);
|
||||
}
|
||||
|
||||
for (i=0; i<ru->nb_rx; i++) {
|
||||
for (int i = 0; i < ru->nb_rx * ru->num_beams_period; i++) {
|
||||
if (ru->if_frequency == 0) {
|
||||
cfg->rx_freq[i] = (double)fp->ul_CarrierFreq;
|
||||
} else if (ru->if_freq_offset) {
|
||||
@@ -944,8 +939,8 @@ static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_
|
||||
Each rf chain is is addressed by the card number and the chain on the card. The
|
||||
rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple
|
||||
antennas are mapped to successive RF chains on the same card. */
|
||||
int setup_RU_buffers(RU_t *ru) {
|
||||
int i,j;
|
||||
int setup_RU_buffers(RU_t *ru)
|
||||
{
|
||||
int card,ant;
|
||||
//uint16_t N_TA_offset = 0;
|
||||
NR_DL_FRAME_PARMS *fp;
|
||||
@@ -967,27 +962,27 @@ int setup_RU_buffers(RU_t *ru) {
|
||||
|
||||
if (ru->openair0_cfg.mmapped_dma == 1) {
|
||||
// replace RX signal buffers with mmaped HW versions
|
||||
for (i=0; i<ru->nb_rx; i++) {
|
||||
card = i/4;
|
||||
ant = i%4;
|
||||
for (int i = 0; i < ru->nb_rx * ru->num_beams_period; i++) {
|
||||
card = i / 4;
|
||||
ant = i % 4;
|
||||
LOG_D(PHY, "Mapping RU id %u, rx_ant %d, on card %d, chain %d\n", ru->idx, i, ru->rf_map.card + card, ru->rf_map.chain + ant);
|
||||
free(ru->common.rxdata[i]);
|
||||
ru->common.rxdata[i] = ru->openair0_cfg.rxbase[ru->rf_map.chain + ant];
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
ru->common.rxdata[i][j] = 16-j;
|
||||
for (int j = 0; j < 16; j++) {
|
||||
ru->common.rxdata[i][j] = 16 - j;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<ru->nb_tx; i++) {
|
||||
card = i/4;
|
||||
ant = i%4;
|
||||
for (int i = 0; i < ru->nb_tx * ru->num_beams_period; i++) {
|
||||
card = i / 4;
|
||||
ant = i % 4;
|
||||
LOG_D(PHY, "Mapping RU id %u, tx_ant %d, on card %d, chain %d\n", ru->idx, i, ru->rf_map.card + card, ru->rf_map.chain + ant);
|
||||
free(ru->common.txdata[i]);
|
||||
ru->common.txdata[i] = ru->openair0_cfg.txbase[ru->rf_map.chain + ant];
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
ru->common.txdata[i][j] = 16-j;
|
||||
for (int j = 0; j < 16; j++) {
|
||||
ru->common.txdata[i][j] = 16 - j;
|
||||
}
|
||||
}
|
||||
} else { // not memory-mapped DMA
|
||||
@@ -1054,7 +1049,7 @@ void ru_tx_func(void *param)
|
||||
ru->fh_north_out(ru);
|
||||
} else {
|
||||
if(frame_tx == print_frame) {
|
||||
for (int i=0; i<ru->nb_tx; i++) {
|
||||
for (int i = 0; i < ru->nb_tx * ru->num_beams_period; i++) {
|
||||
if(slot_tx == 0) {
|
||||
sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, slot_tx);
|
||||
LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
|
||||
@@ -1324,10 +1319,12 @@ void *ru_thread(void *param)
|
||||
|
||||
for (int prach_oc = 0; prach_oc < p->num_prach_ocas; prach_oc++) {
|
||||
int prachStartSymbol = p->prachStartSymbol + prach_oc * N_dur;
|
||||
int beam_id = ru->prach_list[prach_id].beam ? ru->prach_list[prach_id].beam[prach_oc] : 0;
|
||||
//comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}.
|
||||
rx_nr_prach_ru(ru,
|
||||
p->fmt, // could also use format
|
||||
p->numRA,
|
||||
beam_id,
|
||||
prachStartSymbol,
|
||||
p->slot,
|
||||
prach_oc,
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
||||
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
#include "RRC/LTE/rrc_vars.h"
|
||||
#ifdef SMBV
|
||||
#include "PHY/TOOLS/smbv.h"
|
||||
|
||||
@@ -1124,6 +1124,33 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e
|
||||
// only increase if it was set
|
||||
numTLVs += pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag == NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG;
|
||||
|
||||
AssertFatal(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag == 0,
|
||||
"Total num beams Vendor extension shouldn't be set!");
|
||||
// The call to pack the TLV would be the same as any other TLV, it is only packed if the tag is set,
|
||||
// so, it's safe to add the call to pack_nr_tlv even if it is not always set
|
||||
retval &= pack_nr_tlv(NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG,
|
||||
&(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext),
|
||||
ppWritePackedMsg,
|
||||
end,
|
||||
&pack_uint8_tlv_value);
|
||||
// only increase if it was set
|
||||
numTLVs +=
|
||||
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag == NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
|
||||
|
||||
for (int beam = 0; beam < pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.value; beam++) {
|
||||
AssertFatal(pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam].tl.tag == 0,
|
||||
"Analog beams list Vendor extension shouldn't be set!");
|
||||
// The call to pack the TLV would be the same as any other TLV, it is only packed if the tag is set,
|
||||
// so, it's safe to add the call to pack_nr_tlv even if it is not always set
|
||||
retval &= pack_nr_tlv(NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG,
|
||||
&(pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam]),
|
||||
ppWritePackedMsg,
|
||||
end,
|
||||
&pack_uint8_tlv_value);
|
||||
// only increase if it was set
|
||||
numTLVs += pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag == NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
|
||||
}
|
||||
|
||||
pNfapiMsg->num_tlv = numTLVs;
|
||||
retval &= push8(pNfapiMsg->num_tlv, &pNumTLVFields, end);
|
||||
return retval;
|
||||
@@ -1138,6 +1165,7 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
|
||||
int config_beam_idx = 0;
|
||||
int tdd_periodicity_idx = 0;
|
||||
int symbol_per_slot_idx = 0;
|
||||
int beam_ve_idx = 0;
|
||||
nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t *)msg;
|
||||
// unpack TLVs
|
||||
|
||||
@@ -1188,6 +1216,10 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
|
||||
&unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, NULL, &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG, NULL, &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, &(pNfapiMsg->measurement_config.rssi_measurement), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value},
|
||||
{NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), &unpack_ipv6_address_value},
|
||||
@@ -1221,6 +1253,21 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
|
||||
}
|
||||
int result = 0;
|
||||
switch (generic_tl.tag) {
|
||||
case NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG:
|
||||
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag = generic_tl.tag;
|
||||
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.length = generic_tl.length;
|
||||
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext, ppReadPackedMsg, end);
|
||||
pNfapiMsg->analog_beamforming_ve.analog_beam_list = (nfapi_uint8_tlv_t *)malloc(
|
||||
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
|
||||
beam_ve_idx = 0;
|
||||
break;
|
||||
case NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG:
|
||||
unpack_fns[idx].tlv = &pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx];
|
||||
pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx].tl.tag = generic_tl.tag;
|
||||
pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx].tl.length = generic_tl.length;
|
||||
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx], ppReadPackedMsg, end);
|
||||
beam_ve_idx ++;
|
||||
break;
|
||||
case NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG:
|
||||
pNfapiMsg->prach_config.num_prach_fd_occasions.tl.tag = generic_tl.tag;
|
||||
pNfapiMsg->prach_config.num_prach_fd_occasions.tl.length = generic_tl.length;
|
||||
|
||||
@@ -276,6 +276,17 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const
|
||||
EQ_TLV(unpacked_req->nfapi_config.timing_info_mode, req->nfapi_config.timing_info_mode);
|
||||
|
||||
EQ_TLV(unpacked_req->nfapi_config.timing_info_period, req->nfapi_config.timing_info_period);
|
||||
|
||||
EQ_TLV(unpacked_req->analog_beamforming_ve.num_beams_period_vendor_ext, req->analog_beamforming_ve.num_beams_period_vendor_ext);
|
||||
|
||||
EQ_TLV(unpacked_req->analog_beamforming_ve.analog_bf_vendor_ext, req->analog_beamforming_ve.analog_bf_vendor_ext);
|
||||
|
||||
EQ_TLV(unpacked_req->analog_beamforming_ve.total_num_beams_vendor_ext, req->analog_beamforming_ve.total_num_beams_vendor_ext);
|
||||
|
||||
for (int i = 0; i < unpacked_req->analog_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
|
||||
EQ_TLV(unpacked_req->analog_beamforming_ve.analog_beam_list[i], req->analog_beamforming_ve.analog_beam_list[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -422,6 +433,10 @@ void free_config_request(nfapi_nr_config_request_scf_t *msg)
|
||||
if (msg->pmi_list.pmi_pdu) {
|
||||
free(msg->pmi_list.pmi_pdu);
|
||||
}
|
||||
|
||||
if (msg->analog_beamforming_ve.analog_beam_list) {
|
||||
free(msg->analog_beamforming_ve.analog_beam_list);
|
||||
}
|
||||
}
|
||||
|
||||
void free_config_response(nfapi_nr_config_response_scf_t *msg)
|
||||
@@ -832,6 +847,21 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf
|
||||
COPY_TLV(dst->nfapi_config.ul_dci_timing_offset, src->nfapi_config.ul_dci_timing_offset);
|
||||
|
||||
COPY_TLV(dst->nfapi_config.tx_data_timing_offset, src->nfapi_config.tx_data_timing_offset);
|
||||
|
||||
COPY_TLV(dst->analog_beamforming_ve.num_beams_period_vendor_ext, src->analog_beamforming_ve.num_beams_period_vendor_ext);
|
||||
|
||||
COPY_TLV(dst->analog_beamforming_ve.analog_bf_vendor_ext, src->analog_beamforming_ve.analog_bf_vendor_ext);
|
||||
|
||||
COPY_TLV(dst->analog_beamforming_ve.total_num_beams_vendor_ext, src->analog_beamforming_ve.total_num_beams_vendor_ext);
|
||||
|
||||
if (dst->analog_beamforming_ve.total_num_beams_vendor_ext.value > 0) {
|
||||
dst->analog_beamforming_ve.analog_beam_list = (nfapi_uint8_tlv_t *)malloc(
|
||||
dst->analog_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
|
||||
for (int i = 0; i < src->analog_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
|
||||
COPY_TLV(dst->analog_beamforming_ve.analog_beam_list[i], src->analog_beamforming_ve.analog_beam_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void copy_config_response(const nfapi_nr_config_response_scf_t *src, nfapi_nr_config_response_scf_t *dst)
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#define NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG 0x0120
|
||||
#define NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG 0xA000
|
||||
#define NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG 0xA001
|
||||
#define NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG 0xA002
|
||||
#define NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG 0xA003
|
||||
|
||||
typedef struct {
|
||||
uint16_t phy_id;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#define NFAPI_MAX_NUM_GROUPS 8
|
||||
#define NFAPI_MAX_NUM_CB 8
|
||||
#define NFAPI_MAX_NUM_PRGS 1
|
||||
#define NFAPI_MAX_NUM_BG_IF 1
|
||||
#define NFAPI_MAX_NUM_BG_IF 6
|
||||
#define NFAPI_MAX_NUM_PERIODS 8
|
||||
|
||||
// Extension to the generic structures for single tlv values
|
||||
@@ -496,6 +496,8 @@ typedef struct {
|
||||
typedef struct {
|
||||
nfapi_uint8_tlv_t num_beams_period_vendor_ext;
|
||||
nfapi_uint8_tlv_t analog_bf_vendor_ext;
|
||||
nfapi_uint8_tlv_t total_num_beams_vendor_ext;
|
||||
nfapi_uint8_tlv_t *analog_beam_list;
|
||||
} nfapi_nr_analog_beamforming_ve_t;
|
||||
|
||||
// ERROR enums
|
||||
@@ -1829,7 +1831,7 @@ typedef struct {
|
||||
uint8_t num_symbols; // Number of symbols for SRS. Value: 1 -> 4. If a PHY does not report for individual symbols then this parameter should be set to 1.
|
||||
uint8_t wide_band_snr; // SNR value in dB measured within configured SRS bandwidth on each symbol. Value: 0 -> 255 representing -64 dB to 63 dB with a step size 0.5 dB. 0xff will be set if this field is invalid.
|
||||
uint8_t num_reported_symbols; // Number of symbols reported in this message. This allows PHY to report individual symbols or aggregated symbols where this field will be set to 1. Value: 1 -> 4.
|
||||
nfapi_nr_srs_reported_symbol_t* reported_symbol_list;
|
||||
nfapi_nr_srs_reported_symbol_t reported_symbol_list[4];
|
||||
} nfapi_nr_srs_beamforming_report_t;
|
||||
|
||||
// SRS indication
|
||||
|
||||
@@ -4455,8 +4455,7 @@ int unpack_nr_srs_beamforming_report(void *pMessageBuf, uint32_t messageBufLen,
|
||||
&& pull8(&pReadPackedMessage, &nr_srs_beamforming_report->num_reported_symbols, end))) {
|
||||
return -1;
|
||||
}
|
||||
nr_srs_beamforming_report->reported_symbol_list =
|
||||
calloc(nr_srs_beamforming_report->num_reported_symbols, sizeof(*nr_srs_beamforming_report->reported_symbol_list));
|
||||
|
||||
for (int reported_symbol = 0; reported_symbol < nr_srs_beamforming_report->num_reported_symbols; ++reported_symbol) {
|
||||
if (!unpack_nr_srs_reported_symbol(&nr_srs_beamforming_report->reported_symbol_list[reported_symbol],
|
||||
&pReadPackedMessage,
|
||||
|
||||
@@ -229,6 +229,33 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap
|
||||
|
||||
FILL_TLV(nfapi_resp->nfapi_config.timing_info_period, NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
/*
|
||||
// TODO: Uncomment this block when ready to enable the pack of the following VE TLVs in nr_fapi_p5.c
|
||||
// NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG
|
||||
// NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG
|
||||
// NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG
|
||||
// NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG
|
||||
FILL_TLV(nfapi_resp->analog_beamforming_ve.num_beams_period_vendor_ext,
|
||||
NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG,
|
||||
rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
|
||||
FILL_TLV(nfapi_resp->analog_beamforming_ve.analog_bf_vendor_ext, NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG, rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
|
||||
FILL_TLV(nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext,
|
||||
NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG,
|
||||
rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
|
||||
if (nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext.value > 0) {
|
||||
nfapi_resp->analog_beamforming_ve.analog_beam_list =
|
||||
(nfapi_uint8_tlv_t *)malloc(nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
|
||||
for (int i = 0; i < nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
|
||||
FILL_TLV(nfapi_resp->analog_beamforming_ve.analog_beam_list[i], NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG, rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
static void test_pack_unpack(nfapi_nr_config_request_scf_t *req)
|
||||
|
||||
@@ -172,8 +172,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
for (int i = 0; i < common_vars->num_beams_period; i++)
|
||||
common_vars->rxdataF[i] = (c16_t **)malloc16(Prx * sizeof(c16_t*));
|
||||
|
||||
common_vars->num_beams = cfg->dbt_config.num_dig_beams;
|
||||
if (common_vars->num_beams > 0) {
|
||||
if (cfg->analog_beamforming_ve.analog_bf_vendor_ext.value) {
|
||||
common_vars->beam_id = (int **)malloc16(common_vars->num_beams_period * sizeof(int*));
|
||||
for (int i = 0; i < common_vars->num_beams_period; i++)
|
||||
common_vars->beam_id[i] = (int*)malloc16_clear(fp->symbols_per_slot * fp->slots_per_frame * sizeof(int));
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
void init_prach_ru_list(RU_t *ru);
|
||||
|
||||
int nr_phy_init_RU(RU_t *ru)
|
||||
void nr_phy_init_RU(RU_t *ru)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
|
||||
@@ -47,36 +47,40 @@ int nr_phy_init_RU(RU_t *ru)
|
||||
|
||||
AssertFatal(ru->nb_log_antennas > 0 && ru->nb_log_antennas < 13, "ru->nb_log_antennas %d ! \n",ru->nb_log_antennas);
|
||||
|
||||
ru->common.beam_id = malloc16_clear(MAX_NUM_BEAM_PERIODS * sizeof(int*));
|
||||
for(int i = 0; i < MAX_NUM_BEAM_PERIODS; i++)
|
||||
nfapi_nr_analog_beamforming_ve_t *analog_config = &cfg->analog_beamforming_ve;
|
||||
ru->num_beams_period = analog_config->analog_bf_vendor_ext.value ? analog_config->num_beams_period_vendor_ext.value : 1;
|
||||
int nb_tx_streams = ru->nb_tx * ru->num_beams_period;
|
||||
int nb_rx_streams = ru->nb_rx * ru->num_beams_period;
|
||||
LOG_I(NR_PHY, "nb_tx_streams %d, nb_rx_streams %d, num_Beams_period %d\n", nb_tx_streams, nb_rx_streams, ru->num_beams_period);
|
||||
ru->common.beam_id = malloc16_clear(ru->num_beams_period * sizeof(int*));
|
||||
for(int i = 0; i < ru->num_beams_period; i++)
|
||||
ru->common.beam_id[i] = malloc16_clear(fp->symbols_per_slot * fp->slots_per_frame * sizeof(int));
|
||||
|
||||
if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so allocate memory for time-domain signals
|
||||
// Time-domain signals
|
||||
ru->common.txdata = (int32_t**)malloc16(ru->nb_tx*sizeof(int32_t*));
|
||||
ru->common.rxdata = (int32_t**)malloc16(ru->nb_rx*sizeof(int32_t*) );
|
||||
ru->common.txdata = (int32_t**)malloc16(nb_tx_streams * sizeof(int32_t*));
|
||||
ru->common.rxdata = (int32_t**)malloc16(nb_rx_streams * sizeof(int32_t*));
|
||||
|
||||
|
||||
for (int i = 0; i < ru->nb_tx; i++) {
|
||||
for (int i = 0; i < nb_tx_streams; i++) {
|
||||
// Allocate 10 subframes of I/Q TX signal data (time) if not
|
||||
ru->common.txdata[i] = (int32_t*)malloc16_clear((ru->sf_extension + fp->samples_per_frame)*sizeof(int32_t));
|
||||
ru->common.txdata[i] = (int32_t*)malloc16_clear((ru->sf_extension + fp->samples_per_frame) * sizeof(int32_t));
|
||||
LOG_D(PHY,
|
||||
"[INIT] common.txdata[%d] = %p (%lu bytes,sf_extension %d)\n",
|
||||
i,
|
||||
ru->common.txdata[i],
|
||||
(ru->sf_extension + fp->samples_per_frame) * sizeof(int32_t),
|
||||
ru->sf_extension);
|
||||
ru->common.txdata[i] = &ru->common.txdata[i][ru->sf_extension];
|
||||
ru->common.txdata[i] = &ru->common.txdata[i][ru->sf_extension];
|
||||
|
||||
LOG_D(PHY, "[INIT] common.txdata[%d] = %p \n", i, ru->common.txdata[i]);
|
||||
}
|
||||
for (int i = 0; i < ru->nb_rx; i++) {
|
||||
ru->common.rxdata[i] = (int32_t*)malloc16_clear( fp->samples_per_frame*sizeof(int32_t) );
|
||||
for (int i = 0; i < nb_rx_streams; i++) {
|
||||
ru->common.rxdata[i] = (int32_t*)malloc16_clear(fp->samples_per_frame * sizeof(int32_t));
|
||||
}
|
||||
} // IF5 or local RF
|
||||
else {
|
||||
ru->common.txdata = (int32_t**)NULL;
|
||||
ru->common.rxdata = (int32_t**)NULL;
|
||||
ru->common.txdata = (int32_t**)NULL;
|
||||
ru->common.rxdata = (int32_t**)NULL;
|
||||
}
|
||||
if (ru->function != NGFI_RRU_IF5) { // we need to do RX/TX RU processing
|
||||
LOG_D(PHY, "nb_tx %d\n", ru->nb_tx);
|
||||
@@ -85,7 +89,6 @@ int nr_phy_init_RU(RU_t *ru)
|
||||
ru->common.rxdata_7_5kHz[i] = (int32_t*)malloc16_clear( 2*fp->samples_per_subframe*2*sizeof(int32_t) );
|
||||
LOG_D(PHY, "rxdata_7_5kHz[%d] %p for RU %d\n", i, ru->common.rxdata_7_5kHz[i], ru->idx);
|
||||
}
|
||||
|
||||
|
||||
// allocate precoding input buffers (TX)
|
||||
ru->common.txdataF = (int32_t **)malloc16(ru->nb_tx*sizeof(int32_t*));
|
||||
@@ -94,15 +97,15 @@ int nr_phy_init_RU(RU_t *ru)
|
||||
ru->common.txdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP * sizeof(int32_t));
|
||||
|
||||
// allocate IFFT input buffers (TX)
|
||||
ru->common.txdataF_BF = (int32_t **)malloc16(ru->nb_tx*sizeof(int32_t*));
|
||||
LOG_D(PHY, "[INIT] common.txdata_BF= %p (%lu bytes)\n", ru->common.txdataF_BF, ru->nb_tx * sizeof(int32_t *));
|
||||
for (int i = 0; i < ru->nb_tx; i++) {
|
||||
ru->common.txdataF_BF[i] = (int32_t*)malloc16_clear(fp->samples_per_subframe_wCP*sizeof(int32_t) );
|
||||
ru->common.txdataF_BF = (int32_t **)malloc16(nb_tx_streams * sizeof(int32_t*));
|
||||
LOG_D(PHY, "[INIT] common.txdata_BF= %p (%lu bytes)\n", ru->common.txdataF_BF, nb_tx_streams * sizeof(int32_t *));
|
||||
for (int i = 0; i < nb_tx_streams; i++) {
|
||||
ru->common.txdataF_BF[i] = (int32_t*)malloc16_clear(fp->samples_per_subframe_wCP * sizeof(int32_t));
|
||||
LOG_D(PHY, "txdataF_BF[%d] %p for RU %d\n", i, ru->common.txdataF_BF[i], ru->idx);
|
||||
}
|
||||
// allocate FFT output buffers (RX)
|
||||
ru->common.rxdataF = (int32_t**)malloc16(ru->nb_rx*sizeof(int32_t*) );
|
||||
for (int i = 0; i < ru->nb_rx; i++) {
|
||||
ru->common.rxdataF = (int32_t**)malloc16(nb_rx_streams * sizeof(int32_t*));
|
||||
for (int i = 0; i < nb_rx_streams; i++) {
|
||||
// allocate 4 slots of I/Q signal data (frequency)
|
||||
int size = RU_RX_SLOT_DEPTH * fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
ru->common.rxdataF[i] = (int32_t*)malloc16_clear(sizeof(**ru->common.rxdataF) * size);
|
||||
@@ -113,40 +116,38 @@ int nr_phy_init_RU(RU_t *ru)
|
||||
// AssertFatal(ru->nb_rx <= sizeof(ru->prach_rxsigF) / sizeof(ru->prach_rxsigF[0]),
|
||||
// "nb_antennas_rx too large");
|
||||
for (int j = 0; j < NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX; j++) {
|
||||
ru->prach_rxsigF[j] = (int16_t**)malloc(ru->nb_rx * sizeof(int16_t*));
|
||||
ru->prach_rxsigF[j] = (int16_t**)malloc(nb_rx_streams * sizeof(int16_t*));
|
||||
|
||||
for (int i = 0; i < ru->nb_rx; i++) {
|
||||
for (int i = 0; i < nb_rx_streams; i++) {
|
||||
// largest size for PRACH FFT is 4x98304 (16*24576)
|
||||
ru->prach_rxsigF[j][i] = (int16_t*)malloc16_clear( 4*98304*2*sizeof(int16_t) );
|
||||
LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[j][i]);
|
||||
ru->prach_rxsigF[j][i] = (int16_t*)malloc16_clear(4 * 98304 * 2 * sizeof(int16_t));
|
||||
LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n", i, ru->prach_rxsigF[j][i]);
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(ru->num_gNB <= NUMBER_OF_gNB_MAX,"gNB instances %d > %d\n",
|
||||
ru->num_gNB,NUMBER_OF_gNB_MAX);
|
||||
|
||||
AssertFatal(ru->num_gNB <= NUMBER_OF_gNB_MAX, "gNB instances %d > %d\n", ru->num_gNB,NUMBER_OF_gNB_MAX);
|
||||
|
||||
LOG_D(PHY, "[INIT] %s() ru->num_gNB:%d \n", __FUNCTION__, ru->num_gNB);
|
||||
|
||||
} // !=IF5
|
||||
|
||||
init_prach_ru_list(ru);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void nr_phy_free_RU(RU_t *ru)
|
||||
{
|
||||
LOG_D(PHY, "Freeing RU signal buffers (if_south %s) nb_tx %d\n", ru_if_types[ru->if_south], ru->nb_tx);
|
||||
int nb_tx_streams = ru->nb_tx * ru->num_beams_period;
|
||||
int nb_rx_streams = ru->nb_rx * ru->num_beams_period;
|
||||
|
||||
if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so free memory for time-domain signals
|
||||
// Hack: undo what is done at allocation
|
||||
for (int i = 0; i < ru->nb_tx; i++) {
|
||||
for (int i = 0; i < nb_tx_streams; i++) {
|
||||
int32_t *p = &ru->common.txdata[i][-ru->sf_extension];
|
||||
free_and_zero(p);
|
||||
}
|
||||
free_and_zero(ru->common.txdata);
|
||||
|
||||
for (int i = 0; i < ru->nb_rx; i++)
|
||||
for (int i = 0; i < nb_rx_streams; i++)
|
||||
free_and_zero(ru->common.rxdata[i]);
|
||||
free_and_zero(ru->common.rxdata);
|
||||
} // else: IF5 or local RF -> nothing to free()
|
||||
@@ -162,21 +163,21 @@ void nr_phy_free_RU(RU_t *ru)
|
||||
free_and_zero(ru->common.txdataF);
|
||||
|
||||
// free IFFT input buffers (TX)
|
||||
for (int i = 0; i < ru->nb_tx; i++)
|
||||
for (int i = 0; i < nb_tx_streams; i++)
|
||||
free_and_zero(ru->common.txdataF_BF[i]);
|
||||
free_and_zero(ru->common.txdataF_BF);
|
||||
|
||||
// free FFT output buffers (RX)
|
||||
for (int i = 0; i < ru->nb_rx; i++)
|
||||
for (int i = 0; i < nb_rx_streams; i++)
|
||||
free_and_zero(ru->common.rxdataF[i]);
|
||||
free_and_zero(ru->common.rxdataF);
|
||||
|
||||
for (int j = 0; j < NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX; j++) {
|
||||
for (int i = 0; i < ru->nb_rx; i++)
|
||||
for (int i = 0; i < nb_rx_streams; i++)
|
||||
free_and_zero(ru->prach_rxsigF[j][i]);
|
||||
free_and_zero(ru->prach_rxsigF[j]);
|
||||
}
|
||||
for(int i = 0; i < MAX_NUM_BEAM_PERIODS; ++i)
|
||||
for(int i = 0; i < ru->num_beams_period; ++i)
|
||||
free_and_zero(ru->common.beam_id[i]);
|
||||
free_and_zero(ru->common.beam_id);
|
||||
}
|
||||
|
||||
@@ -81,7 +81,9 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
int dci_idx = 0;
|
||||
// multi-beam number (for concurrent beams)
|
||||
int bitmap = SL_to_bitmap(cset_start_symb, pdcch_pdu_rel15->DurationSymbols);
|
||||
int beam_nb = beam_index_allocation(dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
int beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
frame_parms->symbols_per_slot,
|
||||
|
||||
@@ -680,7 +680,9 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
|
||||
// beam number in multi-beam scenario (concurrent beams)
|
||||
int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols);
|
||||
int beam_nb = beam_index_allocation(pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
int beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
frame_parms->symbols_per_slot,
|
||||
|
||||
@@ -42,7 +42,6 @@ void init_prach_list(PHY_VARS_gNB *gNB)
|
||||
for (int i = 0; i < NUMBER_OF_NR_PRACH_MAX; i++){
|
||||
gNB->prach_vars.list[i].frame = -1;
|
||||
gNB->prach_vars.list[i].slot = -1;
|
||||
gNB->prach_vars.list[i].beam_nb = -1;
|
||||
gNB->prach_vars.list[i].num_slots = -1;
|
||||
}
|
||||
}
|
||||
@@ -51,8 +50,8 @@ void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id)
|
||||
{
|
||||
gNB->prach_vars.list[prach_id].frame = -1;
|
||||
gNB->prach_vars.list[prach_id].slot = -1;
|
||||
gNB->prach_vars.list[prach_id].beam_nb = -1;
|
||||
gNB->prach_vars.list[prach_id].num_slots = -1;
|
||||
free_and_zero(gNB->prach_vars.list[prach_id].beam_nb);
|
||||
}
|
||||
|
||||
int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame, int slot, find_type_t type) {
|
||||
@@ -70,7 +69,7 @@ int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame, int slot, find_type_t type) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
|
||||
int nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
|
||||
{
|
||||
int prach_id = find_nr_prach(gNB, SFN, Slot, SEARCH_EXIST_OR_FREE);
|
||||
AssertFatal(((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX)), "illegal or no prach_id found!!! prach_id %d\n", prach_id);
|
||||
@@ -79,16 +78,25 @@ void nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *p
|
||||
prach->slot = Slot;
|
||||
const int format = prach_pdu->prach_format;
|
||||
prach->num_slots = (format < 4) ? get_long_prach_dur(format, gNB->frame_parms.numerology_index) : 1;
|
||||
prach->beam_nb = 0;
|
||||
if (gNB->common_vars.beam_id) {
|
||||
int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
|
||||
// TODO no idea how to compute final prach symbol here so for now we go til the end of the slot
|
||||
int temp_nb_symbols = NR_NUMBER_OF_SYMBOLS_PER_SLOT - prach_pdu->prach_start_symbol;
|
||||
int bitmap = SL_to_bitmap(prach_pdu->prach_start_symbol, temp_nb_symbols);
|
||||
prach->beam_nb = beam_index_allocation(fapi_beam_idx, &gNB->common_vars, Slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap);
|
||||
int n_symb = get_nr_prach_duration(prach_pdu->prach_format);
|
||||
prach->beam_nb = calloc(prach_pdu->beamforming.dig_bf_interface, sizeof(*prach->beam_nb));
|
||||
for (int i = 0; i < prach_pdu->beamforming.dig_bf_interface; i++) {
|
||||
int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[i].beam_idx;
|
||||
int start_symb = prach_pdu->prach_start_symbol + i * n_symb;
|
||||
int bitmap = SL_to_bitmap(start_symb, n_symb);
|
||||
prach->beam_nb[i] = beam_index_allocation(gNB->enable_analog_das,
|
||||
fapi_beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
Slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
}
|
||||
}
|
||||
LOG_D(NR_PHY,"Copying prach pdu %d bytes to index %d\n", (int)sizeof(*prach_pdu), prach_id);
|
||||
memcpy(&prach->pdu, prach_pdu, sizeof(*prach_pdu));
|
||||
return prach_id;
|
||||
}
|
||||
|
||||
void init_prach_ru_list(RU_t *ru)
|
||||
@@ -121,10 +129,10 @@ int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void nr_fill_prach_ru(RU_t *ru, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
|
||||
void nr_fill_prach_ru(RU_t *ru, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu, int *beam_id)
|
||||
{
|
||||
int prach_id = find_nr_prach_ru(ru, SFN, Slot, SEARCH_EXIST_OR_FREE);
|
||||
AssertFatal(((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX)) || (prach_id < 0),
|
||||
AssertFatal((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX),
|
||||
"illegal or no prach_id found!!! prach_id %d\n",
|
||||
prach_id);
|
||||
|
||||
@@ -135,6 +143,7 @@ void nr_fill_prach_ru(RU_t *ru, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_p
|
||||
ru->prach_list[prach_id].num_slots = (fmt < 4) ? get_long_prach_dur(fmt, ru->nr_frame_parms->numerology_index) : 1;
|
||||
ru->prach_list[prach_id].fmt = fmt;
|
||||
ru->prach_list[prach_id].numRA = prach_pdu->num_ra;
|
||||
ru->prach_list[prach_id].beam = beam_id;
|
||||
ru->prach_list[prach_id].prachStartSymbol = prach_pdu->prach_start_symbol;
|
||||
ru->prach_list[prach_id].num_prach_ocas = prach_pdu->num_prach_ocas;
|
||||
pthread_mutex_unlock(&ru->prach_list_mutex);
|
||||
@@ -151,6 +160,7 @@ void free_nr_ru_prach_entry(RU_t *ru, int prach_id)
|
||||
void rx_nr_prach_ru(RU_t *ru,
|
||||
int prachFormat,
|
||||
int numRA,
|
||||
int beam,
|
||||
int prachStartSymbol,
|
||||
int prachStartSlot,
|
||||
int prachOccasion,
|
||||
@@ -159,7 +169,6 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
{
|
||||
AssertFatal(ru != NULL,"ru is null\n");
|
||||
|
||||
int16_t **rxsigF = NULL;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
int slot2 = slot;
|
||||
int16_t *prach[ru->nb_rx];
|
||||
@@ -191,15 +200,16 @@ void rx_nr_prach_ru(RU_t *ru,
|
||||
prachStartSymbol,
|
||||
prachOccasion);
|
||||
|
||||
rxsigF = ru->prach_rxsigF[prachOccasion];
|
||||
int16_t **rxsigF = ru->prach_rxsigF[prachOccasion];
|
||||
|
||||
AssertFatal(ru->if_south == LOCAL_RF || ru->if_south == REMOTE_IF5,
|
||||
"we shouldn't call this if if_south != LOCAL_RF or REMOTE_IF5\n");
|
||||
|
||||
for (int aa=0; aa<ru->nb_rx; aa++){
|
||||
for (int aa = 0; aa < ru->nb_rx; aa++) {
|
||||
if (prach_sequence_length == 0)
|
||||
slot2 = prachStartSlot;
|
||||
prach[aa] = (int16_t*)&ru->common.rxdata[aa][fp->get_samples_slot_timestamp(slot2, fp, 0) + sample_offset_slot - ru->N_TA_offset];
|
||||
int idx = aa + beam * ru->nb_rx;
|
||||
prach[aa] = (int16_t*)&ru->common.rxdata[idx][fp->get_samples_slot_timestamp(slot2, fp, 0) + sample_offset_slot - ru->N_TA_offset];
|
||||
}
|
||||
|
||||
int reps;
|
||||
|
||||
@@ -257,14 +257,11 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB,
|
||||
int slot,
|
||||
nfapi_nr_pusch_pdu_t *ulsch_pdu);
|
||||
|
||||
void nr_fill_prach(PHY_VARS_gNB *gNB,
|
||||
int SFN,
|
||||
int Slot,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu);
|
||||
int nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu);
|
||||
|
||||
void rx_nr_prach(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu,
|
||||
int prachOccasion,
|
||||
int prachOccasion,
|
||||
int frame,
|
||||
int subframe,
|
||||
uint16_t *max_preamble,
|
||||
@@ -274,16 +271,14 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
|
||||
void rx_nr_prach_ru(RU_t *ru,
|
||||
int prach_fmt,
|
||||
int numRA,
|
||||
int beam,
|
||||
int prachStartSymbol,
|
||||
int prachStartSlot,
|
||||
int prachOccasion,
|
||||
int frame,
|
||||
int subframe);
|
||||
|
||||
void nr_fill_prach_ru(RU_t *ru,
|
||||
int SFN,
|
||||
int Slot,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu);
|
||||
void nr_fill_prach_ru(RU_t *ru,int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu, int *beam_nb);
|
||||
|
||||
int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame,int slot, find_type_t type);
|
||||
int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type);
|
||||
@@ -309,7 +304,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB,
|
||||
void init_prach_list(PHY_VARS_gNB *gNB);
|
||||
void init_prach_ru_list(RU_t *ru);
|
||||
void free_nr_ru_prach_entry(RU_t *ru, int prach_id);
|
||||
uint8_t get_nr_prach_duration(uint8_t prach_format);
|
||||
int get_nr_prach_duration(uint8_t prach_format);
|
||||
|
||||
void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id);
|
||||
|
||||
|
||||
@@ -76,7 +76,13 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t
|
||||
if (gNB->common_vars.beam_id) {
|
||||
int fapi_beam_idx = ulsch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
|
||||
int bitmap = SL_to_bitmap(ulsch_pdu->start_symbol_index, ulsch_pdu->nr_of_symbols);
|
||||
ulsch->beam_nb = beam_index_allocation(fapi_beam_idx, &gNB->common_vars, slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap);
|
||||
ulsch->beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
fapi_beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
}
|
||||
ulsch->frame = frame;
|
||||
ulsch->slot = slot;
|
||||
|
||||
@@ -57,10 +57,7 @@
|
||||
|
||||
//#define DEBUG_NR_PUCCH_RX 1
|
||||
|
||||
void nr_fill_pucch(PHY_VARS_gNB *gNB,
|
||||
int frame,
|
||||
int slot,
|
||||
nfapi_nr_pucch_pdu_t *pucch_pdu)
|
||||
void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu)
|
||||
{
|
||||
bool found = false;
|
||||
for (int i = 0; i < gNB->max_nb_pucch; i++) {
|
||||
@@ -73,7 +70,13 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB,
|
||||
if (gNB->common_vars.beam_id) {
|
||||
int fapi_beam_idx = pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
|
||||
int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols);
|
||||
pucch->beam_nb = beam_index_allocation(fapi_beam_idx, &gNB->common_vars, slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap);
|
||||
pucch->beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
fapi_beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
}
|
||||
memcpy((void *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t));
|
||||
LOG_D(PHY,
|
||||
|
||||
@@ -59,7 +59,13 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu
|
||||
if (gNB->common_vars.beam_id) {
|
||||
int bitmap = SL_to_bitmap(srs_pdu->time_start_position, 1 << srs_pdu->num_symbols);
|
||||
int fapi_beam_idx = srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
|
||||
srs->beam_nb = beam_index_allocation(fapi_beam_idx, &gNB->common_vars, slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap);
|
||||
srs->beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
fapi_beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
}
|
||||
memcpy((void *)&srs->srs_pdu, (void *)srs_pdu, sizeof(nfapi_nr_srs_pdu_t));
|
||||
break;
|
||||
|
||||
@@ -172,6 +172,7 @@ typedef struct RU_prec_t_s{
|
||||
|
||||
typedef struct {
|
||||
int aid;
|
||||
int beam;
|
||||
struct RU_t_s *ru;
|
||||
int startSymbol;
|
||||
int endSymbol;
|
||||
@@ -181,6 +182,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
int aid;
|
||||
int beam;
|
||||
struct RU_t_s *ru;
|
||||
int slot;
|
||||
int startSymbol;
|
||||
@@ -196,6 +198,7 @@ typedef struct {
|
||||
int prachStartSymbol;
|
||||
int num_prach_ocas;
|
||||
int num_slots;
|
||||
int *beam;
|
||||
} RU_PRACH_list_t;
|
||||
|
||||
#define NUMBER_OF_NR_RU_PRACH_MAX 8
|
||||
@@ -488,6 +491,8 @@ typedef struct RU_t_s {
|
||||
int nb_rx;
|
||||
/// number of TX paths on device
|
||||
int nb_tx;
|
||||
/// number of concurrent analog beams in period
|
||||
int num_beams_period;
|
||||
/// number of logical antennas at TX beamformer input
|
||||
int nb_log_antennas;
|
||||
/// maximum PDSCH RS EPRE
|
||||
|
||||
@@ -138,9 +138,9 @@ typedef struct {
|
||||
int frame;
|
||||
int slot;
|
||||
// identifier for concurrent beams
|
||||
int beam_nb;
|
||||
// prach duration in slots
|
||||
int num_slots;
|
||||
int *beam_nb;
|
||||
nfapi_nr_prach_pdu_t pdu;
|
||||
} gNB_PRACH_list_t;
|
||||
|
||||
@@ -287,7 +287,6 @@ typedef struct {
|
||||
/// - first index: beam index (for concurrent beams)
|
||||
/// - second index: beam_id [0.. symbols_per_frame[
|
||||
int **beam_id;
|
||||
int num_beams;
|
||||
int num_beams_period;
|
||||
bool analog_bf;
|
||||
int32_t *debugBuff;
|
||||
@@ -493,6 +492,8 @@ typedef struct PHY_VARS_gNB_s {
|
||||
int num_ulprbbl;
|
||||
uint16_t ulprbbl [MAX_BWP_SIZE];
|
||||
|
||||
bool enable_analog_das;
|
||||
|
||||
time_stats_t phy_proc_tx;
|
||||
time_stats_t phy_proc_rx;
|
||||
time_stats_t rx_prach;
|
||||
|
||||
@@ -157,9 +157,9 @@ void nr_schedule_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti
|
||||
UL_tti_req->SFN,
|
||||
UL_tti_req->Slot);
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu;
|
||||
nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
int id = nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
if (gNB->RU_list[0]->if_south == LOCAL_RF || gNB->RU_list[0]->if_south == REMOTE_IF5)
|
||||
nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu, gNB->prach_vars.list[id].beam_nb);
|
||||
break;
|
||||
case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE:
|
||||
LOG_D(NR_PHY,
|
||||
|
||||
@@ -37,62 +37,14 @@
|
||||
#include "nfapi_pnf.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
|
||||
#include "assertions.h"
|
||||
|
||||
#include <time.h>
|
||||
uint8_t get_nr_prach_duration(uint8_t prach_format){
|
||||
|
||||
switch(prach_format){
|
||||
|
||||
case 0: // format 0
|
||||
return 0;
|
||||
|
||||
case 1: // format 1
|
||||
return 0;
|
||||
|
||||
case 2: // format 2
|
||||
return 0;
|
||||
|
||||
case 3: // format 3
|
||||
return 0;
|
||||
|
||||
case 4: // format A1
|
||||
return 2;
|
||||
|
||||
case 5: // format A2
|
||||
return 4;
|
||||
|
||||
case 6: // format A3
|
||||
return 6;
|
||||
|
||||
case 7: // format B1
|
||||
return 2;
|
||||
|
||||
case 8: // format B4
|
||||
return 12;
|
||||
|
||||
case 9: // format C0
|
||||
return 2;
|
||||
|
||||
case 10: // format C2
|
||||
return 6;
|
||||
|
||||
case 11: // format A1/B1
|
||||
return 2;
|
||||
|
||||
case 12: // format A2/B2
|
||||
return 4;
|
||||
|
||||
case 13: // format A3/B3
|
||||
return 6;
|
||||
|
||||
default :
|
||||
AssertFatal(1==0,"Invalid Prach format\n");
|
||||
break;
|
||||
|
||||
}
|
||||
int get_nr_prach_duration(uint8_t prach_format)
|
||||
{
|
||||
const int val[14] = {0, 0, 0, 0, 2, 4, 6, 2, 12, 2, 6, 2, 4, 6};
|
||||
AssertFatal(prach_format < sizeofArray(val), "Invalid Prach format %d\n", prach_format);
|
||||
return val[prach_format];
|
||||
}
|
||||
|
||||
void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rach_indication_t *rach_ind)
|
||||
@@ -117,14 +69,14 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_vars.list[prach_id].pdu;
|
||||
const int prach_start_slot = gNB->prach_vars.list[prach_id].slot;
|
||||
uint8_t prachStartSymbol;
|
||||
uint8_t N_dur = get_nr_prach_duration(prach_pdu->prach_format);
|
||||
int N_dur = get_nr_prach_duration(prach_pdu->prach_format);
|
||||
|
||||
for(int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) {
|
||||
for (ru_aa=0,aa=0;ru_aa<ru->nb_rx;ru_aa++,aa++) {
|
||||
gNB->prach_vars.rxsigF[aa] = ru->prach_rxsigF[prach_oc][ru_aa];
|
||||
}
|
||||
|
||||
prachStartSymbol = prach_pdu->prach_start_symbol+prach_oc*N_dur;
|
||||
prachStartSymbol = prach_pdu->prach_start_symbol + prach_oc * N_dur;
|
||||
//comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}.
|
||||
|
||||
rx_nr_prach(gNB,
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
// RU OFDM Modulator gNodeB
|
||||
// OFDM modulation core routine, generates a first_symbol to first_symbol+num_symbols on a particular slot and TX antenna port
|
||||
void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa)
|
||||
void nr_feptx0(RU_t *ru, int tti_tx, int first_symbol, int num_symbols, int aa)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
|
||||
@@ -175,57 +175,39 @@ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) {
|
||||
|
||||
}
|
||||
|
||||
void nr_feptx_prec(RU_t *ru, int frame_tx, int tti_tx)
|
||||
void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx)
|
||||
{
|
||||
PHY_VARS_gNB **gNB_list = ru->gNB_list,*gNB;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
PHY_VARS_gNB **gNB_list = ru->gNB_list;
|
||||
AssertFatal(ru->num_gNB == 1, "Cannot handle more than 1 gNB\n");
|
||||
PHY_VARS_gNB *gNB = gNB_list[0];
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
int slot_tx = tti_tx;
|
||||
int txdataF_offset = (tti_tx*fp->samples_per_slot_wCP);
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
int txdataF_offset = slot_tx * fp->samples_per_slot_wCP;
|
||||
start_meas(&ru->precoding_stats);
|
||||
AssertFatal(ru->nb_log_antennas > 0, "ru->nb_log_antennas is 0!\n");
|
||||
|
||||
if (nr_slot_select(cfg,frame_tx,slot_tx) == NR_UPLINK_SLOT)
|
||||
return;
|
||||
|
||||
if (ru->num_gNB == 1) {
|
||||
gNB = gNB_list[0];
|
||||
if (gNB->common_vars.analog_bf) {
|
||||
for (int i = 0; i < ru->num_beams_period; i++) {
|
||||
memcpy((void*) &ru->common.beam_id[i][slot_tx * fp->symbols_per_slot],
|
||||
(void*) &gNB->common_vars.beam_id[i][slot_tx * fp->symbols_per_slot],
|
||||
(fp->symbols_per_slot) * sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
if (ru->config.dbt_config.num_dig_beams != 0) {
|
||||
for(int i = 0; i < gNB->common_vars.num_beams_period; ++i) {
|
||||
memcpy((void*) &ru->common.beam_id[i][slot_tx * fp->symbols_per_slot],
|
||||
(void*) &gNB->common_vars.beam_id[i][slot_tx * fp->symbols_per_slot],
|
||||
(fp->symbols_per_slot) * sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
if (ru->config.dbt_config.num_dig_beams == 0 || gNB->common_vars.analog_bf) {
|
||||
for (int i = 0; i < ru->nb_log_antennas; ++i) {
|
||||
// TODO hardcoded beam to 0, still need to understand how to handle this properly
|
||||
memcpy(ru->common.txdataF_BF[i], &gNB->common_vars.txdataF[0][i][txdataF_offset], fp->samples_per_slot_wCP * sizeof(int32_t));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int i = 0; i < ru->nb_log_antennas; ++i) {
|
||||
// TODO hardcoded beam to 0, still need to understand how to handle this properly
|
||||
memcpy(ru->common.txdataF[i], &gNB->common_vars.txdataF[0][i][txdataF_offset], fp->samples_per_slot_wCP * sizeof(int32_t));
|
||||
}
|
||||
for (int l = 0; l < fp->symbols_per_slot; l++) {
|
||||
for (int aa = 0; aa < ru->nb_tx; aa++) {
|
||||
AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n");
|
||||
nr_beam_precoding((c16_t **)ru->common.txdataF,
|
||||
(c16_t **)ru->common.txdataF_BF,
|
||||
fp,
|
||||
ru->beam_weights[0],
|
||||
tti_tx,
|
||||
l,
|
||||
aa,
|
||||
ru->nb_log_antennas,
|
||||
0);
|
||||
}
|
||||
// If there is no digital beamforming we just need to copy the data to RU
|
||||
if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) {
|
||||
for (int b = 0; b < ru->num_beams_period; b++) {
|
||||
for (int i = 0; i < ru->nb_tx; ++i) {
|
||||
int tx_idx = i + b * ru->nb_tx;
|
||||
memcpy((void*)ru->common.txdataF_BF[tx_idx],
|
||||
(void*)&gNB->common_vars.txdataF[b][i][txdataF_offset],
|
||||
fp->samples_per_slot_wCP * sizeof(int32_t));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n");
|
||||
}
|
||||
stop_meas(&ru->precoding_stats);
|
||||
}
|
||||
@@ -238,6 +220,7 @@ void nr_feptx(void *arg)
|
||||
RU_t *ru = feptx->ru;
|
||||
int slot = feptx->slot;
|
||||
int aa = feptx->aid;
|
||||
int bb = feptx->beam;
|
||||
int startSymbol = feptx->startSymbol;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
int numSymbols = feptx->numSymbols;
|
||||
@@ -246,44 +229,32 @@ void nr_feptx(void *arg)
|
||||
int txdataF_BF_offset = startSymbol * fp->ofdm_symbol_size;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->aid , 1);
|
||||
int tx_idx = aa + bb * ru->nb_tx;
|
||||
|
||||
if (aa == 0)
|
||||
if (tx_idx == 0)
|
||||
start_meas(&ru->precoding_stats);
|
||||
|
||||
if (ru->config.dbt_config.num_dig_beams != 0) {
|
||||
for(int i = 0; i < ru->gNB_list[0]->common_vars.num_beams_period; i++) {
|
||||
memcpy(&ru->common.beam_id[i][slot * fp->symbols_per_slot],
|
||||
&ru->gNB_list[0]->common_vars.beam_id[i][slot * fp->symbols_per_slot],
|
||||
(fp->symbols_per_slot) * sizeof(int));
|
||||
}
|
||||
if (ru->gNB_list[0]->common_vars.analog_bf) {
|
||||
memcpy(&ru->common.beam_id[bb][slot * fp->symbols_per_slot],
|
||||
&ru->gNB_list[0]->common_vars.beam_id[bb][slot * fp->symbols_per_slot],
|
||||
(fp->symbols_per_slot) * sizeof(int));
|
||||
}
|
||||
|
||||
// If there is no digital beamforming we just need to copy the data to RU
|
||||
if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf)
|
||||
memcpy((void*)&ru->common.txdataF_BF[aa][txdataF_BF_offset],
|
||||
(void*)&ru->gNB_list[0]->common_vars.txdataF[0][aa][txdataF_offset], // TODO hardcoded beam to 0, still need to understand how to handle this properly
|
||||
memcpy((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset],
|
||||
(void*)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset],
|
||||
numSamples * sizeof(int32_t));
|
||||
else {
|
||||
AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n");
|
||||
for(int i = 0; i < fp->symbols_per_slot; ++i) {
|
||||
nr_beam_precoding((c16_t **)ru->gNB_list[0]->common_vars.txdataF,
|
||||
(c16_t **)ru->common.txdataF_BF,
|
||||
fp,
|
||||
ru->beam_weights[0],
|
||||
slot,
|
||||
i,
|
||||
aa,
|
||||
ru->nb_log_antennas,
|
||||
txdataF_offset);
|
||||
}
|
||||
AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n");
|
||||
}
|
||||
|
||||
if (aa==0)
|
||||
if (tx_idx == 0)
|
||||
stop_meas(&ru->precoding_stats);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->aid , 0);
|
||||
|
||||
////////////FEPTX////////////
|
||||
nr_feptx0(ru, slot, startSymbol, numSymbols, aa);
|
||||
nr_feptx0(ru, slot, startSymbol, numSymbols, tx_idx);
|
||||
|
||||
// Task completed in //
|
||||
completed_task_ans(feptx->ans);
|
||||
@@ -299,39 +270,42 @@ void nr_feptx_tp(RU_t *ru, int frame_tx, int slot)
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM, 1);
|
||||
start_meas(&ru->ofdm_total_stats);
|
||||
|
||||
size_t const sz = ru->nb_tx + (ru->half_slot_parallelization > 0) * ru->nb_tx;
|
||||
int nt = ru->nb_tx * ru->num_beams_period;
|
||||
size_t const sz = nt + (ru->half_slot_parallelization > 0) * nt;
|
||||
feptx_cmd_t arr[sz];
|
||||
task_ans_t ans;
|
||||
init_task_ans(&ans, sz);
|
||||
|
||||
int nbfeptx = 0;
|
||||
for (int aid = 0; aid < ru->nb_tx; aid++) {
|
||||
feptx_cmd_t *feptx_cmd = &arr[nbfeptx];
|
||||
feptx_cmd->ans = &ans;
|
||||
|
||||
feptx_cmd->aid = aid;
|
||||
feptx_cmd->ru = ru;
|
||||
feptx_cmd->slot = slot;
|
||||
feptx_cmd->startSymbol = 0;
|
||||
feptx_cmd->numSymbols =
|
||||
(ru->half_slot_parallelization > 0) ? ru->nr_frame_parms->symbols_per_slot >> 1 : ru->nr_frame_parms->symbols_per_slot;
|
||||
|
||||
task_t t = {.func = nr_feptx, .args = feptx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
nbfeptx++;
|
||||
if (ru->half_slot_parallelization > 0) {
|
||||
for (int beam = 0; beam < ru->num_beams_period; beam++) {
|
||||
for (int aid = 0; aid < ru->nb_tx; aid++) {
|
||||
feptx_cmd_t *feptx_cmd = &arr[nbfeptx];
|
||||
feptx_cmd->ans = &ans;
|
||||
|
||||
feptx_cmd->beam = beam;
|
||||
feptx_cmd->aid = aid;
|
||||
feptx_cmd->ru = ru;
|
||||
feptx_cmd->slot = slot;
|
||||
feptx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
feptx_cmd->numSymbols = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
feptx_cmd->startSymbol = 0;
|
||||
feptx_cmd->numSymbols =
|
||||
(ru->half_slot_parallelization > 0) ? ru->nr_frame_parms->symbols_per_slot >> 1 : ru->nr_frame_parms->symbols_per_slot;
|
||||
|
||||
task_t t = {.func = nr_feptx, .args = feptx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
nbfeptx++;
|
||||
if (ru->half_slot_parallelization > 0) {
|
||||
feptx_cmd_t *feptx_cmd = &arr[nbfeptx];
|
||||
feptx_cmd->ans = &ans;
|
||||
feptx_cmd->beam = beam;
|
||||
feptx_cmd->aid = aid;
|
||||
feptx_cmd->ru = ru;
|
||||
feptx_cmd->slot = slot;
|
||||
feptx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
feptx_cmd->numSymbols = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
|
||||
task_t t = {.func = nr_feptx, .args = feptx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
nbfeptx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
join_task_ans(&ans);
|
||||
@@ -345,24 +319,26 @@ void nr_feptx_tp(RU_t *ru, int frame_tx, int slot)
|
||||
void nr_fep(void* arg)
|
||||
{
|
||||
feprx_cmd_t *feprx_cmd = (feprx_cmd_t *)arg;
|
||||
RU_t *ru = feprx_cmd->ru;
|
||||
int aid = feprx_cmd->aid;
|
||||
int tti_rx = feprx_cmd->slot;
|
||||
int startSymbol = feprx_cmd->startSymbol;
|
||||
int endSymbol = feprx_cmd->endSymbol;
|
||||
RU_t *ru = feprx_cmd->ru;
|
||||
int aid = feprx_cmd->aid;
|
||||
int beam = feprx_cmd->beam;
|
||||
int slot = feprx_cmd->slot;
|
||||
int startSymbol = feprx_cmd->startSymbol;
|
||||
int endSymbol = feprx_cmd->endSymbol;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
|
||||
LOG_D(PHY,"aid %d, frame %d slot %d, startSymbol %d, endSymbol %d\n", aid, ru->proc.frame_rx, tti_rx, startSymbol, endSymbol);
|
||||
LOG_D(PHY,"aid %d, frame %d slot %d, startSymbol %d, endSymbol %d\n", aid, ru->proc.frame_rx, slot, startSymbol, endSymbol);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+aid, 1);
|
||||
|
||||
int offset = (tti_rx % RU_RX_SLOT_DEPTH) * fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
int idx = aid + beam * ru->nb_rx;
|
||||
int offset = (slot % RU_RX_SLOT_DEPTH) * fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
for (int l = startSymbol; l <= endSymbol; l++)
|
||||
nr_slot_fep_ul(fp,
|
||||
ru->common.rxdata[aid],
|
||||
&ru->common.rxdataF[aid][offset],
|
||||
ru->common.rxdata[idx],
|
||||
&ru->common.rxdataF[idx][offset],
|
||||
l,
|
||||
tti_rx,
|
||||
slot,
|
||||
ru->N_TA_offset);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+aid, 0);
|
||||
|
||||
@@ -377,39 +353,42 @@ void nr_fep_tp(RU_t *ru, int slot) {
|
||||
if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 );
|
||||
start_meas(&ru->ofdm_demod_stats);
|
||||
|
||||
size_t const sz = ru->nb_rx + (ru->half_slot_parallelization > 0) * ru->nb_rx;
|
||||
int nt = ru->nb_rx * ru->num_beams_period;
|
||||
size_t const sz = nt + (ru->half_slot_parallelization > 0) * nt;
|
||||
feprx_cmd_t arr[sz];
|
||||
task_ans_t ans;
|
||||
init_task_ans(&ans, sz);
|
||||
|
||||
for (int aid=0;aid<ru->nb_rx;aid++) {
|
||||
feprx_cmd_t *feprx_cmd = &arr[nbfeprx];
|
||||
feprx_cmd->ans = &ans;
|
||||
|
||||
feprx_cmd->aid = aid;
|
||||
feprx_cmd->ru = ru;
|
||||
feprx_cmd->slot = ru->proc.tti_rx;
|
||||
feprx_cmd->startSymbol = 0;
|
||||
feprx_cmd->endSymbol = (ru->half_slot_parallelization > 0) ? (ru->nr_frame_parms->symbols_per_slot >> 1) - 1
|
||||
: (ru->nr_frame_parms->symbols_per_slot - 1);
|
||||
|
||||
task_t t = {.func = nr_fep, .args = feprx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
nbfeprx++;
|
||||
if (ru->half_slot_parallelization > 0) {
|
||||
for (int beam = 0; beam < ru->num_beams_period; beam++) {
|
||||
for (int aid = 0; aid < ru->nb_rx; aid++) {
|
||||
feprx_cmd_t *feprx_cmd = &arr[nbfeprx];
|
||||
feprx_cmd->ans = &ans;
|
||||
|
||||
feprx_cmd->beam = beam;
|
||||
feprx_cmd->aid = aid;
|
||||
feprx_cmd->ru = ru;
|
||||
feprx_cmd->slot = ru->proc.tti_rx;
|
||||
feprx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
feprx_cmd->endSymbol = ru->nr_frame_parms->symbols_per_slot - 1;
|
||||
feprx_cmd->startSymbol = 0;
|
||||
feprx_cmd->endSymbol = (ru->half_slot_parallelization > 0) ? (ru->nr_frame_parms->symbols_per_slot >> 1) - 1
|
||||
: (ru->nr_frame_parms->symbols_per_slot - 1);
|
||||
|
||||
task_t t = {.func = nr_fep, .args = feprx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
|
||||
nbfeprx++;
|
||||
if (ru->half_slot_parallelization > 0) {
|
||||
feprx_cmd_t *feprx_cmd = &arr[nbfeprx];
|
||||
feprx_cmd->ans = &ans;
|
||||
feprx_cmd->beam = beam;
|
||||
feprx_cmd->aid = aid;
|
||||
feprx_cmd->ru = ru;
|
||||
feprx_cmd->slot = ru->proc.tti_rx;
|
||||
feprx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
feprx_cmd->endSymbol = ru->nr_frame_parms->symbols_per_slot - 1;
|
||||
|
||||
task_t t = {.func = nr_fep, .args = feprx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
|
||||
nbfeprx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
join_task_ans(&ans);
|
||||
|
||||
@@ -45,18 +45,26 @@
|
||||
//#define DEBUG_RXDATA
|
||||
//#define SRS_IND_DEBUG
|
||||
|
||||
int beam_index_allocation(int fapi_beam_index, NR_gNB_COMMON *common_vars, int slot, int symbols_per_slot, int bitmap_symbols)
|
||||
int beam_index_allocation(bool das,
|
||||
int fapi_beam_index,
|
||||
nfapi_nr_analog_beamforming_ve_t *analog_bf,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
int slot,
|
||||
int symbols_per_slot,
|
||||
int bitmap_symbols)
|
||||
{
|
||||
if (!common_vars->beam_id)
|
||||
return 0;
|
||||
if (das)
|
||||
return fapi_beam_index;
|
||||
|
||||
int ru_beam_idx = analog_bf->analog_beam_list[fapi_beam_index].value;
|
||||
int idx = -1;
|
||||
for (int j = 0; j < common_vars->num_beams_period; j++) {
|
||||
// L2 analog beam implementation is slot based, so we need to verify occupancy for the whole slot
|
||||
for (int i = 0; i < symbols_per_slot; i++) {
|
||||
if (((bitmap_symbols >> i) & 0x01) == 0)
|
||||
continue;
|
||||
int current_beam = common_vars->beam_id[j][slot * symbols_per_slot + i];
|
||||
if (current_beam == -1 || current_beam == fapi_beam_index)
|
||||
if (current_beam == -1 || current_beam == ru_beam_idx)
|
||||
idx = j;
|
||||
else {
|
||||
idx = -1;
|
||||
@@ -66,12 +74,12 @@ int beam_index_allocation(int fapi_beam_index, NR_gNB_COMMON *common_vars, int s
|
||||
if (idx != -1)
|
||||
break;
|
||||
}
|
||||
AssertFatal(idx >= 0, "Couldn't allocate beam ID %d\n", fapi_beam_index);
|
||||
AssertFatal(idx >= 0, "Couldn't allocate beam ID %d\n", ru_beam_idx);
|
||||
for (int j = 0; j < symbols_per_slot; j++) {
|
||||
if (((bitmap_symbols >> j) & 0x01))
|
||||
common_vars->beam_id[idx][slot * symbols_per_slot + j] = fapi_beam_index;
|
||||
common_vars->beam_id[idx][slot * symbols_per_slot + j] = ru_beam_idx;
|
||||
}
|
||||
LOG_D(PHY, "Allocating beam %d in slot %d\n", idx, slot);
|
||||
LOG_D(PHY, "Allocating beam_id[%d] %d in slot %d\n", idx, ru_beam_idx, slot);
|
||||
return idx;
|
||||
}
|
||||
|
||||
@@ -131,7 +139,9 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n
|
||||
int txdataF_offset = slot * fp->samples_per_slot_wCP;
|
||||
// beam number in a scenario with multiple concurrent beams
|
||||
int bitmap = SL_to_bitmap(ssb_start_symbol, 4); // 4 ssb symbols
|
||||
int beam_nb = beam_index_allocation(pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
int beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&cfg->analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
fp->symbols_per_slot,
|
||||
@@ -272,7 +282,9 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
int lprime_num = mapping_parms.lprime + 1;
|
||||
for (int j = 0; j < mapping_parms.size; j++)
|
||||
csi_bitmap |= ((1 << lprime_num) - 1) << mapping_parms.loverline[j];
|
||||
int beam_nb = beam_index_allocation(pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
int beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&cfg->analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
fp->symbols_per_slot,
|
||||
@@ -1046,6 +1058,9 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
|
||||
nr_srs_bf_report.num_symbols = 1 << srs_pdu->num_symbols;
|
||||
nr_srs_bf_report.wide_band_snr = srs_est >= 0 ? (gNB->srs->snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid
|
||||
nr_srs_bf_report.num_reported_symbols = 1 << srs_pdu->num_symbols;
|
||||
AssertFatal(nr_srs_bf_report.num_reported_symbols == 1,
|
||||
"nr_srs_bf_report.num_reported_symbols %i not handled yet!\n",
|
||||
nr_srs_bf_report.num_reported_symbols);
|
||||
fill_srs_reported_symbol(&nr_srs_bf_report.reported_symbol_list[0], srs_pdu, frame_parms->N_RB_UL, snr_per_rb, srs_est);
|
||||
|
||||
#ifdef SRS_IND_DEBUG
|
||||
@@ -1053,13 +1068,13 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
|
||||
LOG_I(NR_PHY, "nr_srs_bf_report.num_symbols = %i\n", nr_srs_bf_report.num_symbols);
|
||||
LOG_I(NR_PHY, "nr_srs_bf_report.wide_band_snr = %i (%i dB)\n", nr_srs_bf_report.wide_band_snr, (nr_srs_bf_report.wide_band_snr >> 1) - 64);
|
||||
LOG_I(NR_PHY, "nr_srs_bf_report.num_reported_symbols = %i\n", nr_srs_bf_report.num_reported_symbols);
|
||||
LOG_I(NR_PHY, "nr_srs_bf_report.prgs[0].num_prgs = %i\n", nr_srs_bf_report.prgs[0].num_prgs);
|
||||
for (int prg_idx = 0; prg_idx < nr_srs_bf_report.prgs[0].num_prgs; prg_idx++) {
|
||||
LOG_I(NR_PHY, "nr_srs_bf_report.reported_symbol_list[0].num_prgs = %i\n", nr_srs_bf_report.reported_symbol_list[0].num_prgs);
|
||||
for (int prg_idx = 0; prg_idx < nr_srs_bf_report.reported_symbol_list[0].num_prgs; prg_idx++) {
|
||||
LOG_I(NR_PHY,
|
||||
"nr_srs_beamforming_report.prgs[0].prg_list[%3i].rb_snr = %i (%i dB)\n",
|
||||
"nr_srs_beamforming_report.reported_symbol_list[0].prg_list[%3i].rb_snr = %i (%i dB)\n",
|
||||
prg_idx,
|
||||
nr_srs_bf_report.prgs[0].prg_list[prg_idx].rb_snr,
|
||||
(nr_srs_bf_report.prgs[0].prg_list[prg_idx].rb_snr >> 1) - 64);
|
||||
nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr,
|
||||
(nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr >> 1) - 64);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -44,8 +44,14 @@ void nr_feptx_prec_control(RU_t *ru,int frame,int tti_tx);
|
||||
void nr_fep_tp(RU_t *ru, int slot);
|
||||
void nr_feptx_tp(RU_t *ru, int frame_tx, int slot);
|
||||
void feptx_prec(RU_t *ru,int frame_tx,int tti_tx);
|
||||
int nr_phy_init_RU(RU_t *ru);
|
||||
void nr_phy_init_RU(RU_t *ru);
|
||||
void nr_phy_free_RU(RU_t *ru);
|
||||
void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot);
|
||||
int beam_index_allocation(int fapi_beam_index, NR_gNB_COMMON *common_vars, int slot, int symbols_per_slot, int bitmap_symbols);
|
||||
int beam_index_allocation(bool das,
|
||||
int fapi_beam_index,
|
||||
nfapi_nr_analog_beamforming_ve_t *analog_bf,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
int slot,
|
||||
int symbols_per_slot,
|
||||
int bitmap_symbols);
|
||||
#endif
|
||||
|
||||
@@ -714,12 +714,36 @@ printf("%d\n", slot);
|
||||
.timer_config.n311 = 1,
|
||||
.timer_config.t319 = 400,
|
||||
.num_agg_level_candidates = {0, 0, 1, 1, 0}};
|
||||
const nr_rlc_configuration_t rlc_config = {
|
||||
.srb = {
|
||||
.t_poll_retransmit = 45,
|
||||
.t_reassembly = 35,
|
||||
.t_status_prohibit = 0,
|
||||
.poll_pdu = -1,
|
||||
.poll_byte = -1,
|
||||
.max_retx_threshold = 8,
|
||||
.sn_field_length = 12,
|
||||
},
|
||||
.drb_am = {
|
||||
.t_poll_retransmit = 45,
|
||||
.t_reassembly = 15,
|
||||
.t_status_prohibit = 15,
|
||||
.poll_pdu = 64,
|
||||
.poll_byte = 1024 * 500,
|
||||
.max_retx_threshold = 32,
|
||||
.sn_field_length = 18,
|
||||
},
|
||||
.drb_um = {
|
||||
.t_reassembly = 15,
|
||||
.sn_field_length = 12,
|
||||
}
|
||||
};
|
||||
|
||||
RC.nb_nr_macrlc_inst = 1;
|
||||
RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int));
|
||||
for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
|
||||
RC.nb_nr_mac_CC[i] = 1;
|
||||
mac_top_init_gNB(ngran_gNB, scc, NULL, &conf);
|
||||
mac_top_init_gNB(ngran_gNB, scc, NULL, &conf, &rlc_config);
|
||||
gNB_mac = RC.nrmac[0];
|
||||
nr_mac_config_scc(RC.nrmac[0], scc, &conf);
|
||||
|
||||
|
||||
@@ -773,7 +773,7 @@ int main(int argc, char **argv){
|
||||
}
|
||||
}
|
||||
|
||||
rx_nr_prach_ru(ru, prach_format, numRA, prachStartSymbol, slot, prachOccasion, frame, slot);
|
||||
rx_nr_prach_ru(ru, prach_format, numRA, 0, prachStartSymbol, slot, prachOccasion, frame, slot);
|
||||
|
||||
for (int i = 0; i < ru->nb_rx; ++i)
|
||||
gNB->prach_vars.rxsigF[i] = ru->prach_rxsigF[prachOccasion][i];
|
||||
|
||||
@@ -668,12 +668,36 @@ int main(int argc, char *argv[])
|
||||
.timer_config.t311 = 3000,
|
||||
.timer_config.n311 = 1,
|
||||
.timer_config.t319 = 400};
|
||||
const nr_rlc_configuration_t rlc_config = {
|
||||
.srb = {
|
||||
.t_poll_retransmit = 45,
|
||||
.t_reassembly = 35,
|
||||
.t_status_prohibit = 0,
|
||||
.poll_pdu = -1,
|
||||
.poll_byte = -1,
|
||||
.max_retx_threshold = 8,
|
||||
.sn_field_length = 12,
|
||||
},
|
||||
.drb_am = {
|
||||
.t_poll_retransmit = 45,
|
||||
.t_reassembly = 15,
|
||||
.t_status_prohibit = 15,
|
||||
.poll_pdu = 64,
|
||||
.poll_byte = 1024 * 500,
|
||||
.max_retx_threshold = 32,
|
||||
.sn_field_length = 18,
|
||||
},
|
||||
.drb_um = {
|
||||
.t_reassembly = 15,
|
||||
.sn_field_length = 12,
|
||||
}
|
||||
};
|
||||
|
||||
RC.nb_nr_macrlc_inst = 1;
|
||||
RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int));
|
||||
for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
|
||||
RC.nb_nr_mac_CC[i] = 1;
|
||||
mac_top_init_gNB(ngran_gNB, scc, NULL /* scd will be updated further below */, &conf);
|
||||
mac_top_init_gNB(ngran_gNB, scc, NULL /* scd will be updated further below */, &conf, &rlc_config);
|
||||
nr_mac_config_scc(RC.nrmac[0], scc, &conf);
|
||||
|
||||
NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t));
|
||||
|
||||
@@ -664,11 +664,8 @@ typedef struct ngap_pdusession_setup_req_s {
|
||||
/* E RAB setup request */
|
||||
pdusession_t pdusession_setup_params[NGAP_MAX_PDU_SESSION];
|
||||
|
||||
/* UE Uplink Aggregated Max Bitrates */
|
||||
uint64_t ueAggMaxBitRateUplink;
|
||||
|
||||
/* UE Downlink Aggregated Max Bitrates */
|
||||
uint64_t ueAggMaxBitRateDownlink;
|
||||
/* UE Aggregated Max Bitrates */
|
||||
ngap_ambr_t ueAggMaxBitRate;
|
||||
|
||||
} ngap_pdusession_setup_req_t;
|
||||
|
||||
|
||||
@@ -115,7 +115,9 @@ static cudu_ue_info_pair_t fill_ue_related_info(arr_ue_id_t* arr_ue_id, const si
|
||||
|
||||
if (arr_ue_id->ue_id[ue_idx].type == GNB_UE_ID_E2SM) {
|
||||
ue_info.rrc_ue_id = *arr_ue_id->ue_id[ue_idx].gnb.ran_ue_id; // rrc_ue_id
|
||||
ue_info.ue = arr_ue_id->ue_info_list[ue_idx];
|
||||
if (arr_ue_id->ue_info_list != NULL) {
|
||||
ue_info.ue = arr_ue_id->ue_info_list[ue_idx];
|
||||
}
|
||||
} else if (arr_ue_id->ue_id[ue_idx].type == GNB_CU_UP_UE_ID_E2SM) {
|
||||
/* in OAI implementation, CU-UP ue id = CU-CP ue id
|
||||
=> CU-UP ue id = rrc_ue_id, but it should not be the case by the spec */
|
||||
@@ -171,6 +173,7 @@ static void capture_sst_sd(test_cond_value_t* test_cond_value, uint8_t *sst, uin
|
||||
*sd = malloc(**sd);
|
||||
**sd = buf[1] << 16 | buf[2] << 8 | buf[3];
|
||||
}
|
||||
printf("[E2 AGENT][E2SM-KPM] Condition NSSAI (%d, %x).\n", *sst, (*sd) ? **sd : 0xffffff);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -406,7 +409,10 @@ bool read_kpm_sm(void* data)
|
||||
ue_type_matcher fp_match_cond_type = (*match_cond_arr[test_info.test_cond_type])[node_type];
|
||||
arr_ue_id_t arr_ue_id = fp_match_cond_type(test_info);
|
||||
|
||||
if (arr_ue_id.sz == 0) return false;
|
||||
if (arr_ue_id.sz == 0) {
|
||||
printf("[E2 AGENT][E2SM-KPM] No UE matches the condition criteria.\n");
|
||||
return false;
|
||||
}
|
||||
kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3(&arr_ue_id, &frm_4->action_def_format_1);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "../../flexric/src/sm/rc_sm/ie/ir/ran_param_list.h"
|
||||
#include "../../flexric/src/agent/e2_agent_api.h"
|
||||
#include "openair2/E2AP/flexric/src/lib/sm/enc/enc_ue_id.h"
|
||||
#include "openair2/E2AP/flexric/src/sm/rc_sm/rc_sm_id.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
@@ -379,10 +380,26 @@ static void fill_rc_control(ran_func_def_ctrl_t* ctrl)
|
||||
ctrl_style->ran_param_ctrl_out = NULL;
|
||||
}
|
||||
|
||||
static ran_function_name_t fill_rc_ran_func_name(void)
|
||||
{
|
||||
ran_function_name_t dst = {
|
||||
.name = cp_str_to_ba(SM_RAN_CTRL_SHORT_NAME),
|
||||
.oid = cp_str_to_ba(SM_RAN_CTRL_OID),
|
||||
.description = cp_str_to_ba(SM_RAN_CTRL_DESCRIPTION),
|
||||
.instance = NULL
|
||||
};
|
||||
return dst;
|
||||
}
|
||||
|
||||
e2sm_rc_func_def_t fill_rc_ran_def_gnb(void)
|
||||
{
|
||||
e2sm_rc_func_def_t def = {0};
|
||||
|
||||
// RAN Function Name
|
||||
// Mandatory
|
||||
// 9.3.2
|
||||
def.name = fill_rc_ran_func_name();
|
||||
|
||||
// RAN Function Definition for EVENT TRIGGER
|
||||
// Optional
|
||||
// 9.2.2.2
|
||||
@@ -421,6 +438,11 @@ static e2sm_rc_func_def_t fill_rc_ran_def_cu(void)
|
||||
{
|
||||
e2sm_rc_func_def_t def = {0};
|
||||
|
||||
// RAN Function Name
|
||||
// Mandatory
|
||||
// 9.3.2
|
||||
def.name = fill_rc_ran_func_name();
|
||||
|
||||
// RAN Function Definition for EVENT TRIGGER
|
||||
// Optional
|
||||
// 9.2.2.2
|
||||
@@ -459,6 +481,11 @@ static e2sm_rc_func_def_t fill_rc_ran_def_null(void)
|
||||
{
|
||||
e2sm_rc_func_def_t def = {0};
|
||||
|
||||
// RAN Function Name
|
||||
// Mandatory
|
||||
// 9.3.2
|
||||
def.name = fill_rc_ran_func_name();
|
||||
|
||||
// RAN Function Definition for EVENT TRIGGER
|
||||
// Optional
|
||||
// 9.2.2.2
|
||||
@@ -491,6 +518,11 @@ static e2sm_rc_func_def_t fill_rc_ran_def_cucp(void)
|
||||
{
|
||||
e2sm_rc_func_def_t def = {0};
|
||||
|
||||
// RAN Function Name
|
||||
// Mandatory
|
||||
// 9.3.2
|
||||
def.name = fill_rc_ran_func_name();
|
||||
|
||||
// RAN Function Definition for EVENT TRIGGER
|
||||
// Optional
|
||||
// 9.2.2.2
|
||||
@@ -547,9 +579,6 @@ void read_rc_setup_sm(void* data)
|
||||
rc_e2_setup_t* rc = (rc_e2_setup_t*)data;
|
||||
|
||||
/* Fill the RAN Function Definition with currently supported measurements */
|
||||
|
||||
// RAN Function Name is already filled in fill_ran_function_name() in rc_sm_agent.c
|
||||
|
||||
const ngran_node_t node_type = get_e2_node_type();
|
||||
rc->ran_func_def = ran_def_rc[node_type]();
|
||||
|
||||
|
||||
+141
-118
@@ -11,163 +11,147 @@ Please see [NOTICE](NOTICE.md) file for third party software that is included in
|
||||
|
||||
# Overview
|
||||
|
||||
This tutorial describes the steps of deployment 5G OAI RAN, with integrated E2 agent and a nearRT-RIC using O-RAN compliant FlexRIC.
|
||||
This tutorial describes the steps of deployment 5G OAI RAN, with integrated E2 agent, and a nearRT-RIC using O-RAN compliant FlexRIC.
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
# 1. Installation
|
||||
# 1. Mandatory prerequisites of FlexRIC before starting with E2 agent
|
||||
* [GCC compiler](https://gitlab.eurecom.fr/mosaic5g/flexric#111-gcc-compiler)
|
||||
* [(opt.) configure Wireshark](https://gitlab.eurecom.fr/mosaic5g/flexric#112-opt-wireshark)
|
||||
* [Mandatory dependencies](https://gitlab.eurecom.fr/mosaic5g/flexric#121-mandatory-dependencies)
|
||||
|
||||
## 1.1 Install prerequisites
|
||||
|
||||
- A *recent* CMake (at least v3.15).
|
||||
|
||||
On Ubuntu, you might want to use [this PPA](https://apt.kitware.com/) to install an up-to-date version.
|
||||
|
||||
- SWIG (at least v.4.1).
|
||||
|
||||
We use SWIG as an interface generator to enable the multi-language feature (i.e., C/C++ and Python) for the xApps. Please, check your SWIG version (i.e, `swig
|
||||
-version`) and install it from scratch if necessary as described here: https://swig.org/svn.html or via the code below:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/swig/swig.git
|
||||
cd swig
|
||||
git checkout release-4.1
|
||||
./autogen.sh
|
||||
./configure --prefix=/usr/
|
||||
make -j8
|
||||
make install
|
||||
```
|
||||
|
||||
- Flatbuffer encoding(optional).
|
||||
|
||||
We also provide a flatbuffers encoding/decoding scheme as alternative to ASN.1. In case that you want to use it follow the
|
||||
instructions at https://github.com/dvidelabs/flatcc and provide the path for the lib and include when selecting it at `ccmake ..` from the build directory
|
||||
|
||||
## 1.2 Download the required dependencies.
|
||||
|
||||
Below an example of how to install it in ubuntu
|
||||
```bash
|
||||
sudo apt install libsctp-dev python3.8 cmake-curses-gui libpcre2-dev python-dev
|
||||
```
|
||||
|
||||
# 2. Deployment
|
||||
|
||||
## 2.1 OAI RAN
|
||||
OAI E2 agent contains:
|
||||
* RAN functions: exposure of service models capabilities
|
||||
* FlexRIC submodule: for message enc/dec
|
||||
|
||||
Currently available versions:
|
||||
| |E2SM-KPM v2.03|E2SM-KPM v3.00|
|
||||
|:-----------|:-------------|:-------------|
|
||||
| E2AP v1.01 | Y | Y |
|
||||
| E2AP v2.03 | Y (default) | Y |
|
||||
| E2AP v3.01 | Y | Y |
|
||||
|
||||
Note: E2SM-KPM `v2.01` is supported only in FlexRIC, but not in OAI.
|
||||
|
||||
### 2.1.1 Clone the OAI repository
|
||||
```bash
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g oai
|
||||
cd oai/
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g
|
||||
```
|
||||
|
||||
### 2.1.2 Build OAI with E2 Agent
|
||||
|
||||
- By default, OAI will build the E2 Agent with E2AP v2 and KPM v2. If you want a different version, edit the variable E2AP\_VERSION and KPM\_VERSION at OAI's CMakeLists.txt file.
|
||||
|
||||
Currently available versions:
|
||||
| |KPM v2.03|KPM v3.00|
|
||||
|:-----------|:--------|:--------|
|
||||
| E2AP v1.01 | Y | Y |
|
||||
| E2AP v2.03 | Y | Y |
|
||||
| E2AP v3.01 | Y | Y |
|
||||
|
||||
Please note that KPM SM v2.01 is supported only in FlexRIC, but not in OAI.
|
||||
|
||||
#### Using build_oai script
|
||||
```bash
|
||||
cd cmake_targets/
|
||||
./build_oai -I -w SIMU --gNB --nrUE --build-e2 --ninja
|
||||
cd openairinterface5g/cmake_targets/
|
||||
./build_oai -I # if you never installed OAI, use this command once before the next line
|
||||
#
|
||||
./build_oai --gNB --nrUE --build-e2 --cmake-opt -DE2AP_VERSION=E2AP_VX --cmake-opt -DKPM_VERSION=KPM_VY --ninja
|
||||
```
|
||||
where `X`=`1`,`2`,`3`, and `Y`=`2_03`,`3_00`.
|
||||
|
||||
* `-I` option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed.
|
||||
* `-w` option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from `liboai_device.so` to the true device which will be used at run-time (here the USRP one, liboai_usrpdevif.so). The RF simulatorRF simulator is implemented as a specific device replacing RF hardware, it can be specifically built using `-w SIMU` option, but is also built during any softmodem build.
|
||||
* `-w` option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from `liboai_device.so` to the true device which will be used at run-time (here the USRP one, `liboai_usrpdevif.so`). The RF simulator is implemented as a specific device replacing RF hardware, it can be specifically built using `-w SIMU` option, but is also built during any softmodem build.
|
||||
* `--gNB` is to build the `nr-softmodem` and `nr-cuup` executables and all required shared libraries
|
||||
* `--nrUE` is to build the `nr-uesoftmodem` executable and all required shared libraries
|
||||
* `--ninja` is to use the ninja build tool, which speeds up compilation
|
||||
* `--build-e2` option is to use the E2 agent, integrated within RAN.
|
||||
* `--build-e2` option is to use the E2 agent, integrated within E2 nodes (gNB-mono, DU, CU, CU-UP, CU-CP).
|
||||
|
||||
If the openair2/E2AP/flexric folder is empty, try manually the following commands:
|
||||
#### Using cmake directly
|
||||
```bash
|
||||
git submodule init
|
||||
git submodule update
|
||||
cd openairinterface5g
|
||||
mkdir build && cd build
|
||||
cmake .. -GNinja -DE2_AGENT=ON -DE2AP_VERSION=E2AP_VX -DKPM_VERSION=KPM_VY
|
||||
ninja nr-softmodem nr-cuup nr-uesoftmodem params_libconfig rfsimulator
|
||||
```
|
||||
where `X`=`1`,`2`,`3`, and `Y`=`2_03`,`3_00`.
|
||||
|
||||
|
||||
## 2.2 FlexRIC
|
||||
Important to note: OAI RAN and FlexRIC must be compiled with the same E2AP and E2SM-KPM versions.
|
||||
|
||||
By default, FlexRIC will build the nearRT-RIC with E2AP v2 and KPM v2. If you want a different version, edit the variable E2AP\_VERSION and KPM\_VERSION at FlexRIC's CMakeLists.txt file. Note that OAI's and FlexRIC's E2AP\_VERSION and KPM\_VERSION need to match due to O-RAN incompatibilities among versions.
|
||||
|
||||
|
||||
### 2.2.1 Clone the FlexRIC repository
|
||||
### 2.2.1 Case 1: OAI RAN and FlexRIC on the same machine
|
||||
Instead of cloning the new FlexRIC repository, feel free to use FlexRIC submodule as a nearRT-RIC + xApp framework, apart from the E2 agent side. In order to achieve this, please follow the next steps:
|
||||
```bash
|
||||
git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric
|
||||
cd flexric/
|
||||
git checkout f1c08ed2b9b1eceeda7941dd7bf435db0168dd56
|
||||
cd openairinterface5g/openair2/E2AP/flexric
|
||||
git submodule init && git submodule update # only if OAI RAN wasn't previously compiled with --build-e2 or -DE2_AGENT options
|
||||
```
|
||||
and continue as described in the [build FlexRIC section](https://gitlab.eurecom.fr/mosaic5g/flexric#22-build-flexric).
|
||||
|
||||
### 2.2.2 Build FlexRIC
|
||||
```bash
|
||||
mkdir build && cd build && cmake .. && make -j8
|
||||
```
|
||||
### 2.2.2 Case 2: OAI RAN and FlexRIC on different machines
|
||||
The [FlexRIC submodule compilation step](#221-case-1-oai-ran-and-flexric-on-the-same-machine) is **mandatory** as the OAI RAN must use the Service Models (which are built as shared libraries).
|
||||
To build FlexRIC on the other machine, follow the complete [FlexRIC installation](https://gitlab.eurecom.fr/mosaic5g/flexric#2-flexric-installation) process.
|
||||
|
||||
### 2.2.3 Installation of Service Models (SMs)
|
||||
```bash
|
||||
sudo make install
|
||||
```
|
||||
|
||||
By default the service model libraries will be installed in the path `/usr/local/lib/flexric` while the configuration file in `/usr/local/etc/flexric`.
|
||||
|
||||
# 3. Service Models available in OAI RAN
|
||||
|
||||
## 3.1 O-RAN
|
||||
For a deeper understanding, we recommend that users of FlexRIC familiarize themselves with O-RAN WG3 specifications available at the [O-RAN specifications page](https://orandownloadsweb.azurewebsites.net/specifications).
|
||||
|
||||
We assume that user is familiar with O-RAN WG3 specifications that can be found at https://orandownloadsweb.azurewebsites.net/specifications.
|
||||
The following specifications are recommended:
|
||||
* `O-RAN.WG3.E2GAP-v02.00` - nearRT-RIC architecture & E2 General Aspects and Principles: important for a general understanding for E2
|
||||
* `O-RAN.WG3.E2AP-version` - E2AP protocol description
|
||||
* `O-RAN.WG3.E2SM-KPM-version` - E2SM-KPM Service Model description
|
||||
* `O-RAN.WG3.E2SM-RC-v01.03` - E2SM-RC Service Model description
|
||||
|
||||
### 3.1.1 E2SM-KPM
|
||||
|
||||
As mentioned in section [2.1.2 Build OAI with E2 Agent](#212-build-oai-with-e2-agent), we support KPM v2.03/v3.00. Uses ASN.1 encoding.
|
||||
As mentioned in section [2.1 OAI RAN](#21-oai-ran), we support KPM `v2.03/v3.00` which all use ASN.1 encoding.
|
||||
|
||||
Per O-RAN specifications, 5G measurements supported by KPM are specified in 3GPP TS 28.552.
|
||||
|
||||
From 3GPP TS 28.552, we support the following list:
|
||||
* "DRB.PdcpSduVolumeDL"
|
||||
* "DRB.PdcpSduVolumeUL"
|
||||
* "DRB.RlcSduDelayDl"
|
||||
* "DRB.UEThpDl"
|
||||
* "DRB.UEThpUl"
|
||||
* "RRU.PrbTotDl"
|
||||
* "RRU.PrbTotUl"
|
||||
* `DRB.PdcpSduVolumeDL`
|
||||
* `DRB.PdcpSduVolumeUL`
|
||||
* `DRB.RlcSduDelayDl`
|
||||
* `DRB.UEThpDl`
|
||||
* `DRB.UEThpUl`
|
||||
* `RRU.PrbTotDl`
|
||||
* `RRU.PrbTotUl`
|
||||
|
||||
From O-RAN.WG3.E2SM-KPM-version specification, we implemented:
|
||||
* REPORT Service Style 4 ("Common condition-based, UE-level" - section 7.4.5) - fetch above measurements per each UE that matches common criteria (e.g. S-NSSAI).
|
||||
From `O-RAN.WG3.E2SM-KPM-version` specification, we implemented:
|
||||
* REPORT Service Style 4 ("Common condition-based, UE-level" - section 7.4.5) - fetch above measurements per each UE based on the common S-NSSAI `(1, 0xffffff)` condition
|
||||
|
||||
### 3.1.2 E2SM-RC
|
||||
We support E2SM-RC `v1.03` which uses ASN.1 encoding.
|
||||
|
||||
We support RC v1.03. Uses ASN.1 encoding.
|
||||
|
||||
From ORAN.WG3.E2SM-RC-v01.03 specification, we implemented:
|
||||
From `O-RAN.WG3.E2SM-RC-v01.03` specification, we implemented:
|
||||
* REPORT Service Style 1 ("Message copy" - section 7.4.2) - aperiodic subscription for "RRC Message" and "UE ID"
|
||||
* REPORT Service Style 4 ("UE Information" - section 7.4.5) - aperiodic subscription for "UE RRC State Change"
|
||||
* CONTROL Service Style 1 ("Radio Bearer Control" - section 7.6.2) - "QoS flow mapping configuration" (e.g creating a new DRB)
|
||||
* CONTROL Service Style 1 ("Radio Bearer Control" - section 7.6.2) - "QoS flow mapping configuration"; please be aware that this functionality is defined as per O-RAN "To control the multiplexing of QoS flows to a DRB",
|
||||
but OAI RAN doesn't support multiple QoS flows in one DRB. Therefore, this use case was adjusted for creation of new DRB, instead of creation of new QoS flow in the existing DRB.
|
||||
More information can be found in the branch [qoe-e2](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/qoe-e2?ref_type=heads). It's not merged due to incompliance with O-RAN specifications.
|
||||
We showcased this demo in the O-RAN F2F Osaka meeting. Please feel free to download the [demo video](https://lf-o-ran-sc.atlassian.net/wiki/download/attachments/13566077/oai-flexric-demo-ric.mp4?api=v2) and [accompanying presentation](https://lf-o-ran-sc.atlassian.net/wiki/download/attachments/13566077/oai-FlexRIC-demo.pdf?api=v2).
|
||||
|
||||
## 3.2 Custom Service Models
|
||||
In addition, we support custom Service Models for L2/L3. Please find the KPIs for each layer in the following structs:
|
||||
* MAC: `mac_ue_stats_impl_t`
|
||||
* RLC: `rlc_radio_bearer_stats_t`
|
||||
* PDCP: `pdcp_radio_bearer_stats_t`
|
||||
* GTP: `gtp_ngu_t_stats_t`
|
||||
|
||||
In addition, we support custom Service Models, such are MAC, RLC, PDCP, and GTP. Use plain encoding.
|
||||
All use plain encoding, i.e., no ASN.1, but write the binary data into network messages.
|
||||
|
||||
If you are interested in TC and SLICE SMs, please follow the instructions at https://gitlab.eurecom.fr/mosaic5g/flexric.
|
||||
There exist two additional custom Service Models, SLICE and TC (traffic control), but they are not supported in OAI RAN. They can only be tested with [E2 agent emulators](https://gitlab.eurecom.fr/mosaic5g/flexric#4-deployment) within FlexRIC framework.
|
||||
|
||||
# 4. Start the process
|
||||
At this point, we assume the 5G Core Network is already running in the background. For more information, please follow the [5GCN tutorial](../../doc/NR_SA_Tutorial_OAI_CN5G.md).
|
||||
|
||||
At this point, we assume the 5G Core Network is already running in the background. For more information, please follow the tutorial at https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_OAI_CN5G.md.
|
||||
Optionally run Wireshark and capture E2AP traffic.
|
||||
|
||||
In order to configure E2 agent, please, add the following block in OAI's configuration file:
|
||||
The E2 node (gNB-mono, DU, CU, CU-UP, CU-CP) configuration file must contain the `e2_agent` section. Please adjust the following example to your needs:
|
||||
```bash
|
||||
e2_agent = {
|
||||
near_ric_ip_addr = "127.0.0.1";
|
||||
sm_dir = "/usr/local/lib/flexric/"
|
||||
sm_dir = "/usr/local/lib/flexric/";
|
||||
}
|
||||
```
|
||||
* start E2 Node agents
|
||||
|
||||
As per O-RAN.WG3.E2SM-v02.00 specifications, UE ID (section 6.2.2.6) representation in OAI is:
|
||||
* start the E2 nodes
|
||||
|
||||
As per `O-RAN.WG3.E2SM-v02.00` specifications, `UE ID` (section 6.2.2.6) representation in OAI is:
|
||||
| | gNB-mono | CU | CU-CP | CU-UP | DU |
|
||||
|:----------------------|:----------------|:----------------|:----------------|:----------------------|:-------------------|
|
||||
| CHOICE UE ID case | GNB_UE_ID_E2SM | GNB_UE_ID_E2SM | GNB_UE_ID_E2SM | GNB_CU_UP_UE_ID_E2SM | GNB_DU_UE_ID_E2SM |
|
||||
@@ -179,68 +163,107 @@ e2_agent = {
|
||||
|
||||
* start the gNB-mono
|
||||
```bash
|
||||
cd oai/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --rfsim -E
|
||||
cd <path-to>/build
|
||||
sudo ./nr-softmodem -O <path-to>/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim
|
||||
```
|
||||
|
||||
* if CU/DU split is used, start the gNB as follows
|
||||
```bash
|
||||
sudo ./nr-softmodem -O <path_to_du_conf_file> --rfsim -E
|
||||
sudo ./nr-softmodem -O <path_to_cu_conf_file>
|
||||
cd <path-to>/build
|
||||
sudo ./nr-softmodem -O <path-to>/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf --rfsim
|
||||
sudo ./nr-softmodem -O <path-to>/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf
|
||||
```
|
||||
|
||||
* if CU-CP/CU-UP/DU split is used, start the gNB as follows
|
||||
```bash
|
||||
sudo ./nr-softmodem -O <path_to_du_conf_file> --rfsim -E
|
||||
sudo ./nr-softmodem -O <path_to_cu_cp_conf_file>
|
||||
sudo ./nr-cuup -O <path_to_cu_up_conf_file>
|
||||
cd <path-to>/build
|
||||
sudo ./nr-softmodem -O <path-to>/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf --rfsim
|
||||
./nr-softmodem -O <path-to>/ci-scripts/conf_files/gnb-cucp.sa.f1.conf --gNBs.[0].plmn_list.[0].mcc 001 --gNBs.[0].plmn_list.[0].mnc 01 --gNBs.[0].local_s_address "127.0.0.3" --gNBs.[0].amf_ip_address.[0].ipv4 "192.168.70.132" --gNBs.[0].E1_INTERFACE.[0].ipv4_cucp "127.0.0.3" --gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NG_AMF "192.168.70.129" --e2_agent.near_ric_ip_addr "127.0.0.1" --e2_agent.sm_dir "/usr/local/lib/flexric/"
|
||||
sudo ./nr-cuup -O <path-to>/ci-scripts/conf_files/gnb-cuup.sa.f1.conf --gNBs.[0].plmn_list.[0].mcc 001 --gNBs.[0].plmn_list.[0].mnc 01 --gNBs.[0].local_s_address "127.0.0.6" --gNBs.[0].E1_INTERFACE.[0].ipv4_cucp "127.0.0.3" --gNBs.[0].E1_INTERFACE.[0].ipv4_cuup "127.0.0.6" --gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NG_AMF "192.168.70.129" --gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NGU "192.168.70.129" --e2_agent.near_ric_ip_addr "127.0.0.1" --e2_agent.sm_dir "/usr/local/lib/flexric/" --rfsim
|
||||
|
||||
```
|
||||
|
||||
* start the nrUE
|
||||
```bash
|
||||
cd oai/cmake_targets/ran_build/build
|
||||
cd <path-to>/build
|
||||
# for gNB-mono
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --uicc0.imsi 001010000000001 --rfsimulator.serveraddr 127.0.0.1
|
||||
# for CU/DU and CU-CP/CU-UP/DU split
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3450720000 --rfsim --uicc0.imsi 001010000000001 --rfsimulator.serveraddr 127.0.0.1
|
||||
```
|
||||
Note: [multi-UE rfsim deployment tutorial](../../doc/NR_SA_Tutorial_OAI_multi_UE.md?ref_type=heads#run-multiple-ues-in-rfsimulator)
|
||||
|
||||
* start the nearRT-RIC
|
||||
```bash
|
||||
cd flexric
|
||||
cd flexric # or openairinterface5g/openair2/E2AP/flexric
|
||||
./build/examples/ric/nearRT-RIC
|
||||
```
|
||||
|
||||
`XAPP_DURATION` environment variable overwrites the default xApp duration of 20s.
|
||||
* Start different xApps
|
||||
|
||||
* start the KPM monitor xApp - measurements stated in [3.1.1 E2SM-KPM](#311-e2sm-kpm) for each UE that matches S-NSSAI common criteria
|
||||
Important to note: if no RIC INDICATION is received by any of the xApps, either the
|
||||
* start the KPM monitor xApp - measurements stated in [3.1.1 E2SM-KPM](#311-e2sm-kpm) for each UE that matches S-NSSAI `(1, 0xffffff)` common criteria
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/monitor/xapp_kpm_moni
|
||||
cd flexric # or openairinterface5g/openair2/E2AP/flexric
|
||||
XAPP_DURATION=30 ./build/examples/xApp/c/monitor/xapp_kpm_moni
|
||||
```
|
||||
Note: we assume that each UE has only 1 DRB; CU-UP does not store the slices, therefore "coarse filtering" is used
|
||||
Note: we assume that each UE has only 1 DRB; CU-UP does not store the slices, therefore "coarse filtering" is used; **if no RIC INDICATION message received**, please check if:
|
||||
(1) UE is connected to the gNB
|
||||
(2) UE has a PDU session (LCID 4)
|
||||
(3) UE supports the slice `(1, 0xffffff)`
|
||||
|
||||
* start the RC monitor xApp - aperiodic subscriptions for "UE RRC State Change", "RRC Message" copy (`RRC Reconfiguration`, `Measurement Report`, `Security Mode Complete`, `RRC Setup Complete`), and "UE ID" when `RRC Setup Complete` and/or `F1 UE Context Setup Request` detected
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/monitor/xapp_rc_moni
|
||||
cd flexric # or openairinterface5g/openair2/E2AP/flexric
|
||||
XAPP_DURATION=30 ./build/examples/xApp/c/monitor/xapp_rc_moni
|
||||
```
|
||||
|
||||
* start the RC control xApp - RAN control function "QoS flow mapping configuration" (e.g. creating a new DRB)
|
||||
* start the KPM monitor and RC control xApp - this xApp is only a PoC. It collects the measurements stated in [3.1.1 E2SM-KPM](#311-e2sm-kpm) and sends the RC Control message
|
||||
for "QoS flow mapping configuration". However, no control is being done within the RAN itself. Please refer to [3.1.2 E2SM-RC](#312-e2sm-rc) for detailed explanation.
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/kpm_rc/xapp_kpm_rc
|
||||
cd flexric # or openairinterface5g/openair2/E2AP/flexric
|
||||
XAPP_DURATION=30 ./build/examples/xApp/c/kpm_rc/xapp_kpm_rc
|
||||
```
|
||||
|
||||
* start the (MAC + RLC + PDCP + GTP) monitor xApp
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_moni
|
||||
cd flexric # or openairinterface5g/openair2/E2AP/flexric
|
||||
XAPP_DURATION=30 ./build/examples/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_moni
|
||||
```
|
||||
Note: GTP is not yet implemented in CU-UP; **if no RIC INDICATION message received**, please check if:
|
||||
(1) UE is connected to the gNB
|
||||
(2) UE has a PDU session (LCID 4) - if no PDU session, only MAC/GTP stats will be sent
|
||||
|
||||
* if `XAPP_MULTILANGUAGE` option is enabled, start the python xApps:
|
||||
```bash
|
||||
XAPP_DURATION=30 python3 build/examples/xApp/python3/xapp_mac_rlc_pdcp_gtp_moni.py # only supported by the gNB-mono
|
||||
```
|
||||
|
||||
The latency that you observe in your monitor xApp is the latency from the E2 Agent to the nearRT-RIC and xApp.
|
||||
Therefore, FlexRIC is well suited for use cases with ultra low-latency requirements.
|
||||
Additionally, all the data received in the `xapp_gtp_mac_rlc_pdcp_moni` xApp is also written to /tmp/xapp_db in case that offline data processing is wanted (e.g., Machine Learning/Artificial Intelligence applications). You can browse the data using e.g., sqlitebrowser.
|
||||
Additionally, all the data received in the `xapp_gtp_mac_rlc_pdcp_moni` xApp is also written to `/tmp/xapp_db_` in case that offline data processing is wanted (e.g., Machine Learning/Artificial Intelligence applications). You can browse the data using e.g., `sqlitebrowser`.
|
||||
|
||||
Please note:
|
||||
* KPM SM database is not been updated, therefore commented in `flexric/src/xApp/db/sqlite3/sqlite3_wrapper.c:1152`
|
||||
* RC SM database is not yet implemented.
|
||||
|
||||
# Optional - Multiple UEs
|
||||
# 5. O-RAN SC nearRT-RIC interoperability
|
||||
|
||||
If you are interested in having multiple UEs in rfsim mode, please, follow the instructions at https://gitlab.eurecom.fr/oaiworkshop/summerworkshop2023/-/tree/main/ran#multiple-ues.
|
||||
The E2AP port for OSC nearRT-RIC is 36422, but the default value in E2 agent is 36421. Before proceeding with integration, please set the `e2ap_server_port` to 36422, and recompile the OAI.
|
||||
|
||||
## 5.1 H release
|
||||
We showcased the QoE use case during the O-RAN F2F meeting Phoenix, October 2023:
|
||||
* [recorded presentation](https://zoom.us/rec/play/N5mnAQUcEVRf8HN6qLYa4k7kjNq3bK4hQiYqHGv9KUoLfcR6GHiE-GvnmAudT6xccmZSbkxxYHRwTaxk.Zi7d8Sl1kQ6Sk1SH?canPlayFromShare=true&from=share_recording_detail&continueMode=true&componentName=rec-play&originRequestUrl=https%3A%2F%2Fzoom.us%2Frec%2Fshare%2FwiYXulPlAqIIDY_vLPQSGqYIj-e5Ef_UCxveMjrDNGgXLLvEcDF4v1cmVBe8imb4.WPi-DA_dfPDBQ0FH). This use case is shown after 4 minutes (04:00).
|
||||
* [accompanying flyer](https://openairinterface.org/wp-content/uploads/2023/10/demo2-phoenix.pdf)
|
||||
|
||||
The same was shown in the following events:
|
||||
* [Joint OSC/OSFG-OAI Workshop](https://openairinterface.org/joint-osc-oai-workshop-end-to-end-open-source-reference-designs-for-o-ran/)
|
||||
|
||||
In order to reproduce this testbed, please follow the [O-RAN SC nearRT-RIC installation guide](https://lf-o-ran-sc.atlassian.net/wiki/spaces/GS/overview), and the [kpm-rc-xapp](https://github.com/mirazabal/kpm_rc-xapp) xApp used. Please note that we cannot give support for the O-RAN SC nearRT-RIC.
|
||||
|
||||
## 5.2 J release
|
||||
The OAI E2 Agent has been successfully integrated with the J release of the O-RAN OSC nearRT-RIC, leveraging the xDevSM framework developed by the MMWG at the University of Bologna and the WIoT at Northeastern University.
|
||||
|
||||
xDevSM framework uses KPM SM (`libkpm_sm.so`) and RC SM (`librc_sm.so`) libraries from FlexRIC. Therefore, only E2AP is validated between OAI E2 Agent and OSC nearRT-RIC.
|
||||
|
||||
Please follow [the xDevSM framework tutorial](https://openrangym.com/tutorials/xdevsm-tutorial) in order to reproduce this testbed, and try [the example xApps](https://github.com/wineslab/xDevSM-xapps-examples) built using this framework.
|
||||
|
||||
+1
-1
Submodule openair2/E2AP/flexric updated: 2638b58e20...df754a8553
@@ -61,6 +61,8 @@
|
||||
#define HLP_L1_PHASE_COMP "Apply NR symbolwise phase rotation"
|
||||
#define CONFIG_STRING_NUM_ANTENNAS_PER_THREAD "dmrs_num_antennas_per_thread"
|
||||
#define HLP_NUM_ARX "Number of antennas per thread for PUSCH channel estimation"
|
||||
#define CONFIG_STRING_ANALOG_DAS "enable_das"
|
||||
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* L1 configuration parameters */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
@@ -81,12 +83,13 @@
|
||||
{CONFIG_STRING_L1_PRACH_DTX_THRESHOLD, NULL, 0, .uptr=NULL, .defintval=150, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_PUSCH_DTX_THRESHOLD, NULL, 0, .uptr=NULL, .defintval=50, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_SRS_DTX_THRESHOLD, NULL, 0, .uptr=NULL, .defintval=30, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_MAX_LDPC_ITERATIONS, NULL, 0, .uptr=NULL, .defintval=8, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_RX_THREAD_CORE, NULL, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_TX_THREAD_CORE, NULL, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_MAX_LDPC_ITERATIONS, NULL, 0, .uptr=NULL, .defintval=8, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_RX_THREAD_CORE, NULL, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_TX_THREAD_CORE, NULL, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_TX_AMP_BACKOFF_dB, HLP_L1TX_BO,0, .uptr=NULL, .defintval=36, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_PHASE_COMP, HLP_L1_PHASE_COMP,PARAMFLAG_BOOL, .uptr=NULL,.defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_NUM_ANTENNAS_PER_THREAD, HLP_NUM_ARX,0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_ANALOG_DAS, NULL, 0, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
#define L1_CC_IDX 0
|
||||
@@ -109,6 +112,7 @@
|
||||
#define L1_TX_AMP_BACKOFF_dB 17
|
||||
#define L1_PHASE_COMP 18
|
||||
#define NUM_ANTENNAS_PER_THREAD 19
|
||||
#define L1_ANALOG_DAS 20
|
||||
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
#define CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING "set_analog_beamforming"
|
||||
#define CONFIG_STRING_MACRLC_BEAM_DURATION "beam_duration"
|
||||
#define CONFIG_STRING_MACRLC_BEAMS_PERIOD "beams_per_period"
|
||||
#define CONFIG_STRING_MACRLC_BEAM_WEIGHTS_LIST "beam_weights"
|
||||
#define CONFIG_STRING_MACRLC_PUSCH_RSSI_THRESHOLD "pusch_RSSI_Threshold"
|
||||
#define CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD "pucch_RSSI_Threshold"
|
||||
|
||||
@@ -143,6 +144,7 @@
|
||||
{CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING, HLP_MACRLC_AB, PARAMFLAG_BOOL, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_BEAM_DURATION, HLP_MACRLC_BEAM_DURATION, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_BEAMS_PERIOD, HLP_MACRLC_BEAMS_PERIOD, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_BEAM_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY,0}, \
|
||||
{CONFIG_STRING_MACRLC_PUSCH_RSSI_THRESHOLD, HLP_MACRLC_PUSCH_RSSI_THRESHOLD, \
|
||||
0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
|
||||
{CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD, HLP_MACRLC_PUCCH_RSSI_THRESHOLD, \
|
||||
@@ -189,8 +191,9 @@
|
||||
#define MACRLC_ANALOG_BEAMFORMING_IDX 36
|
||||
#define MACRLC_ANALOG_BEAM_DURATION_IDX 37
|
||||
#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 38
|
||||
#define MACRLC_PUSCH_RSSI_THRES_IDX 39
|
||||
#define MACRLC_PUCCH_RSSI_THRES_IDX 40
|
||||
#define MACRLC_BEAMWEIGHTS_IDX 39
|
||||
#define MACRLC_PUSCH_RSSI_THRES_IDX 40
|
||||
#define MACRLC_PUCCH_RSSI_THRES_IDX 41
|
||||
|
||||
#define MACRLCPARAMS_CHECK { \
|
||||
{ .s5 = { NULL } }, \
|
||||
@@ -232,6 +235,7 @@
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s2 = { config_check_intrange, {-1280, 0}} }, /* PUSCH RSSI threshold range */ \
|
||||
{ .s2 = { config_check_intrange, {-1280, 0}} }, /* PUCCH RSSI threshold range */ \
|
||||
}
|
||||
|
||||
+112
-46
@@ -846,7 +846,11 @@ static void verify_section_notset(configmodule_interface_t *cfg, char *aprefix,
|
||||
paramlist_def_t pl = {0};
|
||||
strncpy(pl.listname, secname, sizeof(pl.listname) - 1);
|
||||
config_getlist(cfg, &pl, NULL, 0, aprefix);
|
||||
AssertFatal(pl.numelt == 0, "Section \"%s.%s\" not allowed in this config, please remove it\n", aprefix ? aprefix : "", secname);
|
||||
AssertFatal(pl.numelt == 0,
|
||||
"Section \"%s%s%s\" not allowed in this config, please remove it\n",
|
||||
aprefix ? aprefix : "",
|
||||
aprefix ? "." : "",
|
||||
secname);
|
||||
}
|
||||
void RCconfig_verify(configmodule_interface_t *cfg, ngran_node_t node_type)
|
||||
{
|
||||
@@ -879,6 +883,7 @@ void RCconfig_verify(configmodule_interface_t *cfg, ngran_node_t node_type)
|
||||
verify_section_notset(cfg, NULL, CONFIG_STRING_L1_LIST);
|
||||
verify_section_notset(cfg, NULL, CONFIG_STRING_RU_LIST);
|
||||
verify_section_notset(cfg, NULL, CONFIG_STRING_MACRLC_LIST);
|
||||
verify_section_notset(cfg, NULL, CONFIG_STRING_NR_RLC_LIST);
|
||||
} else if (NODE_IS_DU(node_type)) {
|
||||
// verify that there is no bearer config
|
||||
verify_gnb_param_notset(gnbp, GNB_ENABLE_SDAP_IDX, GNB_CONFIG_STRING_ENABLE_SDAP);
|
||||
@@ -886,6 +891,7 @@ void RCconfig_verify(configmodule_interface_t *cfg, ngran_node_t node_type)
|
||||
|
||||
verify_section_notset(cfg, GNB_CONFIG_STRING_GNB_LIST ".[0]", GNB_CONFIG_STRING_AMF_IP_ADDRESS);
|
||||
verify_section_notset(cfg, NULL, CONFIG_STRING_SECURITY);
|
||||
verify_section_notset(cfg, NULL, CONFIG_STRING_NR_PDCP_LIST);
|
||||
} // else nothing to be checked
|
||||
|
||||
/* other possible verifications: PNF, VNF, CU-CP, CU-UP, ...? */
|
||||
@@ -1061,6 +1067,7 @@ void RCconfig_NR_L1(void)
|
||||
gNB->TX_AMP = min(32767.0 / pow(10.0, .05 * (double)(*L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr)), INT16_MAX);
|
||||
gNB->phase_comp = *L1_ParamList.paramarray[j][L1_PHASE_COMP].uptr;
|
||||
gNB->dmrs_num_antennas_per_thread = *(L1_ParamList.paramarray[j][NUM_ANTENNAS_PER_THREAD].uptr);
|
||||
gNB->enable_analog_das = *(L1_ParamList.paramarray[j][L1_ANALOG_DAS].uptr);
|
||||
LOG_I(NR_PHY, "TX_AMP = %d (-%d dBFS)\n", gNB->TX_AMP, *L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr);
|
||||
AssertFatal(gNB->TX_AMP > 300, "TX_AMP is too small, must be larger than 300 (is %d)\n", gNB->TX_AMP);
|
||||
// Midhaul configuration
|
||||
@@ -1467,6 +1474,55 @@ static seq_arr_t *fill_du_sibs(paramdef_t *GNBparamarray)
|
||||
return du_SIBs;
|
||||
}
|
||||
|
||||
void config_rlc(configmodule_interface_t *cfg, nr_rlc_configuration_t *rlc_config)
|
||||
{
|
||||
/* SRB configuration */
|
||||
paramdef_t rlc_srb_params[] = NR_RLC_SRB_GLOBALPARAMS_DESC;
|
||||
int ret = config_get(cfg, rlc_srb_params, sizeofArray(rlc_srb_params), CONFIG_STRING_NR_RLC_SRB);
|
||||
AssertFatal(ret >= 0, "problem reading NR RLC configuration from configuration file\n");
|
||||
|
||||
rlc_config->srb.t_poll_retransmit = config_get_processedint(cfg, &rlc_srb_params[CONFIG_NR_RLC_SRB_T_POLL_RETRANSMIT_IDX]);
|
||||
rlc_config->srb.t_reassembly = config_get_processedint(cfg, &rlc_srb_params[CONFIG_NR_RLC_SRB_T_REASSEMBLY_IDX]);
|
||||
rlc_config->srb.t_status_prohibit = config_get_processedint(cfg, &rlc_srb_params[CONFIG_NR_RLC_SRB_T_STATUS_PROHIBIT_IDX]);
|
||||
rlc_config->srb.poll_pdu = config_get_processedint(cfg, &rlc_srb_params[CONFIG_NR_RLC_SRB_POLL_PDU_IDX]);
|
||||
rlc_config->srb.poll_byte = config_get_processedint(cfg, &rlc_srb_params[CONFIG_NR_RLC_SRB_POLL_BYTE_IDX]);
|
||||
rlc_config->srb.max_retx_threshold = config_get_processedint(cfg, &rlc_srb_params[CONFIG_NR_RLC_SRB_MAX_RETX_THRESHOLD_IDX]);
|
||||
rlc_config->srb.sn_field_length = config_get_processedint(cfg, &rlc_srb_params[CONFIG_NR_RLC_SRB_SN_FIELD_LENGTH_IDX]);
|
||||
|
||||
/* DRB AM configuration */
|
||||
paramdef_t rlc_drb_am_params[] = NR_RLC_DRB_AM_GLOBALPARAMS_DESC;
|
||||
ret = config_get(cfg, rlc_drb_am_params, sizeofArray(rlc_drb_am_params), CONFIG_STRING_NR_RLC_DRB_AM);
|
||||
AssertFatal(ret >= 0, "problem reading NR RLC configuration from configuration file\n");
|
||||
|
||||
rlc_config->drb_am.t_poll_retransmit = config_get_processedint(cfg, &rlc_drb_am_params[CONFIG_NR_RLC_DRB_AM_T_POLL_RETRANSMIT_IDX]);
|
||||
rlc_config->drb_am.t_reassembly = config_get_processedint(cfg, &rlc_drb_am_params[CONFIG_NR_RLC_DRB_AM_T_REASSEMBLY_IDX]);
|
||||
rlc_config->drb_am.t_status_prohibit = config_get_processedint(cfg, &rlc_drb_am_params[CONFIG_NR_RLC_DRB_AM_T_STATUS_PROHIBIT_IDX]);
|
||||
rlc_config->drb_am.poll_pdu = config_get_processedint(cfg, &rlc_drb_am_params[CONFIG_NR_RLC_DRB_AM_POLL_PDU_IDX]);
|
||||
rlc_config->drb_am.poll_byte = config_get_processedint(cfg, &rlc_drb_am_params[CONFIG_NR_RLC_DRB_AM_POLL_BYTE_IDX]);
|
||||
rlc_config->drb_am.max_retx_threshold = config_get_processedint(cfg, &rlc_drb_am_params[CONFIG_NR_RLC_DRB_AM_MAX_RETX_THRESHOLD_IDX]);
|
||||
rlc_config->drb_am.sn_field_length = config_get_processedint(cfg, &rlc_drb_am_params[CONFIG_NR_RLC_DRB_AM_SN_FIELD_LENGTH_IDX]);
|
||||
|
||||
/* DRB UM configuration */
|
||||
paramdef_t rlc_drb_um_params[] = NR_RLC_DRB_UM_GLOBALPARAMS_DESC;
|
||||
ret = config_get(cfg, rlc_drb_um_params, sizeofArray(rlc_drb_um_params), CONFIG_STRING_NR_RLC_DRB_UM);
|
||||
AssertFatal(ret >= 0, "problem reading NR RLC configuration from configuration file\n");
|
||||
|
||||
rlc_config->drb_um.t_reassembly = config_get_processedint(cfg, &rlc_drb_um_params[CONFIG_NR_RLC_DRB_UM_T_REASSEMBLY_IDX]);
|
||||
rlc_config->drb_um.sn_field_length = config_get_processedint(cfg, &rlc_drb_um_params[CONFIG_NR_RLC_DRB_UM_SN_FIELD_LENGTH_IDX]);
|
||||
}
|
||||
|
||||
void config_pdcp(configmodule_interface_t *cfg, nr_pdcp_configuration_t *pdcp_config)
|
||||
{
|
||||
/* DRB configuration */
|
||||
paramdef_t pdcp_params[] = NR_PDCP_DRB_GLOBALPARAMS_DESC;
|
||||
int ret = config_get(cfg, pdcp_params, sizeofArray(pdcp_params), CONFIG_STRING_NR_PDCP_DRB);
|
||||
AssertFatal(ret >= 0, "problem reading NR PDCP configuration from configuration file\n");
|
||||
|
||||
pdcp_config->drb.sn_size = config_get_processedint(cfg, &pdcp_params[CONFIG_NR_PDCP_DRB_SN_SIZE_IDX]);
|
||||
pdcp_config->drb.t_reordering = config_get_processedint(cfg, &pdcp_params[CONFIG_NR_PDCP_DRB_T_REORDERING_IDX]);
|
||||
pdcp_config->drb.discard_timer = config_get_processedint(cfg, &pdcp_params[CONFIG_NR_PDCP_DRB_DISCARD_TIMER_IDX]);
|
||||
}
|
||||
|
||||
void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
{
|
||||
int j = 0;
|
||||
@@ -1566,19 +1622,6 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
config.timer_config.n311,
|
||||
config.timer_config.t319);
|
||||
|
||||
if (config_isparamset(GNBParamList.paramarray[0], GNB_BEAMWEIGHTS_IDX)) {
|
||||
int n = GNBParamList.paramarray[0][GNB_BEAMWEIGHTS_IDX].numelt;
|
||||
AssertFatal(n % num_tx == 0, "Error! Number of beam input needs to be multiple of TX antennas\n");
|
||||
// each beam is described by a set of weights (one for each antenna)
|
||||
// on the other hand in case of analog beamforming an index to the RU beam identifier is provided
|
||||
config.nb_bfw[0] = num_tx; // number of tx antennas
|
||||
config.nb_bfw[1] = n / num_tx; // number of beams
|
||||
config.bw_list = malloc16_clear(n * sizeof(*config.bw_list));
|
||||
for (int b = 0; b < n; b++) {
|
||||
config.bw_list[b] = GNBParamList.paramarray[0][GNB_BEAMWEIGHTS_IDX].iptr[b];
|
||||
}
|
||||
}
|
||||
|
||||
// Construct default aggragation level list or read from config
|
||||
int uess_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS];
|
||||
uess_num_agg_level_candidates[PDCCH_AGG_LEVEL1] = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0;
|
||||
@@ -1612,8 +1655,12 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
NR_ServingCellConfig_t *scd = get_scd_config(cfg);
|
||||
|
||||
if (MacRLC_ParamList.numelt > 0) {
|
||||
/* NR RLC config is needed by mac_top_init_gNB() */
|
||||
nr_rlc_configuration_t default_rlc_config;
|
||||
config_rlc(cfg, &default_rlc_config);
|
||||
|
||||
ngran_node_t node_type = get_node_type();
|
||||
mac_top_init_gNB(node_type, scc, scd, &config);
|
||||
mac_top_init_gNB(node_type, scc, scd, &config, &default_rlc_config);
|
||||
RC.nb_nr_mac_CC = (int *)malloc(RC.nb_nr_macrlc_inst * sizeof(int));
|
||||
|
||||
for (j = 0; j < RC.nb_nr_macrlc_inst; j++) {
|
||||
@@ -1704,6 +1751,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
}
|
||||
bool ab = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMFORMING_IDX].u8ptr;
|
||||
if (ab) {
|
||||
AssertFatal(NFAPI_MODE == NFAPI_MONOLITHIC, "Analog beamforming only supported for monolithic scenario\n");
|
||||
NR_beam_info_t *beam_info = &RC.nrmac[j]->beam_info;
|
||||
int beams_per_period = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMS_PERIOD_IDX].u8ptr;
|
||||
beam_info->beam_allocation = malloc16(beams_per_period * sizeof(int *));
|
||||
@@ -1711,6 +1759,26 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
beam_info->beams_per_period = beams_per_period;
|
||||
beam_info->beam_allocation_size = -1; // to be initialized once we have information on frame configuration
|
||||
}
|
||||
if (config_isparamset(MacRLC_ParamList.paramarray[j], MACRLC_BEAMWEIGHTS_IDX)) {
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC) {
|
||||
GET_PARAMS_LIST(L1_ParamList, L1_Params, L1PARAMS_DESC, CONFIG_STRING_L1_LIST, NULL);
|
||||
AssertFatal(*(L1_ParamList.paramarray[j][L1_ANALOG_DAS].uptr) == 0, "No need to set beam weights in case of DAS\n");
|
||||
}
|
||||
int n = MacRLC_ParamList.paramarray[j][MACRLC_BEAMWEIGHTS_IDX].numelt;
|
||||
int num_beam = n;
|
||||
if (!ab) {
|
||||
AssertFatal(n % num_tx == 0, "Error! Number of beam input needs to be multiple of TX antennas\n");
|
||||
num_beam = n / num_tx;
|
||||
}
|
||||
// each beam is described by a set of weights (one for each antenna)
|
||||
// in case of analog beamforming an index to the RU beam identifier is provided
|
||||
// (one for each beam regardless of the number of antennas per beam)
|
||||
config.nb_bfw[0] = num_tx; // number of tx antennas
|
||||
config.nb_bfw[1] = num_beam; // number of beams weights/indices
|
||||
config.bw_list = calloc_or_fail(n, sizeof(*config.bw_list));
|
||||
for (int b = 0; b < n; b++)
|
||||
config.bw_list[b] = MacRLC_ParamList.paramarray[j][MACRLC_BEAMWEIGHTS_IDX].iptr[b];
|
||||
}
|
||||
// triggers also PHY initialization in case we have L1 via FAPI
|
||||
nr_mac_config_scc(RC.nrmac[j], scc, &config);
|
||||
} // for (j=0;j<RC.nb_nr_macrlc_inst;j++)
|
||||
@@ -1919,9 +1987,8 @@ static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc
|
||||
seq_arr_init(rrc->neighbour_cell_configuration, sizeof(neighbour_cell_configuration_t));
|
||||
|
||||
for (int elm = 0; elm < neighbour_list_param_list.numelt; ++elm) {
|
||||
neighbour_cell_configuration_t *cell = calloc(1, sizeof(neighbour_cell_configuration_t));
|
||||
AssertFatal(cell != NULL, "out of memory\n");
|
||||
cell->nr_cell_id = (uint64_t)*neighbour_list_param_list.paramarray[elm][0].u64ptr;
|
||||
neighbour_cell_configuration_t cell = {0};
|
||||
cell.nr_cell_id = (uint64_t)*neighbour_list_param_list.paramarray[elm][0].u64ptr;
|
||||
|
||||
char neighbourpath[MAX_OPTNAME_SIZE + 8];
|
||||
snprintf(neighbourpath, sizeof(neighbourpath), "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx, GNB_CONFIG_STRING_NEIGHBOUR_LIST, elm);
|
||||
@@ -1930,22 +1997,20 @@ static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc
|
||||
GNBNEIGHBOURCELLPARAMS_DESC,
|
||||
GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST,
|
||||
neighbourpath);
|
||||
LOG_D(GNB_APP, "HO LOG: For the Cell: %ld Neighbour Cell ELM NUM: %d\n", cell->nr_cell_id, NeighbourCellParamList.numelt);
|
||||
LOG_D(GNB_APP, "HO LOG: For the Cell: %ld Neighbour Cell ELM NUM: %d\n", cell.nr_cell_id, NeighbourCellParamList.numelt);
|
||||
if (NeighbourCellParamList.numelt < 1)
|
||||
continue;
|
||||
|
||||
cell->neighbour_cells = malloc(sizeof(seq_arr_t));
|
||||
AssertFatal(cell->neighbour_cells != NULL, "Memory exhausted!!!");
|
||||
seq_arr_init(cell->neighbour_cells, sizeof(nr_neighbour_gnb_configuration_t));
|
||||
cell.neighbour_cells = malloc_or_fail(sizeof(seq_arr_t));
|
||||
seq_arr_init(cell.neighbour_cells, sizeof(nr_neighbour_cell_t));
|
||||
for (int l = 0; l < NeighbourCellParamList.numelt; ++l) {
|
||||
nr_neighbour_gnb_configuration_t *neighbourCell = calloc(1, sizeof(nr_neighbour_gnb_configuration_t));
|
||||
AssertFatal(neighbourCell != NULL, "out of memory\n");
|
||||
neighbourCell->gNB_ID = *(NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_GNB_ID_IDX].uptr);
|
||||
neighbourCell->nrcell_id = (uint64_t) * (NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr);
|
||||
neighbourCell->physicalCellId = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX].uptr;
|
||||
neighbourCell->subcarrierSpacing = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_SCS_IDX].uptr;
|
||||
neighbourCell->absoluteFrequencySSB = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX].i64ptr;
|
||||
neighbourCell->tac = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_TAC_IDX].uptr;
|
||||
nr_neighbour_cell_t neighbourCell = {0};
|
||||
neighbourCell.gNB_ID = *(NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_GNB_ID_IDX].uptr);
|
||||
neighbourCell.nrcell_id = (uint64_t) * (NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr);
|
||||
neighbourCell.physicalCellId = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX].uptr;
|
||||
neighbourCell.subcarrierSpacing = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_SCS_IDX].uptr;
|
||||
neighbourCell.absoluteFrequencySSB = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX].i64ptr;
|
||||
neighbourCell.tac = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_TAC_IDX].uptr;
|
||||
|
||||
char neighbour_plmn_path[CONFIG_MAXOPTLENGTH];
|
||||
snprintf(neighbour_plmn_path,
|
||||
@@ -1957,13 +2022,12 @@ static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc
|
||||
GNB_CONFIG_STRING_NEIGHBOUR_PLMN);
|
||||
GET_PARAMS(NeighbourPlmn, GNBPLMNPARAMS_DESC, neighbour_plmn_path);
|
||||
|
||||
neighbourCell->plmn.mcc = *NeighbourPlmn[GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
|
||||
neighbourCell->plmn.mnc = *NeighbourPlmn[GNB_MOBILE_NETWORK_CODE_IDX].uptr;
|
||||
neighbourCell->plmn.mnc_digit_length = *NeighbourPlmn[GNB_MNC_DIGIT_LENGTH].uptr;
|
||||
seq_arr_push_back(cell->neighbour_cells, neighbourCell, sizeof(nr_neighbour_gnb_configuration_t));
|
||||
neighbourCell.plmn.mcc = *NeighbourPlmn[GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
|
||||
neighbourCell.plmn.mnc = *NeighbourPlmn[GNB_MOBILE_NETWORK_CODE_IDX].uptr;
|
||||
neighbourCell.plmn.mnc_digit_length = *NeighbourPlmn[GNB_MNC_DIGIT_LENGTH].uptr;
|
||||
seq_arr_push_back(cell.neighbour_cells, &neighbourCell, sizeof(neighbourCell));
|
||||
}
|
||||
|
||||
seq_arr_push_back(rrc->neighbour_cell_configuration, cell, sizeof(neighbour_cell_configuration_t));
|
||||
seq_arr_push_back(rrc->neighbour_cell_configuration, &cell, sizeof(cell));
|
||||
}
|
||||
void *base = seq_arr_front(rrc->neighbour_cell_configuration);
|
||||
size_t nmemb = seq_arr_size(rrc->neighbour_cell_configuration);
|
||||
@@ -2020,22 +2084,21 @@ static void fill_measurement_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
|
||||
measurementConfig->a3_event_list = malloc(sizeof(seq_arr_t));
|
||||
seq_arr_init(measurementConfig->a3_event_list, sizeof(nr_a3_event_t));
|
||||
for (int i = 0; i < A3_EventList.numelt; i++) {
|
||||
nr_a3_event_t *a3_event = (nr_a3_event_t *)calloc(1, sizeof(nr_a3_event_t));
|
||||
AssertFatal(a3_event != NULL, "out of memory\n");
|
||||
a3_event->pci = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_PCI_ID_IDX].i64ptr;
|
||||
AssertFatal(a3_event->pci >= -1 && a3_event->pci < 1024,
|
||||
nr_a3_event_t a3_event = {0};
|
||||
a3_event.pci = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_PCI_ID_IDX].i64ptr;
|
||||
AssertFatal(a3_event.pci >= -1 && a3_event.pci < 1024,
|
||||
"entry %s.%s must be -1<=PCI<1024, but is %d\n",
|
||||
measurement_path,
|
||||
MEASUREMENT_EVENTS_PCI_ID,
|
||||
a3_event->pci);
|
||||
a3_event->timeToTrigger = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_TIMETOTRIGGER_IDX].i64ptr;
|
||||
a3_event->a3_offset = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_OFFSET_IDX].i64ptr;
|
||||
a3_event->hysteresis = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_HYSTERESIS_IDX].i64ptr;
|
||||
a3_event.pci);
|
||||
a3_event.timeToTrigger = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_TIMETOTRIGGER_IDX].i64ptr;
|
||||
a3_event.a3_offset = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_OFFSET_IDX].i64ptr;
|
||||
a3_event.hysteresis = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_HYSTERESIS_IDX].i64ptr;
|
||||
|
||||
if (a3_event->pci == -1)
|
||||
if (a3_event.pci == -1)
|
||||
measurementConfig->is_default_a3_configuration_exists = true;
|
||||
|
||||
seq_arr_push_back(measurementConfig->a3_event_list, a3_event, sizeof(nr_a3_event_t));
|
||||
seq_arr_push_back(measurementConfig->a3_event_list, &a3_event, sizeof(nr_a3_event_t));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2147,6 +2210,9 @@ gNB_RRC_INST *RCconfig_NRRRC()
|
||||
if (!NODE_IS_DU(rrc->node_type))
|
||||
config_security(rrc);
|
||||
|
||||
config_rlc(config_get_if(), &rrc->rlc_config);
|
||||
config_pdcp(config_get_if(), &rrc->pdcp_config);
|
||||
|
||||
return rrc;
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,6 @@ typedef enum {
|
||||
#define GNB_CONFIG_STRING_GNB_CU_UP_ID "gNB_CU_UP_ID"
|
||||
#define GNB_CONFIG_STRING_NUM_DL_HARQPROCESSES "num_dlharq"
|
||||
#define GNB_CONFIG_STRING_NUM_UL_HARQPROCESSES "num_ulharq"
|
||||
#define GNB_CONFIG_STRING_BEAM_WEIGHTS_LIST "beam_weights"
|
||||
#define GNB_CONFIG_STRING_UESS_AGG_LEVEL_LIST "uess_agg_levels"
|
||||
#define GNB_CONFIG_STRING_CU_SIB_LIST "cu_sibs"
|
||||
#define GNB_CONFIG_STRING_DU_SIB_LIST "du_sibs"
|
||||
@@ -198,7 +197,6 @@ typedef enum {
|
||||
{GNB_CONFIG_STRING_DISABLE_HARQ, GNB_CONFIG_HLP_DISABLE_HARQ, PARAMFLAG_BOOL, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_NUM_DL_HARQPROCESSES, GNB_CONFIG_HLP_NUM_DL_HARQ, 0, .iptr=NULL, .defintval=16, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_NUM_UL_HARQPROCESSES, GNB_CONFIG_HLP_NUM_UL_HARQ, 0, .iptr=NULL, .defintval=16, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_BEAM_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
|
||||
{GNB_CONFIG_STRING_UESS_AGG_LEVEL_LIST, \
|
||||
GNB_CONFIG_HLP_UESS_AGG_LEVEL_LIST, 0, .iptr=NULL, .defintarrayval=NULL, TYPE_INTARRAY, 0}, \
|
||||
{GNB_CONFIG_STRING_CU_SIB_LIST, GNB_CONFIG_HLP_CU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
|
||||
@@ -243,11 +241,10 @@ typedef enum {
|
||||
#define GNB_DISABLE_HARQ_IDX 32
|
||||
#define GNB_NUM_DL_HARQ_IDX 33
|
||||
#define GNB_NUM_UL_HARQ_IDX 34
|
||||
#define GNB_BEAMWEIGHTS_IDX 35
|
||||
#define GNB_UESS_AGG_LEVEL_LIST_IDX 36
|
||||
#define GNB_CU_SIBS_IDX 37
|
||||
#define GNB_DU_SIBS_IDX 38
|
||||
#define GNB_DO_SINR_IDX 39
|
||||
#define GNB_UESS_AGG_LEVEL_LIST_IDX 35
|
||||
#define GNB_CU_SIBS_IDX 36
|
||||
#define GNB_DU_SIBS_IDX 37
|
||||
#define GNB_DO_SINR_IDX 38
|
||||
|
||||
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
|
||||
#define NUM_DL_HARQ_OKVALUES {2,4,6,8,10,12,16,32}
|
||||
@@ -293,7 +290,6 @@ typedef enum {
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
@@ -680,5 +676,215 @@ typedef enum {
|
||||
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
#define CONFIG_STRING_NR_RLC_LIST "rlc"
|
||||
#define CONFIG_STRING_NR_PDCP_LIST "pdcp"
|
||||
|
||||
#define CONFIG_NR_RLC_T_POLL_RETRANSMIT "t_poll_retransmit"
|
||||
#define CONFIG_NR_RLC_T_REASSEMBLY "t_reassembly"
|
||||
#define CONFIG_NR_RLC_T_STATUS_PROHIBIT "t_status_prohibit"
|
||||
#define CONFIG_NR_RLC_POLL_PDU "poll_pdu"
|
||||
#define CONFIG_NR_RLC_POLL_BYTE "poll_byte"
|
||||
#define CONFIG_NR_RLC_MAX_RETX_THRESHOLD "max_retx_threshold"
|
||||
#define CONFIG_NR_RLC_SN_FIELD_LENGTH "sn_field_length"
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* nr rlc srb configuration */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#define CONFIG_STRING_NR_RLC_SRB "rlc.srb"
|
||||
|
||||
#define CONFIG_NR_RLC_SRB_T_POLL_RETRANSMIT_IDX 0
|
||||
#define CONFIG_NR_RLC_SRB_T_REASSEMBLY_IDX 1
|
||||
#define CONFIG_NR_RLC_SRB_T_STATUS_PROHIBIT_IDX 2
|
||||
#define CONFIG_NR_RLC_SRB_POLL_PDU_IDX 3
|
||||
#define CONFIG_NR_RLC_SRB_POLL_BYTE_IDX 4
|
||||
#define CONFIG_NR_RLC_SRB_MAX_RETX_THRESHOLD_IDX 5
|
||||
#define CONFIG_NR_RLC_SRB_SN_FIELD_LENGTH_IDX 6
|
||||
|
||||
#define NR_RLC_SRB_GLOBALPARAMS_DESC { \
|
||||
{ .optname = CONFIG_NR_RLC_T_POLL_RETRANSMIT, \
|
||||
.defstrval = "ms45", \
|
||||
.helpstr = "poll retransmit timer", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_T_POLL_RETRANSMIT_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_T_POLL_RETRANSMIT }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_T_POLL_RETRANSMIT }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_T_REASSEMBLY, \
|
||||
.defstrval = "ms35", \
|
||||
.helpstr = "reassembly timer", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_T_REASSEMBLY_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_T_REASSEMBLY }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_T_REASSEMBLY }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_T_STATUS_PROHIBIT, \
|
||||
.defstrval = "ms0", \
|
||||
.helpstr = "status prohibit timer", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_T_STATUS_PROHIBIT_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_T_STATUS_PROHIBIT }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_T_STATUS_PROHIBIT }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_POLL_PDU, \
|
||||
.defstrval = "infinity", \
|
||||
.helpstr = "pollPDU", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_POLL_PDU_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_POLL_PDU }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_POLL_PDU }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_POLL_BYTE, \
|
||||
.defstrval = "infinity", \
|
||||
.helpstr = "pollByte", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_POLL_BYTE_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_POLL_BYTE }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_POLL_BYTE }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_MAX_RETX_THRESHOLD, \
|
||||
.defstrval = "t8", \
|
||||
.helpstr = "max reTX threshold", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_MAX_RETX_THRESHOLD_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_MAX_RETX_THRESHOLD }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_MAX_RETX_THRESHOLD }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_SN_FIELD_LENGTH, \
|
||||
.defstrval = "size12", \
|
||||
.helpstr = "SN size", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_SN_FIELD_LENGTH_AM_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_SN_FIELD_LENGTH_AM }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_SN_FIELD_LENGTH_AM }}}, \
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* nr rlc drb am configuration */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#define CONFIG_STRING_NR_RLC_DRB_AM "rlc.drb_am"
|
||||
|
||||
#define CONFIG_NR_RLC_DRB_AM_T_POLL_RETRANSMIT_IDX 0
|
||||
#define CONFIG_NR_RLC_DRB_AM_T_REASSEMBLY_IDX 1
|
||||
#define CONFIG_NR_RLC_DRB_AM_T_STATUS_PROHIBIT_IDX 2
|
||||
#define CONFIG_NR_RLC_DRB_AM_POLL_PDU_IDX 3
|
||||
#define CONFIG_NR_RLC_DRB_AM_POLL_BYTE_IDX 4
|
||||
#define CONFIG_NR_RLC_DRB_AM_MAX_RETX_THRESHOLD_IDX 5
|
||||
#define CONFIG_NR_RLC_DRB_AM_SN_FIELD_LENGTH_IDX 6
|
||||
|
||||
#define NR_RLC_DRB_AM_GLOBALPARAMS_DESC { \
|
||||
{ .optname = CONFIG_NR_RLC_T_POLL_RETRANSMIT, \
|
||||
.defstrval = "ms45", \
|
||||
.helpstr = "poll retransmit timer", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_T_POLL_RETRANSMIT_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_T_POLL_RETRANSMIT }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_T_POLL_RETRANSMIT }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_T_REASSEMBLY, \
|
||||
.defstrval = "ms15", \
|
||||
.helpstr = "reassembly timer", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_T_REASSEMBLY_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_T_REASSEMBLY }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_T_REASSEMBLY }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_T_STATUS_PROHIBIT, \
|
||||
.defstrval = "ms15", \
|
||||
.helpstr = "status prohibit timer", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_T_STATUS_PROHIBIT_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_T_STATUS_PROHIBIT }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_T_STATUS_PROHIBIT }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_POLL_PDU, \
|
||||
.defstrval = "p64", \
|
||||
.helpstr = "pollPDU", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_POLL_PDU_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_POLL_PDU }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_POLL_PDU }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_POLL_BYTE, \
|
||||
.defstrval = "kB500", \
|
||||
.helpstr = "pollByte", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_POLL_BYTE_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_POLL_BYTE }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_POLL_BYTE }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_MAX_RETX_THRESHOLD, \
|
||||
.defstrval = "t32", \
|
||||
.helpstr = "max reTX threshold", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_MAX_RETX_THRESHOLD_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_MAX_RETX_THRESHOLD }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_MAX_RETX_THRESHOLD }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_SN_FIELD_LENGTH, \
|
||||
.defstrval = "size18", \
|
||||
.helpstr = "SN size", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_SN_FIELD_LENGTH_AM_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_SN_FIELD_LENGTH_AM }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_SN_FIELD_LENGTH_AM }}}, \
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* nr rlc drb um configuration */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#define CONFIG_STRING_NR_RLC_DRB_UM "rlc.drb_um"
|
||||
|
||||
#define CONFIG_NR_RLC_DRB_UM_T_REASSEMBLY_IDX 0
|
||||
#define CONFIG_NR_RLC_DRB_UM_SN_FIELD_LENGTH_IDX 1
|
||||
|
||||
#define NR_RLC_DRB_UM_GLOBALPARAMS_DESC { \
|
||||
{ .optname = CONFIG_NR_RLC_T_REASSEMBLY, \
|
||||
.defstrval = "ms15", \
|
||||
.helpstr = "reassembly timer", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_T_REASSEMBLY_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_T_REASSEMBLY }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_T_REASSEMBLY }}}, \
|
||||
{ .optname = CONFIG_NR_RLC_SN_FIELD_LENGTH, \
|
||||
.defstrval = "size12", \
|
||||
.helpstr = "SN size", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_RLC_SN_FIELD_LENGTH_UM_STR }, \
|
||||
.setintval = { VALUES_NR_RLC_SN_FIELD_LENGTH_UM }, \
|
||||
.num_okstrval = SIZEOF_NR_RLC_SN_FIELD_LENGTH_UM }}}, \
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#define CONFIG_NR_PDCP_SN_SIZE "sn_size"
|
||||
#define CONFIG_NR_PDCP_T_REORDERING "t_reordering"
|
||||
#define CONFIG_NR_PDCP_DISCARD_TIMER "discard_timer"
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* nr pdcp drb configuration */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#define CONFIG_STRING_NR_PDCP_DRB "pdcp.drb"
|
||||
|
||||
#define CONFIG_NR_PDCP_DRB_SN_SIZE_IDX 0
|
||||
#define CONFIG_NR_PDCP_DRB_T_REORDERING_IDX 1
|
||||
#define CONFIG_NR_PDCP_DRB_DISCARD_TIMER_IDX 2
|
||||
|
||||
#define NR_PDCP_DRB_GLOBALPARAMS_DESC { \
|
||||
{ .optname = CONFIG_NR_PDCP_SN_SIZE, \
|
||||
.defstrval = "len18bits", \
|
||||
.helpstr = "SN size", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_PDCP_SN_SIZE_STR }, \
|
||||
.setintval = { VALUES_NR_PDCP_SN_SIZE }, \
|
||||
.num_okstrval = SIZEOF_NR_PDCP_SN_SIZE }}}, \
|
||||
{ .optname = CONFIG_NR_PDCP_T_REORDERING, \
|
||||
.defstrval = "ms100", \
|
||||
.helpstr = "reordering timer", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_PDCP_T_REORDERING_STR }, \
|
||||
.setintval = { VALUES_NR_PDCP_T_REORDERING }, \
|
||||
.num_okstrval = SIZEOF_NR_PDCP_T_REORDERING }}}, \
|
||||
{ .optname = CONFIG_NR_PDCP_DISCARD_TIMER, \
|
||||
.defstrval = "infinity", \
|
||||
.helpstr = "discard timer", .paramflags = 0, .strptr = NULL, .type = TYPE_STRING, .numelt = 0, \
|
||||
.chkPptr = &(checkedparam_t){ .s3a = { .f3a = config_checkstr_assign_integer, \
|
||||
.okstrval = { VALUES_NR_PDCP_DISCARD_TIMER_STR }, \
|
||||
.setintval = { VALUES_NR_PDCP_DISCARD_TIMER }, \
|
||||
.num_okstrval = SIZEOF_NR_PDCP_DISCARD_TIMER }}} \
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2703,6 +2703,10 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
|
||||
mac->lc_ordered_list.count);
|
||||
|
||||
// variable used to build the lcids with positive Bj
|
||||
if (!mac->lc_ordered_list.count) {
|
||||
LOG_E(NR_MAC, "Failed to init lcids_bj_pos: mac->lc_ordered_list.count = 0\n");
|
||||
return 0;
|
||||
}
|
||||
nr_lcordered_info_t lcids_bj_pos[mac->lc_ordered_list.count];
|
||||
int avail_lcids_count = select_logical_channels(mac, lcids_bj_pos);
|
||||
|
||||
|
||||
@@ -715,36 +715,32 @@ static void config_common(gNB_MAC_INST *nrmac,
|
||||
if (cfg->cell_config.frame_duplex_type.value == TDD)
|
||||
set_tdd_config_nr(cfg, fs);
|
||||
|
||||
int nb_tx = config->nb_bfw[0]; // number of tx antennas
|
||||
int nb_beams = config->nb_bfw[1]; // number of beams
|
||||
// precoding matrix configuration (to be improved)
|
||||
cfg->pmi_list = init_DL_MIMO_codebook(nrmac, pdsch_AntennaPorts);
|
||||
// beamforming matrix configuration
|
||||
cfg->dbt_config.num_dig_beams = nb_beams;
|
||||
if (nb_beams > 0) {
|
||||
cfg->dbt_config.num_txrus = nb_tx;
|
||||
cfg->dbt_config.dig_beam_list = malloc16(nb_beams * sizeof(*cfg->dbt_config.dig_beam_list));
|
||||
AssertFatal(cfg->dbt_config.dig_beam_list, "out of memory\n");
|
||||
for (int i = 0; i < nb_beams; i++) {
|
||||
nfapi_nr_dig_beam_t *beam = &cfg->dbt_config.dig_beam_list[i];
|
||||
beam->beam_idx = i;
|
||||
beam->txru_list = malloc16(nb_tx * sizeof(*beam->txru_list));
|
||||
for (int j = 0; j < nb_tx; j++) {
|
||||
nfapi_nr_txru_t *txru = &beam->txru_list[j];
|
||||
txru->dig_beam_weight_Re = config->bw_list[j + i * nb_tx] & 0xffff;
|
||||
txru->dig_beam_weight_Im = (config->bw_list[j + i * nb_tx] >> 16) & 0xffff;
|
||||
LOG_D(NR_MAC, "Beam %d Tx %d Weight (%d, %d)\n", i, j, txru->dig_beam_weight_Re, txru->dig_beam_weight_Im);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nb_beams = config->nb_bfw[1]; // number of beams
|
||||
if (nrmac->beam_info.beam_allocation) {
|
||||
LOG_I(NR_MAC, "Configuring analog beamforming in config_request message\n");
|
||||
cfg->analog_beamforming_ve.num_beams_period_vendor_ext.tl.tag = NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG;
|
||||
cfg->analog_beamforming_ve.num_beams_period_vendor_ext.value = nrmac->beam_info.beams_per_period;
|
||||
cfg->num_tlv++;
|
||||
cfg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag = NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG;
|
||||
cfg->analog_beamforming_ve.analog_bf_vendor_ext.value = 1; // analog BF enabled
|
||||
cfg->num_tlv++;
|
||||
cfg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag = NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
|
||||
cfg->analog_beamforming_ve.total_num_beams_vendor_ext.value = nb_beams;
|
||||
cfg->num_tlv++;
|
||||
cfg->analog_beamforming_ve.analog_beam_list = malloc16(nb_beams * sizeof(*cfg->analog_beamforming_ve.analog_beam_list));
|
||||
for (int i = 0; i < nb_beams; i++) {
|
||||
cfg->analog_beamforming_ve.analog_beam_list[i].tl.tag = NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG;
|
||||
cfg->analog_beamforming_ve.analog_beam_list[i].value = config->bw_list[i];
|
||||
}
|
||||
} else {
|
||||
cfg->analog_beamforming_ve.analog_bf_vendor_ext.value = 0; // analog BF disabled
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC) {
|
||||
cfg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag = NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG;
|
||||
cfg->num_tlv++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -356,10 +356,11 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
|
||||
NR_COMMON_channels_t *cc = gNB->common_channels;
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
|
||||
NR_BWP_UplinkCommon_t *initialUplinkBWP = scc->uplinkConfigCommon->initialUplinkBWP;
|
||||
NR_RACH_ConfigCommon_t *rach_ConfigCommon = initialUplinkBWP->rach_ConfigCommon->choice.setup;
|
||||
NR_MsgA_ConfigCommon_r16_t *msgacc = NULL;
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16)
|
||||
msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup;
|
||||
if (initialUplinkBWP->ext1 && initialUplinkBWP->ext1->msgA_ConfigCommon_r16)
|
||||
msgacc = initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup;
|
||||
int slots_frame = gNB->frame_structure.numb_slots_frame;
|
||||
int index = ul_buffer_index(frameP, slotP, slots_frame, gNB->UL_tti_req_ahead_size);
|
||||
nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][index];
|
||||
@@ -371,7 +372,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
int slot_index = 0;
|
||||
uint16_t prach_occasion_id = -1;
|
||||
|
||||
int bwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
int bwp_start = NRRIV2PRBOFFSET(initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
|
||||
uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
|
||||
const int ul_mu = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
@@ -399,6 +400,16 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
uint32_t N_t_slot = cc->prach_info.N_t_slot;
|
||||
uint32_t start_symb = cc->prach_info.start_symbol;
|
||||
for (int fdm_index = 0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion
|
||||
AssertFatal(UL_tti_req->n_pdus < sizeof(UL_tti_req->pdus_list) / sizeof(UL_tti_req->pdus_list[0]),
|
||||
"Invalid UL_tti_req->n_pdus %d\n",
|
||||
UL_tti_req->n_pdus);
|
||||
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE;
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t);
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu;
|
||||
memset(prach_pdu, 0, sizeof(nfapi_nr_prach_pdu_t));
|
||||
UL_tti_req->n_pdus += 1;
|
||||
int num_td_occ = 0;
|
||||
for (int td_index = 0; td_index < N_t_slot; td_index++) {
|
||||
uint32_t config_period = cc->prach_info.x;
|
||||
prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) +
|
||||
@@ -407,6 +418,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
if (prach_occasion_id >= cc->total_prach_occasions) // to be confirmed: unused occasion?
|
||||
continue;
|
||||
|
||||
num_td_occ++;
|
||||
float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];
|
||||
int beam_index = 0;
|
||||
if(num_ssb_per_RO <= 1) {
|
||||
@@ -417,8 +429,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
// multi-beam allocation structure
|
||||
beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, slots_frame);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate PRACH corresponding to %d SSB transmitted in any available beam\n", n_ssb + 1);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
int first_ssb_index = (prach_occasion_id * (int)num_ssb_per_RO) % cc->num_active_ssb;
|
||||
for(int j = first_ssb_index; j < first_ssb_index + num_ssb_per_RO; j++) {
|
||||
// fapi beam index
|
||||
@@ -428,40 +439,15 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate PRACH corresponding to SSB %d in any available beam\n", j);
|
||||
}
|
||||
}
|
||||
if(td_index == 0) {
|
||||
AssertFatal(UL_tti_req->n_pdus < sizeof(UL_tti_req->pdus_list) / sizeof(UL_tti_req->pdus_list[0]),
|
||||
"Invalid UL_tti_req->n_pdus %d\n", UL_tti_req->n_pdus);
|
||||
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE;
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t);
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu;
|
||||
memset(prach_pdu,0,sizeof(nfapi_nr_prach_pdu_t));
|
||||
UL_tti_req->n_pdus+=1;
|
||||
|
||||
if(num_td_occ == 1) {
|
||||
// filling the prach fapi structure
|
||||
prach_pdu->phys_cell_id = *scc->physCellId;
|
||||
prach_pdu->num_prach_ocas = N_t_slot;
|
||||
gNB->num_scheduled_prach_rx += N_t_slot;
|
||||
prach_pdu->prach_start_symbol = start_symb;
|
||||
prach_pdu->num_ra = fdm_index;
|
||||
prach_pdu->num_cs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig,
|
||||
format0,
|
||||
rach_ConfigCommon->restrictedSetConfig);
|
||||
|
||||
prach_pdu->beamforming.num_prgs = 0;
|
||||
prach_pdu->beamforming.prg_size = 0;
|
||||
prach_pdu->beamforming.dig_bf_interface = 1;
|
||||
prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n",
|
||||
frameP,
|
||||
slotP,
|
||||
prach_occasion_id,
|
||||
prach_pdu->num_ra,
|
||||
start_symb,
|
||||
slot_index,
|
||||
RA_sfn_index);
|
||||
// SCF PRACH PDU format field does not consider A1/B1 etc. possibilities
|
||||
// We added 9 = A1/B1 10 = A2/B2 11 A3/B3
|
||||
if (format1!=0xff) {
|
||||
@@ -518,8 +504,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
AssertFatal(1==0,"Invalid PRACH format");
|
||||
}
|
||||
}
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->ext1
|
||||
&& scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) {
|
||||
if (initialUplinkBWP->ext1 && initialUplinkBWP->ext1->msgA_ConfigCommon_r16) {
|
||||
if (gNB->UE_info.connected_ue_list[0] == NULL)
|
||||
schedule_nr_MsgA_pusch(scc->uplinkConfigCommon,
|
||||
gNB,
|
||||
@@ -531,7 +516,26 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
*scc->physCellId);
|
||||
}
|
||||
}
|
||||
prach_pdu->num_prach_ocas = num_td_occ;
|
||||
prach_pdu->beamforming.num_prgs = 0;
|
||||
prach_pdu->beamforming.prg_size = 0;
|
||||
prach_pdu->beamforming.dig_bf_interface = num_td_occ;
|
||||
prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[num_td_occ - 1].beam_idx = beam_index;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n",
|
||||
frameP,
|
||||
slotP,
|
||||
prach_occasion_id,
|
||||
prach_pdu->num_ra,
|
||||
prach_pdu->prach_start_symbol,
|
||||
slot_index,
|
||||
RA_sfn_index);
|
||||
}
|
||||
if (num_td_occ == 0) // no TD PRACH occasion -> no PRACH PDU
|
||||
UL_tti_req->n_pdus -= 1;
|
||||
else
|
||||
gNB->num_scheduled_prach_rx += num_td_occ;
|
||||
}
|
||||
|
||||
// block resources in vrb_map_UL
|
||||
|
||||
@@ -335,6 +335,9 @@ static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, slot_t s
|
||||
const int lcid = c->lcid;
|
||||
const uint16_t rnti = UE->rnti;
|
||||
LOG_D(NR_MAC, "In %s: UE %x: LCID %d\n", __FUNCTION__, rnti, lcid);
|
||||
memset(&sched_ctrl->rlc_status[lcid], 0, sizeof(sched_ctrl->rlc_status[lcid]));
|
||||
if (c->suspended)
|
||||
continue;
|
||||
if (lcid == DL_SCH_LCID_DTCH && nr_timer_is_active(&sched_ctrl->transm_interrupt))
|
||||
continue;
|
||||
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
|
||||
@@ -399,8 +402,7 @@ static bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *U
|
||||
// used if CORESET 0 is configured for the cell and the size of initial DL bandwidth part shall be used if CORESET 0 is not
|
||||
// configured for the cell.
|
||||
if (dl_bwp->dci_format == NR_DL_DCI_FORMAT_1_0 && sched_ctrl->search_space->searchSpaceType
|
||||
&& sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common
|
||||
&& dl_bwp->pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1) {
|
||||
&& sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common) {
|
||||
if (sched_ctrl->coreset->controlResourceSetId == 0) {
|
||||
bwp_info.bwpStart = nr_mac->cset0_bwp_start;
|
||||
} else {
|
||||
@@ -1183,8 +1185,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
// 3GPP TS 38.214 Section 5.1.2.2.2 Downlink resource allocation type 1
|
||||
uint16_t riv_bwp_size = pdsch_pdu->BWPSize;
|
||||
if (current_BWP->dci_format == NR_DL_DCI_FORMAT_1_0
|
||||
&& sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common
|
||||
&& pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1) {
|
||||
&& sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common) {
|
||||
if (gNB_mac->cset0_bwp_size > 0) {
|
||||
riv_bwp_size = gNB_mac->cset0_bwp_size;
|
||||
} else {
|
||||
|
||||
@@ -2104,6 +2104,7 @@ NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP)
|
||||
void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia)
|
||||
{
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SpCellConfig, UE->reconfigSpCellConfig);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability);
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
seq_arr_free(&sched_ctrl->lc_config, NULL);
|
||||
@@ -3326,7 +3327,7 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
|
||||
int srb_id = 1;
|
||||
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
|
||||
const NR_ServingCellConfig_t *sccd = UE->is_redcap ? NULL : mac->common_channels[CC_id].pre_ServingCellConfig;
|
||||
NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config);
|
||||
NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config, &mac->rlc_config);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
UE->CellGroup = cellGroupConfig;
|
||||
|
||||
@@ -3477,6 +3478,16 @@ static int cmp_lc_config(const void *va, const void *vb)
|
||||
return 1;
|
||||
}
|
||||
|
||||
nr_lc_config_t *nr_mac_get_lc_config(NR_UE_sched_ctrl_t* sched_ctrl, int lcid)
|
||||
{
|
||||
nr_lc_config_t c = {.lcid = lcid};
|
||||
elm_arr_t elm = find_if(&sched_ctrl->lc_config, &c, eq_lcid_config);
|
||||
if (elm.found)
|
||||
return elm.it;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool nr_mac_add_lcid(NR_UE_sched_ctrl_t* sched_ctrl, const nr_lc_config_t *c)
|
||||
{
|
||||
elm_arr_t elm = find_if(&sched_ctrl->lc_config, (void *) c, eq_lcid_config);
|
||||
|
||||
@@ -78,8 +78,7 @@ static bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE)
|
||||
// case when DCI format 0_0 is decoded in any common search space in which case the size of the initial UL bandwidth part shall
|
||||
// be used.
|
||||
if (ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_0 && sched_ctrl->search_space->searchSpaceType
|
||||
&& sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common
|
||||
&& ul_bwp->pusch_Config->resourceAllocation == NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) {
|
||||
&& sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common) {
|
||||
bwp_info.bwpSize = min(ul_bwp->BWPSize, UE->sc_info.initial_ul_BWPSize);
|
||||
} else {
|
||||
bwp_info.bwpSize = ul_bwp->BWPSize;
|
||||
@@ -391,10 +390,15 @@ static int nr_process_mac_pdu(instance_t module_idP,
|
||||
slot,
|
||||
lcid);
|
||||
|
||||
nr_mac_rlc_data_ind(module_idP, UE->rnti, true, lcid, (char *)(pduP + mac_subheader_len), mac_len);
|
||||
const nr_lc_config_t *srbc = nr_mac_get_lc_config(sched_ctrl, lcid);
|
||||
if (!srbc || srbc->suspended) {
|
||||
LOG_I(NR_MAC, "RNTI %04x LCID %d: ignoring %d bytes\n", UE->rnti, lcid, mac_len);
|
||||
} else {
|
||||
nr_mac_rlc_data_ind(module_idP, UE->rnti, true, lcid, (char *)(pduP + mac_subheader_len), mac_len);
|
||||
|
||||
UE->mac_stats.ul.total_sdu_bytes += mac_len;
|
||||
UE->mac_stats.ul.lc_bytes[lcid] += mac_len;
|
||||
UE->mac_stats.ul.total_sdu_bytes += mac_len;
|
||||
UE->mac_stats.ul.lc_bytes[lcid] += mac_len;
|
||||
}
|
||||
break;
|
||||
|
||||
case UL_SCH_LCID_DTCH ...(UL_SCH_LCID_DTCH + 28):
|
||||
@@ -407,16 +411,21 @@ static int nr_process_mac_pdu(instance_t module_idP,
|
||||
lcid,
|
||||
module_idP,
|
||||
mac_len);
|
||||
UE->mac_stats.ul.lc_bytes[lcid] += mac_len;
|
||||
const nr_lc_config_t *c = nr_mac_get_lc_config(sched_ctrl, lcid);
|
||||
if (!c || c->suspended) {
|
||||
LOG_I(NR_MAC, "RNTI %04x LCID %d: ignoring %d bytes\n", UE->rnti, lcid, mac_len);
|
||||
} else {
|
||||
UE->mac_stats.ul.lc_bytes[lcid] += mac_len;
|
||||
|
||||
nr_mac_rlc_data_ind(module_idP, UE->rnti, true, lcid, (char *)(pduP + mac_subheader_len), mac_len);
|
||||
nr_mac_rlc_data_ind(module_idP, UE->rnti, true, lcid, (char *)(pduP + mac_subheader_len), mac_len);
|
||||
|
||||
sdus += 1;
|
||||
/* Updated estimated buffer when receiving data */
|
||||
if (sched_ctrl->estimated_ul_buffer >= mac_len)
|
||||
sched_ctrl->estimated_ul_buffer -= mac_len;
|
||||
else
|
||||
sched_ctrl->estimated_ul_buffer = 0;
|
||||
sdus += 1;
|
||||
/* Updated estimated buffer when receiving data */
|
||||
if (sched_ctrl->estimated_ul_buffer >= mac_len)
|
||||
sched_ctrl->estimated_ul_buffer -= mac_len;
|
||||
else
|
||||
sched_ctrl->estimated_ul_buffer = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY:
|
||||
@@ -1442,13 +1451,13 @@ void handle_nr_srs_measurements(const module_id_t module_id,
|
||||
LOG_I(NR_MAC, "nr_srs_bf_report.num_symbols = %i\n", nr_srs_bf_report.num_symbols);
|
||||
LOG_I(NR_MAC, "nr_srs_bf_report.wide_band_snr = %i (%i dB)\n", nr_srs_bf_report.wide_band_snr, wide_band_snr_dB);
|
||||
LOG_I(NR_MAC, "nr_srs_bf_report.num_reported_symbols = %i\n", nr_srs_bf_report.num_reported_symbols);
|
||||
LOG_I(NR_MAC, "nr_srs_bf_report.prgs[0].num_prgs = %i\n", nr_srs_bf_report.prgs[0].num_prgs);
|
||||
for (int prg_idx = 0; prg_idx < nr_srs_bf_report.prgs[0].num_prgs; prg_idx++) {
|
||||
LOG_I(NR_MAC, "nr_srs_bf_report.reported_symbol_list[0].num_prgs = %i\n", nr_srs_bf_report.reported_symbol_list[0].num_prgs);
|
||||
for (int prg_idx = 0; prg_idx < nr_srs_bf_report.reported_symbol_list[0].num_prgs; prg_idx++) {
|
||||
LOG_I(NR_MAC,
|
||||
"nr_srs_bf_report.prgs[0].prg_list[%3i].rb_snr = %i (%i dB)\n",
|
||||
"nr_srs_bf_report.reported_symbol_list[0].prg_list[%3i].rb_snr = %i (%i dB)\n",
|
||||
prg_idx,
|
||||
nr_srs_bf_report.prgs[0].prg_list[prg_idx].rb_snr,
|
||||
(nr_srs_bf_report.prgs[0].prg_list[prg_idx].rb_snr >> 1) - 64);
|
||||
nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr,
|
||||
(nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr >> 1) - 64);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "NR_TAG-Id.h"
|
||||
#include "common/ngran_types.h"
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h"
|
||||
|
||||
void set_cset_offset(uint16_t);
|
||||
void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers);
|
||||
@@ -52,7 +53,8 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca
|
||||
void mac_top_init_gNB(ngran_node_t node_type,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
NR_ServingCellConfig_t *scd,
|
||||
const nr_mac_config_t *conf);
|
||||
const nr_mac_config_t *conf,
|
||||
const nr_rlc_configuration_t *default_rlc_config);
|
||||
void mac_top_destroy_gNB(gNB_MAC_INST *mac);
|
||||
void nr_mac_send_f1_setup_req(void);
|
||||
|
||||
@@ -451,6 +453,7 @@ void process_addmod_bearers_cellGroupConfig(NR_UE_sched_ctrl_t *sched_ctrl,
|
||||
const struct NR_CellGroupConfig__rlc_BearerToAddModList *addmod);
|
||||
|
||||
bool nr_mac_add_lcid(NR_UE_sched_ctrl_t *sched_ctrl, const nr_lc_config_t *c);
|
||||
nr_lc_config_t *nr_mac_get_lc_config(NR_UE_sched_ctrl_t* sched_ctrl, int lcid);
|
||||
bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid);
|
||||
|
||||
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, rnti_t *rnti);
|
||||
|
||||
@@ -221,19 +221,21 @@ void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_upd
|
||||
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)
|
||||
static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_setup_t *srb,
|
||||
const nr_rlc_configuration_t *rlc_config)
|
||||
{
|
||||
long priority = srb->srb_id == 2 ? 3 : 1; // see 38.331 sec 9.2.1
|
||||
e_NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration bucket =
|
||||
NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms5;
|
||||
return get_SRB_RLC_BearerConfig(get_lcid_from_srbid(srb->srb_id), priority, bucket);
|
||||
return get_SRB_RLC_BearerConfig(get_lcid_from_srbid(srb->srb_id), priority, bucket, rlc_config);
|
||||
}
|
||||
|
||||
static int handle_ue_context_srbs_setup(NR_UE_info_t *UE,
|
||||
int srbs_len,
|
||||
const f1ap_srb_to_be_setup_t *req_srbs,
|
||||
f1ap_srb_to_be_setup_t **resp_srbs,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
NR_CellGroupConfig_t *cellGroupConfig,
|
||||
const nr_rlc_configuration_t *rlc_config)
|
||||
{
|
||||
DevAssert(req_srbs != NULL && resp_srbs != NULL && cellGroupConfig != NULL);
|
||||
|
||||
@@ -241,7 +243,7 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE,
|
||||
AssertFatal(*resp_srbs != NULL, "out of memory\n");
|
||||
for (int i = 0; i < srbs_len; i++) {
|
||||
const f1ap_srb_to_be_setup_t *srb = &req_srbs[i];
|
||||
NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb);
|
||||
NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb, rlc_config);
|
||||
nr_rlc_add_srb(UE->rnti, srb->srb_id, rlc_BearerConfig);
|
||||
|
||||
int priority = rlc_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority;
|
||||
@@ -265,11 +267,12 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE,
|
||||
return srbs_len;
|
||||
}
|
||||
|
||||
static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb)
|
||||
static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb,
|
||||
const nr_rlc_configuration_t *rlc_config)
|
||||
{
|
||||
const NR_RLC_Config_PR rlc_conf = drb->rlc_mode == F1AP_RLC_MODE_AM ? NR_RLC_Config_PR_am : NR_RLC_Config_PR_um_Bi_Directional;
|
||||
long priority = 13; // hardcoded for the moment
|
||||
return get_DRB_RLC_BearerConfig(get_lcid_from_drbid(drb->drb_id), drb->drb_id, rlc_conf, priority);
|
||||
return get_DRB_RLC_BearerConfig(get_lcid_from_drbid(drb->drb_id), drb->drb_id, rlc_conf, priority, rlc_config);
|
||||
}
|
||||
|
||||
static int get_non_dynamic_priority(int fiveqi)
|
||||
@@ -304,7 +307,8 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE,
|
||||
int drbs_len,
|
||||
const f1ap_drb_to_be_setup_t *req_drbs,
|
||||
f1ap_drb_to_be_setup_t **resp_drbs,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
NR_CellGroupConfig_t *cellGroupConfig,
|
||||
const nr_rlc_configuration_t *rlc_config)
|
||||
{
|
||||
DevAssert(req_drbs != NULL && resp_drbs != NULL && cellGroupConfig != NULL);
|
||||
instance_t f1inst = get_f1_gtp_instance();
|
||||
@@ -316,7 +320,7 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE,
|
||||
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_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb, rlc_config);
|
||||
nr_rlc_add_drb(UE->rnti, drb->drb_id, rlc_BearerConfig);
|
||||
|
||||
nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nssai};
|
||||
@@ -557,7 +561,7 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
|
||||
const NR_ServingCellConfig_t *sccd = cc->pre_ServingCellConfig;
|
||||
const nr_mac_config_t *configuration = &mac->radio_config;
|
||||
if (is_SA) {
|
||||
cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config);
|
||||
cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config, &mac->rlc_config);
|
||||
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc);
|
||||
} else {
|
||||
NR_UE_NR_Capability_t *cap = get_ue_nr_cap_from_cg_config_info(cgci);
|
||||
@@ -649,7 +653,8 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
req->srbs_to_be_setup_length,
|
||||
req->srbs_to_be_setup,
|
||||
&resp.srbs_to_be_setup,
|
||||
new_CellGroup);
|
||||
new_CellGroup,
|
||||
&mac->rlc_config);
|
||||
}
|
||||
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
@@ -657,7 +662,8 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
req->drbs_to_be_setup_length,
|
||||
req->drbs_to_be_setup,
|
||||
&resp.drbs_to_be_setup,
|
||||
new_CellGroup);
|
||||
new_CellGroup,
|
||||
&mac->rlc_config);
|
||||
}
|
||||
|
||||
if (req->rrc_container != NULL) {
|
||||
@@ -747,7 +753,8 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
req->srbs_to_be_setup_length,
|
||||
req->srbs_to_be_setup,
|
||||
&resp.srbs_to_be_setup,
|
||||
new_CellGroup);
|
||||
new_CellGroup,
|
||||
&mac->rlc_config);
|
||||
}
|
||||
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
@@ -755,7 +762,8 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
req->drbs_to_be_setup_length,
|
||||
req->drbs_to_be_setup,
|
||||
&resp.drbs_to_be_setup,
|
||||
new_CellGroup);
|
||||
new_CellGroup,
|
||||
&mac->rlc_config);
|
||||
}
|
||||
|
||||
if (req->drbs_to_be_released_length > 0) {
|
||||
@@ -774,6 +782,17 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
"RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n");
|
||||
} else if (req->ReconfigComplOutcome == RRCreconf_success) {
|
||||
LOG_I(NR_MAC, "DU received confirmation of successful RRC Reconfiguration\n");
|
||||
if (UE->reconfigSpCellConfig) {
|
||||
// in case of reestablishment, the spCellConfig had to be released
|
||||
// temporarily. Reapply now before doing the reconfiguration.
|
||||
UE->CellGroup->spCellConfig = UE->reconfigSpCellConfig;
|
||||
UE->reconfigSpCellConfig = NULL;
|
||||
for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) {
|
||||
nr_lc_config_t *c = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i);
|
||||
c->suspended = false;
|
||||
nr_rlc_reestablish_entity(req->gNB_DU_ue_id, c->lcid);
|
||||
}
|
||||
}
|
||||
// we re-configure the BWP to apply the CellGroup and to use UE specific Search Space with DCIX1
|
||||
nr_mac_clean_cellgroup(UE->CellGroup);
|
||||
configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_ue_Specific, -1, -1);
|
||||
@@ -941,15 +960,9 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
|
||||
DevAssert(success);
|
||||
}
|
||||
|
||||
if (UE->reestablish_rlc && dl_rrc->srb_id == 1) {
|
||||
// we expected a reconfiguration to re-establish RLC, and this is on DCCH. We assume this is the reconfiguration.
|
||||
for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) {
|
||||
nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i);
|
||||
nr_rlc_reestablish_entity(dl_rrc->gNB_DU_ue_id, lc_config->lcid);
|
||||
}
|
||||
UE->reestablish_rlc = false;
|
||||
}
|
||||
|
||||
/* if we get the old-gNB-DU-UE-ID, this means there is a reestablishment
|
||||
* ongoing. */
|
||||
if (dl_rrc->old_gNB_DU_ue_id != NULL) {
|
||||
AssertFatal(*dl_rrc->old_gNB_DU_ue_id != dl_rrc->gNB_DU_ue_id,
|
||||
"logic bug: current and old gNB DU UE ID cannot be the same\n");
|
||||
@@ -960,30 +973,30 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
|
||||
NR_UE_info_t *oldUE = find_nr_UE(&mac->UE_info, *dl_rrc->old_gNB_DU_ue_id);
|
||||
AssertFatal(oldUE, "CU claims we should know UE %04x, but we don't\n", *dl_rrc->old_gNB_DU_ue_id);
|
||||
pthread_mutex_lock(&mac->sched_lock);
|
||||
/* 38.331 5.3.7.2 says that the UE releases the spCellConfig, so we drop it
|
||||
* from the current configuration. Also, expect the reconfiguration from
|
||||
* the CU, so save the old UE's CellGroup for the new UE */
|
||||
UE->CellGroup->spCellConfig = NULL;
|
||||
uid_t temp_uid = UE->uid;
|
||||
UE->uid = oldUE->uid;
|
||||
oldUE->uid = temp_uid;
|
||||
for (int i = 1; i < seq_arr_size(&oldUE->UE_sched_ctrl.lc_config); ++i) {
|
||||
const nr_lc_config_t *c = seq_arr_at(&oldUE->UE_sched_ctrl.lc_config, i);
|
||||
nr_mac_add_lcid(&UE->UE_sched_ctrl, c);
|
||||
nr_lc_config_t new = *c;
|
||||
new.suspended = true;
|
||||
nr_mac_add_lcid(&UE->UE_sched_ctrl, &new);
|
||||
}
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
UE->CellGroup = oldUE->CellGroup;
|
||||
oldUE->CellGroup = NULL;
|
||||
UE->mac_stats = oldUE->mac_stats;
|
||||
/* 38.331 5.3.7.2 says that the UE releases the spCellConfig, so we drop it
|
||||
* from the current configuration. It will be reapplied when the
|
||||
* reconfiguration has succeeded (indicated by the CU) */
|
||||
UE->reconfigSpCellConfig = UE->CellGroup->spCellConfig;
|
||||
UE->CellGroup->spCellConfig = NULL;
|
||||
mac_remove_nr_ue(mac, *dl_rrc->old_gNB_DU_ue_id);
|
||||
pthread_mutex_unlock(&mac->sched_lock);
|
||||
nr_rlc_remove_ue(dl_rrc->gNB_DU_ue_id);
|
||||
nr_rlc_update_id(*dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id);
|
||||
/* 38.331 clause 5.3.7.4: apply the specified configuration defined in 9.2.1 for SRB1 */
|
||||
nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, NULL);
|
||||
/* Set flag to trigger RLC re-establishment
|
||||
* for remaining RBs in next RRCReconfiguration */
|
||||
UE->reestablish_rlc = true;
|
||||
instance_t f1inst = get_f1_gtp_instance();
|
||||
if (f1inst >= 0) // we actually use F1-U
|
||||
gtpv1u_update_ue_id(f1inst, *dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id);
|
||||
|
||||
@@ -236,7 +236,8 @@ static void mac_rrc_init(gNB_MAC_INST *mac, ngran_node_t node_type)
|
||||
void mac_top_init_gNB(ngran_node_t node_type,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
NR_ServingCellConfig_t *scd,
|
||||
const nr_mac_config_t *config)
|
||||
const nr_mac_config_t *config,
|
||||
const nr_rlc_configuration_t *default_rlc_config)
|
||||
{
|
||||
module_id_t i;
|
||||
gNB_MAC_INST *nrmac;
|
||||
@@ -272,6 +273,7 @@ void mac_top_init_gNB(ngran_node_t node_type,
|
||||
|
||||
RC.nrmac[i]->common_channels[0].ServingCellConfigCommon = scc;
|
||||
RC.nrmac[i]->radio_config = *config;
|
||||
RC.nrmac[i]->rlc_config = *default_rlc_config;
|
||||
|
||||
RC.nrmac[i]->common_channels[0].pre_ServingCellConfig = scd;
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "common/utils/ds/seq_arr.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_configuration.h"
|
||||
|
||||
#define NR_SCHED_LOCK(lock) \
|
||||
do { \
|
||||
@@ -89,9 +90,6 @@
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "NR_TAG.h"
|
||||
|
||||
#include <openair3/UICC/usim_interface.h>
|
||||
|
||||
|
||||
/* Defs */
|
||||
#define MAX_NUM_BWP 5
|
||||
#define MAX_NUM_CORESET 12
|
||||
@@ -100,7 +98,6 @@
|
||||
#define NR_NB_RA_PROC_MAX 4
|
||||
#define MAX_NUM_OF_SSB 64
|
||||
#define MAX_NUM_NR_PRACH_PREAMBLES 64
|
||||
#define MIN_NUM_PRBS_TO_SCHEDULE 5
|
||||
|
||||
uint8_t nr_get_rv(int rel_round);
|
||||
|
||||
@@ -564,6 +561,8 @@ typedef struct NR_QoS_config_s {
|
||||
|
||||
typedef struct nr_lc_config {
|
||||
uint8_t lcid;
|
||||
/// flag if corresponding RB is suspended
|
||||
bool suspended;
|
||||
/// priority as specified in 38.321
|
||||
int priority;
|
||||
/// associated NSSAI for DRB
|
||||
@@ -677,10 +676,6 @@ typedef struct {
|
||||
float pdcch_cl_adjust;
|
||||
} NR_UE_sched_ctrl_t;
|
||||
|
||||
typedef struct {
|
||||
uicc_t *uicc;
|
||||
} NRUEcontext_t;
|
||||
|
||||
typedef struct NR_mac_dir_stats {
|
||||
uint64_t lc_bytes[64];
|
||||
uint64_t rounds[8];
|
||||
@@ -744,8 +739,9 @@ typedef struct {
|
||||
NR_mac_stats_t mac_stats;
|
||||
/// currently active CellGroupConfig
|
||||
NR_CellGroupConfig_t *CellGroup;
|
||||
/// reestablishRLC has to be signaled in RRCreconfiguration
|
||||
bool reestablish_rlc;
|
||||
/// in case of reestablishment, old spCellConfig to apply after
|
||||
/// reconfiguration
|
||||
NR_SpCellConfig_t *reconfigSpCellConfig;
|
||||
interrupt_followup_action_t interrupt_action;
|
||||
NR_UE_NR_Capability_t *capability;
|
||||
// UE selected beam index
|
||||
@@ -899,6 +895,7 @@ typedef struct gNB_MAC_INST_s {
|
||||
nr_pp_impl_ul pre_processor_ul;
|
||||
|
||||
nr_mac_config_t radio_config;
|
||||
nr_rlc_configuration_t rlc_config;
|
||||
|
||||
NR_UE_sched_ctrl_t *sched_ctrlCommon;
|
||||
NR_sched_pdcch_t *sched_pdcch_otherSI;
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair3/UTILS/conversions.h"
|
||||
#include "LAYER2/nr_rlc/nr_rlc_asn1_utils.h"
|
||||
|
||||
#include "NR_MeasurementTimingConfiguration.h"
|
||||
#include "uper_decoder.h"
|
||||
@@ -728,64 +729,58 @@ static struct NR_SRS_Resource__resourceType__periodic *configure_periodic_srs(co
|
||||
return periodic_srs;
|
||||
}
|
||||
|
||||
static NR_SetupRelease_SRS_Config_t *get_config_srs(const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
const int curr_bwp,
|
||||
const int uid,
|
||||
const int res_id,
|
||||
const long maxMIMO_Layers,
|
||||
const int minRXTXTIME,
|
||||
int do_srs)
|
||||
static NR_SRS_ResourceSet_t *get_srs_resourceset(const int resset_id,
|
||||
const int res_id,
|
||||
const long usage,
|
||||
const int minRXTXTIME,
|
||||
int do_srs)
|
||||
{
|
||||
NR_SetupRelease_SRS_Config_t *setup_release_srs_Config = calloc(1,sizeof(*setup_release_srs_Config));
|
||||
setup_release_srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup;
|
||||
setup_release_srs_Config->choice.setup = calloc(1,sizeof(*setup_release_srs_Config->choice.setup));
|
||||
NR_SRS_Config_t *srs_Config = setup_release_srs_Config->choice.setup;
|
||||
|
||||
srs_Config->srs_ResourceSetToReleaseList = NULL;
|
||||
|
||||
srs_Config->srs_ResourceSetToAddModList = calloc(1,sizeof(*srs_Config->srs_ResourceSetToAddModList));
|
||||
NR_SRS_ResourceSet_t *srs_resset0 = calloc(1,sizeof(*srs_resset0));
|
||||
srs_resset0->srs_ResourceSetId = res_id;
|
||||
srs_resset0->srs_ResourceIdList = calloc(1,sizeof(*srs_resset0->srs_ResourceIdList));
|
||||
NR_SRS_ResourceId_t *srs_resset0_id = calloc(1,sizeof(*srs_resset0_id));
|
||||
*srs_resset0_id = res_id;
|
||||
asn1cSeqAdd(&srs_resset0->srs_ResourceIdList->list, srs_resset0_id);
|
||||
srs_Config->srs_ResourceToReleaseList=NULL;
|
||||
NR_SRS_ResourceSet_t *srs_resset = calloc_or_fail(1, sizeof(*srs_resset));
|
||||
srs_resset->srs_ResourceSetId = resset_id;
|
||||
srs_resset->srs_ResourceIdList = calloc_or_fail(1, sizeof(*srs_resset->srs_ResourceIdList));
|
||||
NR_SRS_ResourceId_t *srs_resset_id = calloc_or_fail(1, sizeof(*srs_resset_id));
|
||||
*srs_resset_id = res_id;
|
||||
asn1cSeqAdd(&srs_resset->srs_ResourceIdList->list, srs_resset_id);
|
||||
if (do_srs) {
|
||||
srs_resset0->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_periodic;
|
||||
srs_resset0->resourceType.choice.periodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.periodic));
|
||||
srs_resset0->resourceType.choice.periodic->associatedCSI_RS = NULL;
|
||||
srs_resset->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_periodic;
|
||||
srs_resset->resourceType.choice.periodic = calloc_or_fail(1, sizeof(*srs_resset->resourceType.choice.periodic));
|
||||
srs_resset->resourceType.choice.periodic->associatedCSI_RS = NULL;
|
||||
} else {
|
||||
srs_resset0->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_aperiodic;
|
||||
srs_resset0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic));
|
||||
srs_resset0->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger = 1;
|
||||
srs_resset0->resourceType.choice.aperiodic->csi_RS = NULL;
|
||||
srs_resset0->resourceType.choice.aperiodic->slotOffset = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic->slotOffset));
|
||||
*srs_resset0->resourceType.choice.aperiodic->slotOffset = minRXTXTIME;
|
||||
srs_resset0->resourceType.choice.aperiodic->ext1 = NULL;
|
||||
srs_resset->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_aperiodic;
|
||||
srs_resset->resourceType.choice.aperiodic = calloc_or_fail(1, sizeof(*srs_resset->resourceType.choice.aperiodic));
|
||||
srs_resset->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger = 1;
|
||||
srs_resset->resourceType.choice.aperiodic->csi_RS = NULL;
|
||||
srs_resset->resourceType.choice.aperiodic->slotOffset =
|
||||
calloc_or_fail(1, sizeof(*srs_resset->resourceType.choice.aperiodic->slotOffset));
|
||||
*srs_resset->resourceType.choice.aperiodic->slotOffset = minRXTXTIME;
|
||||
srs_resset->resourceType.choice.aperiodic->ext1 = NULL;
|
||||
}
|
||||
srs_resset0->usage=NR_SRS_ResourceSet__usage_codebook;
|
||||
srs_resset0->alpha = calloc(1,sizeof(*srs_resset0->alpha));
|
||||
*srs_resset0->alpha = NR_Alpha_alpha1;
|
||||
srs_resset0->p0 = calloc(1,sizeof(*srs_resset0->p0));
|
||||
*srs_resset0->p0 =-80;
|
||||
srs_resset0->pathlossReferenceRS = NULL;
|
||||
srs_resset0->srs_PowerControlAdjustmentStates = NULL;
|
||||
asn1cSeqAdd(&srs_Config->srs_ResourceSetToAddModList->list,srs_resset0);
|
||||
srs_resset->usage = usage;
|
||||
srs_resset->alpha = calloc_or_fail(1, sizeof(*srs_resset->alpha));
|
||||
*srs_resset->alpha = NR_Alpha_alpha1;
|
||||
srs_resset->p0 = calloc_or_fail(1, sizeof(*srs_resset->p0));
|
||||
*srs_resset->p0 = -80;
|
||||
srs_resset->pathlossReferenceRS = NULL;
|
||||
srs_resset->srs_PowerControlAdjustmentStates = NULL;
|
||||
return srs_resset;
|
||||
}
|
||||
|
||||
srs_Config->srs_ResourceToReleaseList = NULL;
|
||||
|
||||
srs_Config->srs_ResourceToAddModList = calloc(1,sizeof(*srs_Config->srs_ResourceToAddModList));
|
||||
NR_SRS_Resource_t *srs_res0=calloc(1,sizeof(*srs_res0));
|
||||
srs_res0->srs_ResourceId = res_id;
|
||||
srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_port1;
|
||||
static NR_SRS_Resource_t *get_srs_resource(const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
const int curr_bwp,
|
||||
const int uid,
|
||||
const int res_id,
|
||||
const long maxMIMO_Layers,
|
||||
const NR_SRS_Resource__transmissionComb_PR tx_comb,
|
||||
int do_srs)
|
||||
{
|
||||
NR_SRS_Resource_t *srs_res = calloc_or_fail(1, sizeof(*srs_res));
|
||||
srs_res->srs_ResourceId = res_id;
|
||||
srs_res->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_port1;
|
||||
if (do_srs) {
|
||||
long nrofSRS_Ports = 1;
|
||||
if (uecap &&
|
||||
uecap->featureSets &&
|
||||
uecap->featureSets->featureSetsUplink &&
|
||||
uecap->featureSets->featureSetsUplink->list.count > 0) {
|
||||
if (uecap && uecap->featureSets && uecap->featureSets->featureSetsUplink
|
||||
&& uecap->featureSets->featureSetsUplink->list.count > 0) {
|
||||
NR_FeatureSetUplink_t *ul_feature_setup = uecap->featureSets->featureSetsUplink->list.array[0];
|
||||
switch (ul_feature_setup->supportedSRS_Resources->maxNumberSRS_Ports_PerResource) {
|
||||
case NR_SRS_Resources__maxNumberSRS_Ports_PerResource_n1:
|
||||
@@ -798,55 +793,95 @@ static NR_SetupRelease_SRS_Config_t *get_config_srs(const NR_ServingCellConfigCo
|
||||
nrofSRS_Ports = 4;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_RRC, "Max Number of SRS Ports Per Resource %ld is invalid!\n",
|
||||
LOG_E(NR_RRC,
|
||||
"Max Number of SRS Ports Per Resource %ld is invalid!\n",
|
||||
ul_feature_setup->supportedSRS_Resources->maxNumberSRS_Ports_PerResource);
|
||||
}
|
||||
nrofSRS_Ports = min(nrofSRS_Ports, maxMIMO_Layers);
|
||||
switch (nrofSRS_Ports) {
|
||||
case 1:
|
||||
srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_port1;
|
||||
srs_res->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_port1;
|
||||
break;
|
||||
case 2:
|
||||
srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_ports2;
|
||||
srs_res->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_ports2;
|
||||
break;
|
||||
case 4:
|
||||
srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_ports4;
|
||||
srs_res->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_ports4;
|
||||
break;
|
||||
default:
|
||||
LOG_E(NR_RRC, "Number of SRS Ports Per Resource %ld is invalid!\n",
|
||||
LOG_E(NR_RRC,
|
||||
"Number of SRS Ports Per Resource %ld is invalid!\n",
|
||||
ul_feature_setup->supportedSRS_Resources->maxNumberSRS_Ports_PerResource);
|
||||
}
|
||||
}
|
||||
LOG_I(NR_RRC, "SRS configured with %d ports\n", 1<<srs_res0->nrofSRS_Ports);
|
||||
LOG_I(NR_RRC, "SRS configured with %d ports\n", 1 << srs_res->nrofSRS_Ports);
|
||||
}
|
||||
srs_res0->ptrs_PortIndex = NULL;
|
||||
srs_res0->transmissionComb.present = NR_SRS_Resource__transmissionComb_PR_n2;
|
||||
srs_res0->transmissionComb.choice.n2 = calloc(1,sizeof(*srs_res0->transmissionComb.choice.n2));
|
||||
srs_res0->transmissionComb.choice.n2->combOffset_n2 = 0;
|
||||
srs_res0->transmissionComb.choice.n2->cyclicShift_n2 = 0;
|
||||
srs_res0->resourceMapping.startPosition = 1;
|
||||
srs_res0->resourceMapping.nrofSymbols = NR_SRS_Resource__resourceMapping__nrofSymbols_n1;
|
||||
srs_res0->resourceMapping.repetitionFactor = NR_SRS_Resource__resourceMapping__repetitionFactor_n1;
|
||||
srs_res0->freqDomainPosition = 0;
|
||||
srs_res0->freqDomainShift = 0;
|
||||
srs_res0->freqHopping.b_SRS = 0;
|
||||
srs_res0->freqHopping.b_hop = 0;
|
||||
srs_res0->freqHopping.c_SRS = rrc_get_max_nr_csrs(curr_bwp, srs_res0->freqHopping.b_SRS);
|
||||
srs_res0->groupOrSequenceHopping = NR_SRS_Resource__groupOrSequenceHopping_neither;
|
||||
srs_res->ptrs_PortIndex = NULL;
|
||||
srs_res->transmissionComb.present = tx_comb;
|
||||
switch (tx_comb) {
|
||||
case NR_SRS_Resource__transmissionComb_PR_n2:
|
||||
srs_res->transmissionComb.choice.n2 = calloc_or_fail(1, sizeof(*srs_res->transmissionComb.choice.n2));
|
||||
srs_res->transmissionComb.choice.n2->combOffset_n2 = 0;
|
||||
srs_res->transmissionComb.choice.n2->cyclicShift_n2 = 0;
|
||||
break;
|
||||
case NR_SRS_Resource__transmissionComb_PR_n4:
|
||||
srs_res->transmissionComb.choice.n4 = calloc_or_fail(1, sizeof(*srs_res->transmissionComb.choice.n4));
|
||||
srs_res->transmissionComb.choice.n4->combOffset_n4 = 0;
|
||||
srs_res->transmissionComb.choice.n4->cyclicShift_n4 = 0;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Invalid transmission comb %d\n", tx_comb);
|
||||
}
|
||||
srs_res->resourceMapping.startPosition = 1;
|
||||
srs_res->resourceMapping.nrofSymbols = NR_SRS_Resource__resourceMapping__nrofSymbols_n1;
|
||||
srs_res->resourceMapping.repetitionFactor = NR_SRS_Resource__resourceMapping__repetitionFactor_n1;
|
||||
srs_res->freqDomainPosition = 0;
|
||||
srs_res->freqDomainShift = 0;
|
||||
srs_res->freqHopping.b_SRS = 0;
|
||||
srs_res->freqHopping.b_hop = 0;
|
||||
srs_res->freqHopping.c_SRS = rrc_get_max_nr_csrs(curr_bwp, srs_res->freqHopping.b_SRS);
|
||||
srs_res->groupOrSequenceHopping = NR_SRS_Resource__groupOrSequenceHopping_neither;
|
||||
if (do_srs) {
|
||||
srs_res0->resourceType.present = NR_SRS_Resource__resourceType_PR_periodic;
|
||||
srs_res0->resourceType.choice.periodic = configure_periodic_srs(scc, uid);
|
||||
srs_res->resourceType.present = NR_SRS_Resource__resourceType_PR_periodic;
|
||||
srs_res->resourceType.choice.periodic = configure_periodic_srs(scc, uid);
|
||||
} else {
|
||||
srs_res0->resourceType.present = NR_SRS_Resource__resourceType_PR_aperiodic;
|
||||
srs_res0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_res0->resourceType.choice.aperiodic));
|
||||
srs_res->resourceType.present = NR_SRS_Resource__resourceType_PR_aperiodic;
|
||||
srs_res->resourceType.choice.aperiodic = calloc_or_fail(1, sizeof(*srs_res->resourceType.choice.aperiodic));
|
||||
}
|
||||
srs_res0->sequenceId = 40;
|
||||
srs_res0->spatialRelationInfo = calloc(1,sizeof(*srs_res0->spatialRelationInfo));
|
||||
srs_res0->spatialRelationInfo->servingCellId = NULL;
|
||||
srs_res->sequenceId = 40;
|
||||
srs_res->spatialRelationInfo = calloc_or_fail(1, sizeof(*srs_res->spatialRelationInfo));
|
||||
srs_res->spatialRelationInfo->servingCellId = NULL;
|
||||
// TODO include CSI as reference signal when BWPs are handled properly
|
||||
srs_res0->spatialRelationInfo->referenceSignal.present = NR_SRS_SpatialRelationInfo__referenceSignal_PR_ssb_Index;
|
||||
srs_res0->spatialRelationInfo->referenceSignal.choice.ssb_Index = 0;
|
||||
asn1cSeqAdd(&srs_Config->srs_ResourceToAddModList->list,srs_res0);
|
||||
srs_res->spatialRelationInfo->referenceSignal.present = NR_SRS_SpatialRelationInfo__referenceSignal_PR_ssb_Index;
|
||||
srs_res->spatialRelationInfo->referenceSignal.choice.ssb_Index = 0;
|
||||
return srs_res;
|
||||
}
|
||||
|
||||
static NR_SetupRelease_SRS_Config_t *get_config_srs(const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_UE_NR_Capability_t *uecap,
|
||||
const int curr_bwp,
|
||||
const int uid,
|
||||
const int res_id,
|
||||
const long maxMIMO_Layers,
|
||||
const int minRXTXTIME,
|
||||
int do_srs)
|
||||
{
|
||||
NR_SetupRelease_SRS_Config_t *setup_release_srs_Config = calloc_or_fail(1, sizeof(*setup_release_srs_Config));
|
||||
setup_release_srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup;
|
||||
setup_release_srs_Config->choice.setup = calloc_or_fail(1, sizeof(*setup_release_srs_Config->choice.setup));
|
||||
NR_SRS_Config_t *srs_Config = setup_release_srs_Config->choice.setup;
|
||||
|
||||
srs_Config->srs_ResourceToAddModList = calloc_or_fail(1, sizeof(*srs_Config->srs_ResourceToAddModList));
|
||||
NR_SRS_Resource_t *srs_res0 =
|
||||
get_srs_resource(scc, uecap, curr_bwp, uid, res_id, maxMIMO_Layers, NR_SRS_Resource__transmissionComb_PR_n2, do_srs);
|
||||
asn1cSeqAdd(&srs_Config->srs_ResourceToAddModList->list, srs_res0);
|
||||
|
||||
srs_Config->srs_ResourceSetToAddModList = calloc_or_fail(1, sizeof(*srs_Config->srs_ResourceSetToAddModList));
|
||||
NR_SRS_ResourceSet_t *srs_resset0 = get_srs_resourceset(res_id, res_id, NR_SRS_ResourceSet__usage_codebook, minRXTXTIME, do_srs);
|
||||
asn1cSeqAdd(&srs_Config->srs_ResourceSetToAddModList->list, srs_resset0);
|
||||
|
||||
srs_Config->srs_ResourceSetToReleaseList = NULL;
|
||||
srs_Config->srs_ResourceToReleaseList = NULL;
|
||||
|
||||
return setup_release_srs_Config;
|
||||
}
|
||||
@@ -3338,7 +3373,10 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
|
||||
return SpCellConfig;
|
||||
}
|
||||
|
||||
NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, long priority, long bucketSizeDuration)
|
||||
NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId,
|
||||
long priority,
|
||||
long bucketSizeDuration,
|
||||
const nr_rlc_configuration_t *default_rlc_config)
|
||||
{
|
||||
NR_RLC_BearerConfig_t *rlc_BearerConfig = NULL;
|
||||
rlc_BearerConfig = calloc(1, sizeof(NR_RLC_BearerConfig_t));
|
||||
@@ -3352,15 +3390,15 @@ NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, long priority, l
|
||||
rlc_Config->present = NR_RLC_Config_PR_am;
|
||||
rlc_Config->choice.am = calloc(1, sizeof(*rlc_Config->choice.am));
|
||||
rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t));
|
||||
*(rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength) = NR_SN_FieldLengthAM_size12;
|
||||
rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms35;
|
||||
rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms0;
|
||||
*(rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength) = encode_sn_field_length_am(default_rlc_config->srb.sn_field_length);
|
||||
rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = encode_t_reassembly(default_rlc_config->srb.t_reassembly);
|
||||
rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = encode_t_status_prohibit(default_rlc_config->srb.t_status_prohibit);
|
||||
rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t));
|
||||
*(rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength) = NR_SN_FieldLengthAM_size12;
|
||||
rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms45;
|
||||
rlc_Config->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_infinity;
|
||||
rlc_Config->choice.am->ul_AM_RLC.pollByte = NR_PollByte_infinity;
|
||||
rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t8;
|
||||
*(rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength) = encode_sn_field_length_am(default_rlc_config->srb.sn_field_length);
|
||||
rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = encode_t_poll_retransmit(default_rlc_config->srb.t_poll_retransmit);
|
||||
rlc_Config->choice.am->ul_AM_RLC.pollPDU = encode_poll_pdu(default_rlc_config->srb.poll_pdu);
|
||||
rlc_Config->choice.am->ul_AM_RLC.pollByte = encode_poll_byte(default_rlc_config->srb.poll_byte);
|
||||
rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = encode_max_retx_threshold(default_rlc_config->srb.max_retx_threshold);
|
||||
rlc_BearerConfig->rlc_Config = rlc_Config;
|
||||
|
||||
NR_LogicalChannelConfig_t *logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t));
|
||||
@@ -3381,7 +3419,9 @@ NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, long priority, l
|
||||
return rlc_BearerConfig;
|
||||
}
|
||||
|
||||
static void nr_drb_config(struct NR_RLC_Config *rlc_Config, NR_RLC_Config_PR rlc_config_pr)
|
||||
static void nr_drb_config(struct NR_RLC_Config *rlc_Config,
|
||||
NR_RLC_Config_PR rlc_config_pr,
|
||||
const nr_rlc_configuration_t *default_rlc_config)
|
||||
{
|
||||
switch (rlc_config_pr) {
|
||||
case NR_RLC_Config_PR_um_Bi_Directional:
|
||||
@@ -3390,25 +3430,25 @@ static void nr_drb_config(struct NR_RLC_Config *rlc_Config, NR_RLC_Config_PR rlc
|
||||
rlc_Config->choice.um_Bi_Directional = calloc(1, sizeof(*rlc_Config->choice.um_Bi_Directional));
|
||||
rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength =
|
||||
calloc(1, sizeof(*rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength));
|
||||
*rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12;
|
||||
*rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = encode_sn_field_length_um(default_rlc_config->drb_um.sn_field_length);
|
||||
rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength =
|
||||
calloc(1, sizeof(*rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength));
|
||||
*rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12;
|
||||
rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.t_Reassembly = NR_T_Reassembly_ms15;
|
||||
*rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = encode_sn_field_length_um(default_rlc_config->drb_um.sn_field_length);
|
||||
rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.t_Reassembly = encode_t_reassembly(default_rlc_config->drb_um.t_reassembly);
|
||||
break;
|
||||
case NR_RLC_Config_PR_am:
|
||||
// RLC AM Bearer configuration
|
||||
rlc_Config->choice.am = calloc(1, sizeof(*rlc_Config->choice.am));
|
||||
rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1, sizeof(*rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength));
|
||||
*rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18;
|
||||
rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms45;
|
||||
rlc_Config->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_p64;
|
||||
rlc_Config->choice.am->ul_AM_RLC.pollByte = NR_PollByte_kB500;
|
||||
rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t32;
|
||||
*rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = encode_sn_field_length_am(default_rlc_config->drb_am.sn_field_length);
|
||||
rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = encode_t_poll_retransmit(default_rlc_config->drb_am.t_poll_retransmit);
|
||||
rlc_Config->choice.am->ul_AM_RLC.pollPDU = encode_poll_pdu(default_rlc_config->drb_am.poll_pdu);
|
||||
rlc_Config->choice.am->ul_AM_RLC.pollByte = encode_poll_byte(default_rlc_config->drb_am.poll_byte);
|
||||
rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = encode_max_retx_threshold(default_rlc_config->drb_am.max_retx_threshold);
|
||||
rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1, sizeof(*rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength));
|
||||
*rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18;
|
||||
rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms15;
|
||||
rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms15;
|
||||
*rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = encode_sn_field_length_am(default_rlc_config->drb_am.sn_field_length);
|
||||
rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = encode_t_reassembly(default_rlc_config->drb_am.t_reassembly);
|
||||
rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = encode_t_status_prohibit(default_rlc_config->drb_am.t_status_prohibit);
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "RLC config type %d not handled\n", rlc_config_pr);
|
||||
@@ -3417,7 +3457,11 @@ static void nr_drb_config(struct NR_RLC_Config *rlc_Config, NR_RLC_Config_PR rlc
|
||||
rlc_Config->present = rlc_config_pr;
|
||||
}
|
||||
|
||||
NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, long drbId, NR_RLC_Config_PR rlc_conf, long priority)
|
||||
NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId,
|
||||
long drbId,
|
||||
NR_RLC_Config_PR rlc_conf,
|
||||
long priority,
|
||||
const nr_rlc_configuration_t *default_rlc_config)
|
||||
{
|
||||
NR_RLC_BearerConfig_t *rlc_BearerConfig = calloc(1, sizeof(NR_RLC_BearerConfig_t));
|
||||
rlc_BearerConfig->logicalChannelIdentity = lcChannelId;
|
||||
@@ -3427,7 +3471,7 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, long drbId, NR
|
||||
rlc_BearerConfig->reestablishRLC = NULL;
|
||||
|
||||
NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t));
|
||||
nr_drb_config(rlc_Config, rlc_conf);
|
||||
nr_drb_config(rlc_Config, rlc_conf, default_rlc_config);
|
||||
rlc_BearerConfig->rlc_Config = rlc_Config;
|
||||
|
||||
NR_LogicalChannelConfig_t *logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t));
|
||||
@@ -3451,7 +3495,8 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, long drbId, NR
|
||||
NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_ServingCellConfig_t *servingcellconfigdedicated,
|
||||
const nr_mac_config_t *configuration)
|
||||
const nr_mac_config_t *configuration,
|
||||
const nr_rlc_configuration_t *default_rlc_config)
|
||||
{
|
||||
NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(*cellGroupConfig));
|
||||
cellGroupConfig->cellGroupId = 0;
|
||||
@@ -3460,7 +3505,7 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
|
||||
/* TS38.331 9.2.1 Default SRB configurations */
|
||||
cellGroupConfig->rlc_BearerToAddModList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList));
|
||||
NR_RLC_BearerConfig_t *rlc_BearerConfig =
|
||||
get_SRB_RLC_BearerConfig(1, 1, NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms1000);
|
||||
get_SRB_RLC_BearerConfig(1, 1, NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms1000, default_rlc_config);
|
||||
asn1cSeqAdd(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
|
||||
|
||||
cellGroupConfig->rlc_BearerToReleaseList = NULL;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "NR_UL-CCCH-Message.h"
|
||||
#include "f1ap_messages_types.h"
|
||||
#include "common/platform_types.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_configuration.h"
|
||||
struct NR_MeasurementTimingConfiguration;
|
||||
struct NR_PDSCH_TimeDomainResourceAllocationList;
|
||||
|
||||
@@ -84,7 +85,8 @@ NR_SIB19_r17_t *get_SIB19_NR(const NR_ServingCellConfigCommon_t *scc);
|
||||
NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_ServingCellConfig_t *servingcellconfigdedicated,
|
||||
const nr_mac_config_t *configuration);
|
||||
const nr_mac_config_t *configuration,
|
||||
const nr_rlc_configuration_t *default_rlc_config);
|
||||
void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
|
||||
const int uid,
|
||||
NR_UE_NR_Capability_t *uecap,
|
||||
@@ -107,7 +109,14 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
|
||||
|
||||
NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc);
|
||||
|
||||
NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, long priority, long bucketSizeDuration);
|
||||
NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, long drbId, NR_RLC_Config_PR rlc_conf, long priority);
|
||||
NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId,
|
||||
long priority,
|
||||
long bucketSizeDuration,
|
||||
const nr_rlc_configuration_t *default_rlc_config);
|
||||
NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId,
|
||||
long drbId,
|
||||
NR_RLC_Config_PR rlc_conf,
|
||||
long priority,
|
||||
const nr_rlc_configuration_t *default_rlc_config);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,63 +19,30 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "nr_pdcp_asn1_utils.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "nr_pdcp_entity.h"
|
||||
#include "nr_pdcp_configuration.h"
|
||||
|
||||
int decode_t_reordering(int v)
|
||||
{
|
||||
static const int tab[36] = {0, 1, 2, 4, 5, 8, 10, 15, 20, 30, 40, 50, 60, 80, 100, 120, 140, 160,
|
||||
180, 200, 220, 240, 260, 280, 300, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000};
|
||||
|
||||
if (v < 0 || v > 35) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
#define ENCODE_DECODE(a, b) \
|
||||
int decode_##a(int v) \
|
||||
{ \
|
||||
static const int tab[] = { VALUES_NR_PDCP_##b }; \
|
||||
AssertFatal(v >= 0 && v < SIZEOF_NR_PDCP_##b, \
|
||||
"bad encoded value " #a " %d\n", v); \
|
||||
return tab[v]; \
|
||||
} \
|
||||
\
|
||||
int encode_##a(int v) \
|
||||
{ \
|
||||
static const int tab[] = { VALUES_NR_PDCP_##b }; \
|
||||
for (int ret = 0; ret < SIZEOF_NR_PDCP_##b; ret++) \
|
||||
if (tab[ret] == v) \
|
||||
return ret; \
|
||||
AssertFatal(0, "bad " #a " value %d\n", v); \
|
||||
}
|
||||
|
||||
int decode_sn_size_ul(long s)
|
||||
{
|
||||
if (s == 0) return SHORT_SN_SIZE;
|
||||
if (s == 1) return LONG_SN_SIZE;
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int decode_sn_size_dl(long s)
|
||||
{
|
||||
if (s == 0) return SHORT_SN_SIZE;
|
||||
if (s == 1) return LONG_SN_SIZE;
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int decode_discard_timer(long v)
|
||||
{
|
||||
static const int tab[16] = {
|
||||
10,
|
||||
20,
|
||||
30,
|
||||
40,
|
||||
50,
|
||||
60,
|
||||
75,
|
||||
100,
|
||||
150,
|
||||
200,
|
||||
250,
|
||||
300,
|
||||
500,
|
||||
750,
|
||||
1500,
|
||||
-1,
|
||||
};
|
||||
|
||||
if (v < 0 || v > 15) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
ENCODE_DECODE(t_reordering, T_REORDERING)
|
||||
ENCODE_DECODE(sn_size_ul, SN_SIZE)
|
||||
ENCODE_DECODE(sn_size_dl, SN_SIZE)
|
||||
ENCODE_DECODE(discard_timer, DISCARD_TIMER)
|
||||
|
||||
@@ -23,8 +23,13 @@
|
||||
#define _OPENAIR2_LAYER2_NR_PDCP_ASN1_UTILS_H_
|
||||
|
||||
int decode_t_reordering(int v);
|
||||
int decode_sn_size_ul(long s);
|
||||
int decode_sn_size_dl(long s);
|
||||
int decode_discard_timer(long v);
|
||||
int decode_sn_size_ul(int v);
|
||||
int decode_sn_size_dl(int v);
|
||||
int decode_discard_timer(int v);
|
||||
|
||||
int encode_t_reordering(int v);
|
||||
int encode_sn_size_ul(int v);
|
||||
int encode_sn_size_dl(int v);
|
||||
int encode_discard_timer(int v);
|
||||
|
||||
#endif /* _OPENAIR2_LAYER2_NR_PDCP_ASN1_UTILS_H_ */
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _NR_PDCP_CONFIGURATION_H_
|
||||
#define _NR_PDCP_CONFIGURATION_H_
|
||||
|
||||
#ifndef INT_LIST_SIZE
|
||||
#define INT_LIST_SIZE(x) (sizeof((int[]){x})/sizeof(int))
|
||||
#endif
|
||||
|
||||
/* values taken from 3GPP TS 38.331 version 17.3.0 */
|
||||
|
||||
#define VALUES_NR_PDCP_SN_SIZE \
|
||||
12, 18
|
||||
|
||||
#define VALUES_NR_PDCP_SN_SIZE_STR \
|
||||
"len12bits", "len18bits"
|
||||
|
||||
#define SIZEOF_NR_PDCP_SN_SIZE INT_LIST_SIZE(VALUES_NR_PDCP_SN_SIZE)
|
||||
|
||||
#define VALUES_NR_PDCP_T_REORDERING \
|
||||
0, 1, 2, 4, 5, 8, 10, 15, 20, 30, 40, 50, \
|
||||
60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, \
|
||||
300, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000, \
|
||||
-1 /* -1 means infinity */ \
|
||||
|
||||
#define VALUES_NR_PDCP_T_REORDERING_STR \
|
||||
"ms0", "ms1", "ms2", "ms4", "ms5", "ms8", "ms10", "ms15", "ms20", "ms30", "ms40", "ms50", \
|
||||
"ms60", "ms80", "ms100", "ms120", "ms140", "ms160", "ms180", "ms200", "ms220", "ms240", "ms260", "ms280", \
|
||||
"ms300", "ms500", "ms750", "ms1000", "ms1250", "ms1500", "ms1750", "ms2000", "ms2250", "ms2500", "ms2750", "ms3000", \
|
||||
"infinity"
|
||||
|
||||
#define SIZEOF_NR_PDCP_T_REORDERING INT_LIST_SIZE(VALUES_NR_PDCP_T_REORDERING)
|
||||
|
||||
#define VALUES_NR_PDCP_DISCARD_TIMER \
|
||||
10, 20, 30, 40, 50, 60, 75, 100, 150, 200, 250, 300, 500, 750, 1500, -1 /* -1 means infinity */
|
||||
|
||||
#define VALUES_NR_PDCP_DISCARD_TIMER_STR \
|
||||
"ms10", "ms20", "ms30", "ms40", "ms50", "ms60", "ms75", "ms100", "ms150", "ms200", "ms250", "ms300", "ms500", "ms750", "ms1500", "infinity"
|
||||
|
||||
#define SIZEOF_NR_PDCP_DISCARD_TIMER INT_LIST_SIZE(VALUES_NR_PDCP_DISCARD_TIMER)
|
||||
|
||||
/* configuration of NR PDCP, coming from configuration file */
|
||||
typedef struct {
|
||||
struct {
|
||||
int sn_size;
|
||||
int t_reordering;
|
||||
int discard_timer;
|
||||
} drb;
|
||||
} nr_pdcp_configuration_t;
|
||||
|
||||
#endif /* _NR_PDCP_CONFIGURATION_H_ */
|
||||
@@ -19,157 +19,33 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "nr_rlc_asn1_utils.h"
|
||||
#include "rlc.h"
|
||||
#include "nr_rlc_configuration.h"
|
||||
|
||||
int decode_t_reassembly(int v)
|
||||
{
|
||||
static const int tab[31] = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75,
|
||||
80, 85, 90, 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200};
|
||||
|
||||
if (v < 0 || v > 30) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
#define ENCODE_DECODE(a, b) \
|
||||
int decode_##a(int v) \
|
||||
{ \
|
||||
static const int tab[] = { VALUES_NR_RLC_##b }; \
|
||||
AssertFatal(v >= 0 && v < SIZEOF_NR_RLC_##b, \
|
||||
"bad encoded value " #a " %d\n", v); \
|
||||
return tab[v]; \
|
||||
} \
|
||||
\
|
||||
int encode_##a(int v) \
|
||||
{ \
|
||||
static const int tab[] = { VALUES_NR_RLC_##b }; \
|
||||
for (int ret = 0; ret < SIZEOF_NR_RLC_##b; ret++) \
|
||||
if (tab[ret] == v) \
|
||||
return ret; \
|
||||
AssertFatal(0, "bad " #a " value %d\n", v); \
|
||||
}
|
||||
|
||||
int decode_t_status_prohibit(int v)
|
||||
{
|
||||
static const int tab[62] = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75,
|
||||
80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155,
|
||||
160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235,
|
||||
240, 245, 250, 300, 350, 400, 450, 500, 800, 1000, 1200, 1600, 2000, 2400};
|
||||
|
||||
if (v < 0 || v > 61) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_t_poll_retransmit(int v)
|
||||
{
|
||||
static const int tab[59] = {5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100,
|
||||
105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180, 185, 190, 195, 200,
|
||||
205, 210, 215, 220, 225, 230, 235, 240, 245, 250, 300, 350, 400, 450, 500, 800, 1000, 2000, 4000};
|
||||
|
||||
if (v < 0 || v > 58) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_poll_pdu(int v)
|
||||
{
|
||||
static const int tab[24] = {
|
||||
4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 6144,
|
||||
8192, 12288, 16384, 20480, 24576, 28672, 32768, 40960, 49152, 57344, 65536, -1 /* -1 means infinity */
|
||||
};
|
||||
|
||||
if (v < 0 || v > 23) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_poll_byte(int v)
|
||||
{
|
||||
static const int tab[44] = {
|
||||
/* KB */
|
||||
1024 * 1,
|
||||
1024 * 2,
|
||||
1024 * 5,
|
||||
1024 * 8,
|
||||
1024 * 10,
|
||||
1024 * 15,
|
||||
1024 * 25,
|
||||
1024 * 50,
|
||||
1024 * 75,
|
||||
1024 * 100,
|
||||
1024 * 125,
|
||||
1024 * 250,
|
||||
1024 * 375,
|
||||
1024 * 500,
|
||||
1024 * 750,
|
||||
1024 * 1000,
|
||||
1024 * 1250,
|
||||
1024 * 1500,
|
||||
1024 * 2000,
|
||||
1024 * 3000,
|
||||
1024 * 4000,
|
||||
1024 * 4500,
|
||||
1024 * 5000,
|
||||
1024 * 5500,
|
||||
1024 * 6000,
|
||||
1024 * 6500,
|
||||
1024 * 7000,
|
||||
1024 * 7500,
|
||||
/* MB */
|
||||
1024 * 1024 * 8,
|
||||
1024 * 1024 * 9,
|
||||
1024 * 1024 * 10,
|
||||
1024 * 1024 * 11,
|
||||
1024 * 1024 * 12,
|
||||
1024 * 1024 * 13,
|
||||
1024 * 1024 * 14,
|
||||
1024 * 1024 * 15,
|
||||
1024 * 1024 * 16,
|
||||
1024 * 1024 * 17,
|
||||
1024 * 1024 * 18,
|
||||
1024 * 1024 * 20,
|
||||
1024 * 1024 * 25,
|
||||
1024 * 1024 * 30,
|
||||
1024 * 1024 * 40,
|
||||
-1 /* -1 means infinity */
|
||||
};
|
||||
|
||||
if (v < 0 || v > 43) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (tab[v] == -1) return -1;
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_max_retx_threshold(int v)
|
||||
{
|
||||
static const int tab[8] = {1, 2, 3, 4, 6, 8, 16, 32};
|
||||
|
||||
if (v < 0 || v > 7) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_sn_field_length_um(int v)
|
||||
{
|
||||
static const int tab[2] = {6, 12};
|
||||
|
||||
if (v < 0 || v > 1) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
|
||||
int decode_sn_field_length_am(int v)
|
||||
{
|
||||
static const int tab[2] = {12, 18};
|
||||
|
||||
if (v < 0 || v > 1) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return tab[v];
|
||||
}
|
||||
ENCODE_DECODE(t_reassembly, T_REASSEMBLY)
|
||||
ENCODE_DECODE(t_status_prohibit, T_STATUS_PROHIBIT)
|
||||
ENCODE_DECODE(t_poll_retransmit, T_POLL_RETRANSMIT)
|
||||
ENCODE_DECODE(poll_pdu, POLL_PDU)
|
||||
ENCODE_DECODE(poll_byte, POLL_BYTE)
|
||||
ENCODE_DECODE(max_retx_threshold, MAX_RETX_THRESHOLD)
|
||||
ENCODE_DECODE(sn_field_length_am, SN_FIELD_LENGTH_AM)
|
||||
ENCODE_DECODE(sn_field_length_um, SN_FIELD_LENGTH_UM)
|
||||
|
||||
@@ -31,4 +31,13 @@ int decode_max_retx_threshold(int v);
|
||||
int decode_sn_field_length_um(int v);
|
||||
int decode_sn_field_length_am(int v);
|
||||
|
||||
int encode_t_reassembly(int v);
|
||||
int encode_t_status_prohibit(int v);
|
||||
int encode_t_poll_retransmit(int v);
|
||||
int encode_poll_pdu(int v);
|
||||
int encode_poll_byte(int v);
|
||||
int encode_max_retx_threshold(int v);
|
||||
int encode_sn_field_length_um(int v);
|
||||
int encode_sn_field_length_am(int v);
|
||||
|
||||
#endif /* _OPENAIR2_LAYER2_NR_RLC_ASN1_UTILS_H_ */
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _NR_RLC_CONFIGURATION_H_
|
||||
#define _NR_RLC_CONFIGURATION_H_
|
||||
|
||||
#ifndef INT_LIST_SIZE
|
||||
#define INT_LIST_SIZE(x) (sizeof((int[]){x})/sizeof(int))
|
||||
#endif
|
||||
|
||||
/* values taken from 3GPP TS 38.331 version 17.3.0 */
|
||||
|
||||
#define VALUES_NR_RLC_T_POLL_RETRANSMIT \
|
||||
5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, \
|
||||
75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, \
|
||||
145, 150, 155, 160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, \
|
||||
215, 220, 225, 230, 235, 240, 245, 250, 300, 350, 400, 450, 500, 800, \
|
||||
1000, 2000, 4000, 1, 2, 4
|
||||
|
||||
#define VALUES_NR_RLC_T_POLL_RETRANSMIT_STR \
|
||||
"ms5", "ms10", "ms15", "ms20", "ms25", "ms30", "ms35", "ms40", "ms45", "ms50", "ms55", "ms60", "ms65", "ms70", \
|
||||
"ms75", "ms80", "ms85", "ms90", "ms95", "ms100", "ms105", "ms110", "ms115", "ms120", "ms125", "ms130", "ms135", "ms140", \
|
||||
"ms145", "ms150", "ms155", "ms160", "ms165", "ms170", "ms175", "ms180", "ms185", "ms190", "ms195", "ms200", "ms205", "ms210", \
|
||||
"ms215", "ms220", "ms225", "ms230", "ms235", "ms240", "ms245", "ms250", "ms300", "ms350", "ms400", "ms450", "ms500", "ms800", \
|
||||
"ms1000", "ms2000", "ms4000", "ms1", "ms2", "ms4"
|
||||
|
||||
#define SIZEOF_NR_RLC_T_POLL_RETRANSMIT INT_LIST_SIZE(VALUES_NR_RLC_T_POLL_RETRANSMIT)
|
||||
|
||||
#define VALUES_NR_RLC_T_REASSEMBLY \
|
||||
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, \
|
||||
80, 85, 90, 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200
|
||||
|
||||
#define VALUES_NR_RLC_T_REASSEMBLY_STR \
|
||||
"ms0", "ms5", "ms10", "ms15", "ms20", "ms25", "ms30", "ms35", "ms40", "ms45", "ms50", "ms55", "ms60", "ms65", "ms70", "ms75", \
|
||||
"ms80", "ms85", "ms90", "ms95", "ms100", "ms110", "ms120", "ms130", "ms140", "ms150", "ms160", "ms170", "ms180", "ms190", "ms200"
|
||||
|
||||
#define SIZEOF_NR_RLC_T_REASSEMBLY INT_LIST_SIZE(VALUES_NR_RLC_T_REASSEMBLY)
|
||||
|
||||
#define VALUES_NR_RLC_T_STATUS_PROHIBIT \
|
||||
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, \
|
||||
60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, \
|
||||
120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, \
|
||||
180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235, \
|
||||
240, 245, 250, 300, 350, 400, 450, 500, 800, 1000, 1200, 1600, \
|
||||
2000, 2400
|
||||
|
||||
#define VALUES_NR_RLC_T_STATUS_PROHIBIT_STR \
|
||||
"ms0", "ms5", "ms10", "ms15", "ms20", "ms25", "ms30", "ms35", "ms40", "ms45", "ms50", "ms55", \
|
||||
"ms60", "ms65", "ms70", "ms75", "ms80", "ms85", "ms90", "ms95", "ms100", "ms105", "ms110", "ms115", \
|
||||
"ms120", "ms125", "ms130", "ms135", "ms140", "ms145", "ms150", "ms155", "ms160", "ms165", "ms170", "ms175", \
|
||||
"ms180", "ms185", "ms190", "ms195", "ms200", "ms205", "ms210", "ms215", "ms220", "ms225", "ms230", "ms235", \
|
||||
"ms240", "ms245", "ms250", "ms300", "ms350", "ms400", "ms450", "ms500", "ms800", "ms1000", "ms1200", "ms1600", \
|
||||
"ms2000", "ms2400"
|
||||
|
||||
#define SIZEOF_NR_RLC_T_STATUS_PROHIBIT INT_LIST_SIZE(VALUES_NR_RLC_T_STATUS_PROHIBIT)
|
||||
|
||||
#define VALUES_NR_RLC_POLL_PDU \
|
||||
4, 8, 16, 32, 64, 128, 256, 512, 1024, \
|
||||
2048, 4096, 6144, 8192, 12288, 16384, 20480, 24576, 28672, \
|
||||
32768, 40960, 49152, 57344, 65536, -1 /* -1 means infinity */
|
||||
|
||||
#define VALUES_NR_RLC_POLL_PDU_STR \
|
||||
"p4", "p8", "p16", "p32", "p64", "p128", "p256", "p512", "p1024", \
|
||||
"p2048", "p4096", "p6144", "p8192", "p12288", "p16384", "p20480", "p24576", "p28672", \
|
||||
"p32768", "p40960", "p49152", "p57344", "p65536", "infinity"
|
||||
|
||||
#define SIZEOF_NR_RLC_POLL_PDU INT_LIST_SIZE(VALUES_NR_RLC_POLL_PDU)
|
||||
|
||||
#define VALUES_NR_RLC_POLL_BYTE \
|
||||
/* KB */ \
|
||||
1024 * 1, 1024 * 2, 1024 * 5, 1024 * 8, 1024 * 10, 1024 * 15, 1024 * 25, 1024 * 50, 1024 * 75, \
|
||||
1024 * 100, 1024 * 125, 1024 * 250, 1024 * 375, 1024 * 500, 1024 * 750, 1024 * 1000, 1024 * 1250, \
|
||||
1024 * 1500, 1024 * 2000, 1024 * 3000, 1024 * 4000, 1024 * 4500, 1024 * 5000, 1024 * 5500, \
|
||||
1024 * 6000, 1024 * 6500, 1024 * 7000, 1024 * 7500, \
|
||||
/* MB */ \
|
||||
1024 * 1024 * 8, 1024 * 1024 * 9, 1024 * 1024 * 10, 1024 * 1024 * 11, 1024 * 1024 * 12, \
|
||||
1024 * 1024 * 13, 1024 * 1024 * 14, 1024 * 1024 * 15, 1024 * 1024 * 16, 1024 * 1024 * 17, \
|
||||
1024 * 1024 * 18, 1024 * 1024 * 20, 1024 * 1024 * 25, 1024 * 1024 * 30, 1024 * 1024 * 40, \
|
||||
-1 /* -1 means infinity */
|
||||
|
||||
#define VALUES_NR_RLC_POLL_BYTE_STR \
|
||||
"kB1", "kB2", "kB5", "kB8", "kB10", "kB15", "kB25", "kB50", "kB75", \
|
||||
"kB100", "kB125", "kB250", "kB375", "kB500", "kB750", "kB1000", "kB1250", \
|
||||
"kB1500", "kB2000", "kB3000", "kB4000", "kB4500", "kB5000", "kB5500", \
|
||||
"kB6000", "kB6500", "kB7000", "kB7500", \
|
||||
"mB8", "mB9", "mB10", "mB11", "mB12", "mB13", "mB14", "mB15", \
|
||||
"mB16", "mB17", "mB18", "mB20", "mB25", "mB30", "mB40", \
|
||||
"infinity"
|
||||
|
||||
#define SIZEOF_NR_RLC_POLL_BYTE INT_LIST_SIZE(VALUES_NR_RLC_POLL_BYTE)
|
||||
|
||||
#define VALUES_NR_RLC_MAX_RETX_THRESHOLD \
|
||||
1, 2, 3, 4, 6, 8, 16, 32
|
||||
|
||||
#define VALUES_NR_RLC_MAX_RETX_THRESHOLD_STR \
|
||||
"t1", "t2", "t3", "t4", "t6", "t8", "t16", "t32"
|
||||
|
||||
#define SIZEOF_NR_RLC_MAX_RETX_THRESHOLD INT_LIST_SIZE(VALUES_NR_RLC_MAX_RETX_THRESHOLD)
|
||||
|
||||
#define VALUES_NR_RLC_SN_FIELD_LENGTH_AM \
|
||||
12, 18
|
||||
|
||||
#define VALUES_NR_RLC_SN_FIELD_LENGTH_AM_STR \
|
||||
"size12", "size18"
|
||||
|
||||
#define SIZEOF_NR_RLC_SN_FIELD_LENGTH_AM INT_LIST_SIZE(VALUES_NR_RLC_SN_FIELD_LENGTH_AM)
|
||||
|
||||
#define VALUES_NR_RLC_SN_FIELD_LENGTH_UM \
|
||||
6, 12
|
||||
|
||||
#define VALUES_NR_RLC_SN_FIELD_LENGTH_UM_STR \
|
||||
"size6", "size12"
|
||||
|
||||
#define SIZEOF_NR_RLC_SN_FIELD_LENGTH_UM INT_LIST_SIZE(VALUES_NR_RLC_SN_FIELD_LENGTH_UM)
|
||||
|
||||
/* configuration of NR RLC, coming from configuration file */
|
||||
typedef struct {
|
||||
struct {
|
||||
int t_poll_retransmit;
|
||||
int t_reassembly;
|
||||
int t_status_prohibit;
|
||||
int poll_pdu;
|
||||
int poll_byte;
|
||||
int max_retx_threshold;
|
||||
int sn_field_length;
|
||||
} srb;
|
||||
struct {
|
||||
int t_poll_retransmit;
|
||||
int t_reassembly;
|
||||
int t_status_prohibit;
|
||||
int poll_pdu;
|
||||
int poll_byte;
|
||||
int max_retx_threshold;
|
||||
int sn_field_length;
|
||||
} drb_am;
|
||||
struct {
|
||||
int t_reassembly;
|
||||
int sn_field_length;
|
||||
} drb_um;
|
||||
} nr_rlc_configuration_t;
|
||||
|
||||
#endif /* _NR_RLC_CONFIGURATION_H_ */
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
#include "asn1_msg.h"
|
||||
#include "../nr_rrc_proto.h"
|
||||
#include "LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h"
|
||||
|
||||
#include "openair3/SECU/key_nas_deriver.h"
|
||||
|
||||
@@ -143,6 +144,7 @@
|
||||
|
||||
#include "common/ran_context.h"
|
||||
#include "conversions.h"
|
||||
#include "ds/byte_array.h"
|
||||
|
||||
//#define XER_PRINT
|
||||
|
||||
@@ -273,7 +275,8 @@ int do_RRCReject(uint8_t *const buffer)
|
||||
NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
|
||||
int rb_id,
|
||||
e_NR_CipheringAlgorithm ciphering_algorithm,
|
||||
e_NR_SecurityConfig__keyToUse key_to_use)
|
||||
e_NR_SecurityConfig__keyToUse key_to_use,
|
||||
const nr_pdcp_configuration_t *pdcp_config)
|
||||
{
|
||||
NR_RadioBearerConfig_t *rbconfig = calloc(1, sizeof(*rbconfig));
|
||||
rbconfig->srb_ToAddModList = NULL;
|
||||
@@ -288,9 +291,9 @@ NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
|
||||
drb_ToAddMod->recoverPDCP = NULL;
|
||||
drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config));
|
||||
asn1cCalloc(drb_ToAddMod->pdcp_Config->drb, drb);
|
||||
asn1cCallocOne(drb->discardTimer, NR_PDCP_Config__drb__discardTimer_infinity);
|
||||
asn1cCallocOne(drb->pdcp_SN_SizeUL, NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits);
|
||||
asn1cCallocOne(drb->pdcp_SN_SizeDL, NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits);
|
||||
asn1cCallocOne(drb->discardTimer, encode_discard_timer(pdcp_config->drb.discard_timer));
|
||||
asn1cCallocOne(drb->pdcp_SN_SizeUL, encode_sn_size_ul(pdcp_config->drb.sn_size));
|
||||
asn1cCallocOne(drb->pdcp_SN_SizeDL, encode_sn_size_dl(pdcp_config->drb.sn_size));
|
||||
drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
|
||||
drb->headerCompression.choice.notUsed = 0;
|
||||
drb->integrityProtection = NULL;
|
||||
@@ -298,7 +301,7 @@ NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
|
||||
drb->outOfOrderDelivery = NULL;
|
||||
|
||||
drb_ToAddMod->pdcp_Config->moreThanOneRLC = NULL;
|
||||
asn1cCallocOne(drb_ToAddMod->pdcp_Config->t_Reordering, NR_PDCP_Config__t_Reordering_ms100);
|
||||
asn1cCallocOne(drb_ToAddMod->pdcp_Config->t_Reordering, encode_t_reordering(pdcp_config->drb.t_reordering));
|
||||
drb_ToAddMod->pdcp_Config->ext1 = NULL;
|
||||
|
||||
asn1cSeqAdd(&rbconfig->drb_ToAddModList->list,drb_ToAddMod);
|
||||
@@ -499,112 +502,108 @@ int do_NR_RRCRelease(uint8_t *buffer, size_t buffer_size, uint8_t Transaction_id
|
||||
return((enc_rval.encoded+7)/8);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int do_RRCReconfiguration(int rrc_ue_id,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size,
|
||||
uint8_t Transaction_id,
|
||||
NR_SRB_ToAddModList_t *SRB_configList,
|
||||
NR_DRB_ToAddModList_t *DRB_configList,
|
||||
NR_DRB_ToReleaseList_t *DRB_releaseList,
|
||||
NR_SecurityConfig_t *security_config,
|
||||
NR_MeasConfig_t *meas_config,
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList,
|
||||
NR_CellGroupConfig_t *cellGroupConfig)
|
||||
//------------------------------------------------------------------------------
|
||||
/** @brief Build RRCReconfiguration message (3GPP TS 38.331) */
|
||||
static NR_RRCReconfiguration_IEs_t *build_RRCReconfiguration_IEs(const nr_rrc_reconfig_param_t *params)
|
||||
{
|
||||
NR_DL_DCCH_Message_t dl_dcch_msg={0};
|
||||
asn_enc_rval_t enc_rval;
|
||||
NR_RRCReconfiguration_IEs_t *ie;
|
||||
NR_RRCReconfiguration_IEs_t *ie = calloc_or_fail(1, sizeof(*ie));
|
||||
|
||||
dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1;
|
||||
asn1cCalloc(dl_dcch_msg.message.choice.c1, c1);// = CALLOC(1, sizeof(struct NR_DL_DCCH_MessageType__c1));
|
||||
c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration;
|
||||
// radioBearerConfig
|
||||
if ((params->srb_config_list && params->srb_config_list->list.size)
|
||||
|| (params->drb_config_list && params->drb_config_list->list.size)) {
|
||||
ie->radioBearerConfig = calloc_or_fail(1, sizeof(*ie->radioBearerConfig));
|
||||
struct NR_RadioBearerConfig *cfg = ie->radioBearerConfig;
|
||||
cfg->srb_ToAddModList = params->srb_config_list;
|
||||
cfg->drb_ToAddModList = params->drb_config_list;
|
||||
cfg->securityConfig = params->security_config;
|
||||
cfg->srb3_ToRelease = NULL;
|
||||
cfg->drb_ToReleaseList = params->drb_release_list;
|
||||
}
|
||||
|
||||
asn1cCalloc(c1->choice.rrcReconfiguration, rrcReconf); // = calloc(1, sizeof(NR_RRCReconfiguration_t));
|
||||
rrcReconf->rrc_TransactionIdentifier = Transaction_id;
|
||||
rrcReconf->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration;
|
||||
/* measConfig */
|
||||
ie->measConfig = params->meas_config;
|
||||
|
||||
/******************** Radio Bearer Config ********************/
|
||||
/* Configure Security */
|
||||
// security_config = CALLOC(1, sizeof(NR_SecurityConfig_t));
|
||||
// security_config->securityAlgorithmConfig = CALLOC(1, sizeof(*ie->radioBearerConfig->securityConfig->securityAlgorithmConfig));
|
||||
// security_config->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0;
|
||||
// security_config->securityAlgorithmConfig->integrityProtAlgorithm = NULL;
|
||||
// security_config->keyToUse = CALLOC(1, sizeof(*ie->radioBearerConfig->securityConfig->keyToUse));
|
||||
// *security_config->keyToUse = NR_SecurityConfig__keyToUse_master;
|
||||
/* nonCriticalExtension, RRCReconfiguration-v1530-IEs */
|
||||
if (params->cell_group_config || params->num_nas_msg) {
|
||||
// Allocate memory for extension IE
|
||||
ie->nonCriticalExtension = calloc_or_fail(1, sizeof(*ie->nonCriticalExtension));
|
||||
}
|
||||
|
||||
ie = calloc(1, sizeof(NR_RRCReconfiguration_IEs_t));
|
||||
if ((SRB_configList && SRB_configList->list.size) ||
|
||||
(DRB_configList && DRB_configList->list.size)) {
|
||||
ie->radioBearerConfig = calloc(1, sizeof(NR_RadioBearerConfig_t));
|
||||
ie->radioBearerConfig->srb_ToAddModList = SRB_configList;
|
||||
ie->radioBearerConfig->drb_ToAddModList = DRB_configList;
|
||||
ie->radioBearerConfig->securityConfig = security_config;
|
||||
ie->radioBearerConfig->srb3_ToRelease = NULL;
|
||||
ie->radioBearerConfig->drb_ToReleaseList = DRB_releaseList;
|
||||
}
|
||||
|
||||
/******************** Meas Config ********************/
|
||||
// measConfig
|
||||
ie->measConfig = meas_config;
|
||||
// lateNonCriticalExtension
|
||||
ie->lateNonCriticalExtension = NULL;
|
||||
// nonCriticalExtension
|
||||
|
||||
if (cellGroupConfig || dedicatedNAS_MessageList) {
|
||||
ie->nonCriticalExtension = calloc(1, sizeof(NR_RRCReconfiguration_v1530_IEs_t));
|
||||
if (dedicatedNAS_MessageList)
|
||||
ie->nonCriticalExtension->dedicatedNAS_MessageList = dedicatedNAS_MessageList;
|
||||
}
|
||||
|
||||
if (cellGroupConfig != NULL) {
|
||||
uint8_t *buf = NULL;
|
||||
ssize_t len = uper_encode_to_new_buffer(&asn_DEF_NR_CellGroupConfig, NULL, cellGroupConfig, (void **)&buf);
|
||||
AssertFatal(len > 0, "ASN1 message encoding failed (%lu)!\n", len);
|
||||
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
|
||||
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig);
|
||||
// Configure Cell Group Config
|
||||
if (ie->nonCriticalExtension) {
|
||||
if (params->num_nas_msg) {
|
||||
asn1cCalloc(ie->nonCriticalExtension->dedicatedNAS_MessageList, list);
|
||||
/* dedicatedNAS-MessageList: The field is absent in case of reconfiguration with sync
|
||||
otherwise it is optionally present */
|
||||
for (int i = 0; i < params->num_nas_msg; i++) {
|
||||
asn1cSequenceAdd(list->list, NR_DedicatedNAS_Message_t, msg);
|
||||
OCTET_STRING_fromBuf(msg, (char *)params->dedicated_NAS_msg_list[i].buf, params->dedicated_NAS_msg_list[i].len);
|
||||
}
|
||||
ie->nonCriticalExtension->masterCellGroup = calloc(1,sizeof(OCTET_STRING_t));
|
||||
ie->nonCriticalExtension->masterCellGroup->buf = buf;
|
||||
ie->nonCriticalExtension->masterCellGroup->size = len;
|
||||
}
|
||||
|
||||
dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration = ie;
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
|
||||
xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg);
|
||||
/* masterCellGroup */
|
||||
if (params->cell_group_config) {
|
||||
// Encode in extension IE (Master cell group)
|
||||
uint8_t *buf = NULL;
|
||||
ssize_t len = uper_encode_to_new_buffer(&asn_DEF_NR_CellGroupConfig, NULL, params->cell_group_config, (void **)&buf);
|
||||
AssertFatal(len > 0, "ASN1 message encoding failed (%lu)!\n", len);
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
|
||||
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *)params->cell_group_config);
|
||||
}
|
||||
ie->nonCriticalExtension->masterCellGroup = calloc_or_fail(1, sizeof(*ie->nonCriticalExtension->masterCellGroup));
|
||||
*ie->nonCriticalExtension->masterCellGroup = (OCTET_STRING_t){.buf = buf, .size = len};
|
||||
}
|
||||
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message,
|
||||
NULL,
|
||||
(void *)&dl_dcch_msg,
|
||||
buffer,
|
||||
buffer_size);
|
||||
|
||||
AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
|
||||
// don't free what we did not allocate, so set fields with pointers to NULL
|
||||
// if memory comes from outside
|
||||
ie->measConfig = NULL;
|
||||
if (ie->radioBearerConfig) {
|
||||
ie->radioBearerConfig->srb_ToAddModList = NULL;
|
||||
ie->radioBearerConfig->drb_ToAddModList = NULL;
|
||||
ie->radioBearerConfig->securityConfig = NULL;
|
||||
ie->radioBearerConfig->srb3_ToRelease = NULL;
|
||||
ie->radioBearerConfig->drb_ToReleaseList = NULL;
|
||||
/* masterKeyUpdate */
|
||||
if (params->masterKeyUpdate) {
|
||||
ie->nonCriticalExtension->masterKeyUpdate = calloc_or_fail(1, sizeof(*ie->nonCriticalExtension->masterKeyUpdate));
|
||||
ie->nonCriticalExtension->masterKeyUpdate->keySetChangeIndicator = false;
|
||||
ie->nonCriticalExtension->masterKeyUpdate->nextHopChainingCount = params->nextHopChainingCount;
|
||||
}
|
||||
if (ie->nonCriticalExtension)
|
||||
ie->nonCriticalExtension->dedicatedNAS_MessageList = NULL;
|
||||
}
|
||||
|
||||
return ie;
|
||||
}
|
||||
|
||||
byte_array_t do_RRCReconfiguration(const nr_rrc_reconfig_param_t *params)
|
||||
{
|
||||
byte_array_t msg = {.buf = NULL, .len = 0};
|
||||
NR_RRCReconfiguration_IEs_t *ie = build_RRCReconfiguration_IEs(params);
|
||||
|
||||
NR_DL_DCCH_Message_t dl_dcch_msg = {0};
|
||||
dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1;
|
||||
|
||||
asn1cCalloc(dl_dcch_msg.message.choice.c1, c1);
|
||||
c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration;
|
||||
asn1cCalloc(c1->choice.rrcReconfiguration, rrcReconf);
|
||||
rrcReconf->rrc_TransactionIdentifier = params->transaction_id;
|
||||
rrcReconf->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration;
|
||||
rrcReconf->criticalExtensions.choice.rrcReconfiguration = ie;
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
|
||||
xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg);
|
||||
}
|
||||
|
||||
int val = uper_encode_to_new_buffer(&asn_DEF_NR_DL_DCCH_Message, NULL, &dl_dcch_msg, (void **)&msg.buf);
|
||||
if (val <= 0) {
|
||||
LOG_E(NR_RRC, "Failed to encode DL-DCCH message\n");
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_DL_DCCH_Message, &dl_dcch_msg);
|
||||
LOG_D(NR_RRC,
|
||||
"RRCReconfiguration for UE %d: Encoded %zd bits (%zd bytes)\n",
|
||||
rrc_ue_id,
|
||||
enc_rval.encoded,
|
||||
(enc_rval.encoded + 7) / 8);
|
||||
return msg;
|
||||
}
|
||||
msg.len = val;
|
||||
LOG_D(NR_RRC, "RRCReconfiguration: Encoded (%ld bytes)\n", msg.len);
|
||||
|
||||
return((enc_rval.encoded+7)/8);
|
||||
// Do not free what is not allocated in this context
|
||||
ie->measConfig = NULL;
|
||||
if (ie->radioBearerConfig) {
|
||||
ie->radioBearerConfig->securityConfig = NULL;
|
||||
ie->radioBearerConfig->drb_ToReleaseList = NULL;
|
||||
ie->radioBearerConfig->srb_ToAddModList = NULL;
|
||||
ie->radioBearerConfig->drb_ToAddModList = NULL;
|
||||
}
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_DL_DCCH_Message, &dl_dcch_msg);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_t fiveG_S_TMSI)
|
||||
|
||||
@@ -51,10 +51,25 @@
|
||||
#include "NR_SRB-ToAddModList.h"
|
||||
#include "NR_SecurityConfig.h"
|
||||
#include "ds/seq_arr.h"
|
||||
#include "ds/byte_array.h"
|
||||
#include "rrc_messages_types.h"
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList;
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h"
|
||||
struct asn_TYPE_descriptor_s;
|
||||
|
||||
typedef struct {
|
||||
uint8_t transaction_id;
|
||||
NR_SRB_ToAddModList_t *srb_config_list;
|
||||
NR_DRB_ToAddModList_t *drb_config_list;
|
||||
NR_DRB_ToReleaseList_t *drb_release_list;
|
||||
NR_SecurityConfig_t *security_config;
|
||||
NR_MeasConfig_t *meas_config;
|
||||
byte_array_t dedicated_NAS_msg_list[MAX_DRBS_PER_UE];
|
||||
int num_nas_msg;
|
||||
NR_CellGroupConfig_t *cell_group_config;
|
||||
bool masterKeyUpdate;
|
||||
int nextHopChainingCount;
|
||||
} nr_rrc_reconfig_param_t;
|
||||
|
||||
/*
|
||||
* The variant of the above function which dumps the BASIC-XER (XER_F_BASIC)
|
||||
* output into the chosen string buffer.
|
||||
@@ -72,7 +87,8 @@ int do_RRCReject(uint8_t *const buffer);
|
||||
NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
|
||||
int rb_id,
|
||||
e_NR_CipheringAlgorithm ciphering_algorithm,
|
||||
e_NR_SecurityConfig__keyToUse key_to_use);
|
||||
e_NR_SecurityConfig__keyToUse key_to_use,
|
||||
const nr_pdcp_configuration_t *pdcp_config);
|
||||
|
||||
int do_RRCSetup(uint8_t *const buffer,
|
||||
size_t buffer_size,
|
||||
@@ -91,17 +107,7 @@ int do_NR_SA_UECapabilityEnquiry(uint8_t *const buffer, const uint8_t Transactio
|
||||
|
||||
int do_NR_RRCRelease(uint8_t *buffer, size_t buffer_size, uint8_t Transaction_id);
|
||||
|
||||
int do_RRCReconfiguration(int rrc_ue_id,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size,
|
||||
uint8_t Transaction_id,
|
||||
NR_SRB_ToAddModList_t *SRB_configList,
|
||||
NR_DRB_ToAddModList_t *DRB_configList,
|
||||
NR_DRB_ToReleaseList_t *DRB_releaseList,
|
||||
NR_SecurityConfig_t *security_config,
|
||||
NR_MeasConfig_t *meas_config,
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList,
|
||||
NR_CellGroupConfig_t *cellGroupConfig);
|
||||
byte_array_t do_RRCReconfiguration(const nr_rrc_reconfig_param_t *params);
|
||||
|
||||
int do_RRCSetupComplete(uint8_t *buffer,
|
||||
size_t buffer_size,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
add_executable(test_asn1_msg test_asn1_msg.cpp)
|
||||
add_executable(test_asn1_msg
|
||||
test_asn1_msg.cpp
|
||||
${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c
|
||||
${OPENAIR2_DIR}/LAYER2/nr_rlc/asn1_utils.c)
|
||||
target_link_libraries(test_asn1_msg PRIVATE nr_rrc SECURITY minimal_lib GTest::gtest UTIL)
|
||||
add_dependencies(tests test_asn1_msg)
|
||||
add_test(NAME test_asn1_msg
|
||||
|
||||
@@ -20,14 +20,22 @@
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "openair2/RRC/NR/MESSAGES/asn1_msg.h"
|
||||
#include "common/ran_context.h"
|
||||
#include <stdbool.h>
|
||||
#include "common/utils/assertions.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "NR_DRB-ToAddMod.h"
|
||||
#include "NR_DRB-ToAddModList.h"
|
||||
#include "NR_SRB-ToAddModList.h"
|
||||
#include "ds/byte_array.h"
|
||||
RAN_CONTEXT_t RC;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(nr_asn1, rrc_reject)
|
||||
{
|
||||
@@ -77,6 +85,77 @@ TEST(nr_asn1, paging)
|
||||
EXPECT_GT(do_NR_Paging(0, buf, 0), 0);
|
||||
}
|
||||
|
||||
void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params)
|
||||
{
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MeasConfig, params.meas_config);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, params.drb_release_list);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, params.drb_config_list);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SRB_ToAddModList, params.srb_config_list);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SecurityConfig, params.security_config);
|
||||
for (int i = 0; i < params.num_nas_msg; i++)
|
||||
FREE_AND_ZERO_BYTE_ARRAY(params.dedicated_NAS_msg_list[i]);
|
||||
}
|
||||
|
||||
TEST(nr_asn1, rrc_reconfiguration)
|
||||
{
|
||||
// SRB Configuration
|
||||
NR_SRB_ToAddModList_t *srb_config_list = (NR_SRB_ToAddModList_t *)calloc_or_fail(1, sizeof(*srb_config_list));
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (i == 1 || i == 2) {
|
||||
NR_SRB_ToAddMod_t *srb = (NR_SRB_ToAddMod_t *)calloc_or_fail(1, sizeof(*srb));
|
||||
ASN_SEQUENCE_ADD(&srb_config_list->list, srb);
|
||||
srb->srb_Identity = i;
|
||||
if (i == 1 || i == 2) {
|
||||
srb->reestablishPDCP = (long *)calloc_or_fail(1, sizeof(*srb->reestablishPDCP));
|
||||
*srb->reestablishPDCP = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DRB Configuration
|
||||
NR_DRB_ToAddModList_t *drb_config_list = (NR_DRB_ToAddModList_t *)calloc_or_fail(1, sizeof(*drb_config_list));
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (i == 1 || i == 2) {
|
||||
NR_DRB_ToAddMod_t *drb = (NR_DRB_ToAddMod_t *)calloc_or_fail(1, sizeof(*drb));
|
||||
ASN_SEQUENCE_ADD(&drb_config_list->list, drb);
|
||||
drb->drb_Identity = i;
|
||||
drb->reestablishPDCP = (long *)calloc_or_fail(1, sizeof(*drb->reestablishPDCP));
|
||||
*drb->reestablishPDCP = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// nr_rrc_reconfig_param_t setup
|
||||
nr_rrc_reconfig_param_t params = {};
|
||||
params.srb_config_list = srb_config_list;
|
||||
params.drb_config_list = drb_config_list;
|
||||
params.num_nas_msg = 2;
|
||||
params.masterKeyUpdate = false;
|
||||
params.nextHopChainingCount = 1;
|
||||
|
||||
byte_array_t nas_pdu_1;
|
||||
nas_pdu_1.buf = (uint8_t *)malloc_or_fail(4);
|
||||
memcpy(nas_pdu_1.buf, "NAS1", 4);
|
||||
nas_pdu_1.len = 4;
|
||||
|
||||
byte_array_t nas_pdu_2;
|
||||
nas_pdu_2.buf = (uint8_t *)malloc_or_fail(4);
|
||||
memcpy(nas_pdu_2.buf, "NAS2", 4);
|
||||
nas_pdu_2.len = 4;
|
||||
|
||||
params.dedicated_NAS_msg_list[0] = nas_pdu_1;
|
||||
params.dedicated_NAS_msg_list[1] = nas_pdu_2;
|
||||
|
||||
byte_array_t msg = do_RRCReconfiguration(¶ms);
|
||||
|
||||
EXPECT_GT(msg.len, 0);
|
||||
EXPECT_NE(msg.buf, nullptr);
|
||||
|
||||
LOG_D(NR_RRC, "RRCReconfiguration: Encoded (%ld bytes)\n", msg.len);
|
||||
|
||||
free_byte_array(msg);
|
||||
free_RRCReconfiguration_params(params);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
logInit();
|
||||
|
||||
@@ -54,6 +54,8 @@
|
||||
#include "NR_UE-MRDC-Capability.h"
|
||||
#include "NR_UE-NR-Capability.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_configuration.h"
|
||||
|
||||
typedef enum {
|
||||
NR_RRC_OK=0,
|
||||
@@ -301,7 +303,7 @@ typedef struct {
|
||||
plmn_identity_t plmn;
|
||||
uint32_t tac;
|
||||
bool isIntraFrequencyNeighbour;
|
||||
} nr_neighbour_gnb_configuration_t;
|
||||
} nr_neighbour_cell_t;
|
||||
|
||||
typedef struct neighbour_cell_configuration_s {
|
||||
uint64_t nr_cell_id;
|
||||
@@ -383,6 +385,8 @@ typedef struct gNB_RRC_INST_s {
|
||||
RB_HEAD(rrc_cuup_tree, nr_rrc_cuup_container_t) cuups; // CU-UPs, indexed by assoc_id
|
||||
size_t num_cuups;
|
||||
|
||||
nr_pdcp_configuration_t pdcp_config;
|
||||
nr_rlc_configuration_t rlc_config;
|
||||
} gNB_RRC_INST;
|
||||
|
||||
#define UE_LOG_FMT "(cellID %lx, UE ID %d RNTI %04x)"
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
#include "NR_CG-Config.h"
|
||||
#include "NR_CG-ConfigInfo.h"
|
||||
#include "NR_RRCReconfiguration.h"
|
||||
#include "RRC/NR/MESSAGES/asn1_msg.h"
|
||||
|
||||
#define SRB1 1
|
||||
#define SRB2 2
|
||||
|
||||
void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_assoc_t assoc_id);
|
||||
void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp);
|
||||
@@ -112,6 +116,12 @@ void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc,
|
||||
int n_rel_drbs,
|
||||
const f1ap_drb_to_be_released_t *rel_drbs);
|
||||
|
||||
void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params);
|
||||
|
||||
byte_array_t rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, nr_rrc_reconfig_param_t params);
|
||||
|
||||
nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish);
|
||||
|
||||
pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession);
|
||||
f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param);
|
||||
void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration);
|
||||
|
||||
+176
-230
@@ -96,6 +96,7 @@
|
||||
#include "E1AP/lib/e1ap_interface_management.h"
|
||||
#include "NR_DL-DCCH-Message.h"
|
||||
#include "ds/byte_array.h"
|
||||
#include "alg/find.h"
|
||||
|
||||
#ifdef E2_AGENT
|
||||
#include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h"
|
||||
@@ -124,45 +125,47 @@ static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_i
|
||||
data->rrc->mac_rrc.ue_context_release_command(data->assoc_id, data->release_cmd);
|
||||
}
|
||||
|
||||
static void freeDRBlist(NR_DRB_ToAddModList_t *list)
|
||||
static bool eq_cell_id(const void *vval, const void *vit)
|
||||
{
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, list);
|
||||
return;
|
||||
const int *cell_id = (const int *)vval;
|
||||
const neighbour_cell_configuration_t *cell = (const neighbour_cell_configuration_t *)vit;
|
||||
return cell->nr_cell_id == *cell_id;
|
||||
}
|
||||
|
||||
const neighbour_cell_configuration_t *get_neighbour_config(int serving_cell_nr_cellid)
|
||||
const neighbour_cell_configuration_t *get_neighbour_cell_config(const gNB_RRC_INST *rrc, int cell_id)
|
||||
{
|
||||
const gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
seq_arr_t *neighbour_cell_configuration = rrc->neighbour_cell_configuration;
|
||||
if (!neighbour_cell_configuration)
|
||||
if (!rrc->neighbour_cell_configuration)
|
||||
return NULL;
|
||||
|
||||
for (int cellIdx = 0; cellIdx < neighbour_cell_configuration->size; cellIdx++) {
|
||||
neighbour_cell_configuration_t *neighbour_config =
|
||||
(neighbour_cell_configuration_t *)seq_arr_at(neighbour_cell_configuration, cellIdx);
|
||||
if (neighbour_config->nr_cell_id == serving_cell_nr_cellid)
|
||||
return neighbour_config;
|
||||
seq_arr_t *head = rrc->neighbour_cell_configuration;
|
||||
LOG_D(NR_RRC, "Number of neighbour cell configurations: %ld\n", head->size);
|
||||
elm_arr_t e = find_if(head, &cell_id, eq_cell_id);
|
||||
if (e.found) {
|
||||
const neighbour_cell_configuration_t *cell = (const neighbour_cell_configuration_t *)e.it;
|
||||
LOG_D(NR_RRC, "Found matching neighbour cell with Cell ID %ld\n", cell->nr_cell_id);
|
||||
return cell;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const nr_neighbour_gnb_configuration_t *get_neighbour_cell_information(int serving_cell_nr_cellid, int neighbour_cell_phy_id)
|
||||
static bool eq_pci(const void *vval, const void *vit)
|
||||
{
|
||||
const gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
seq_arr_t *neighbour_cell_configuration = rrc->neighbour_cell_configuration;
|
||||
for (int cellIdx = 0; cellIdx < neighbour_cell_configuration->size; cellIdx++) {
|
||||
neighbour_cell_configuration_t *neighbour_config =
|
||||
(neighbour_cell_configuration_t *)seq_arr_at(neighbour_cell_configuration, cellIdx);
|
||||
if (!neighbour_config)
|
||||
continue;
|
||||
const int *pci = (const int *)vval;
|
||||
const nr_neighbour_cell_t *neighbour = (const nr_neighbour_cell_t *)vit;
|
||||
return neighbour->physicalCellId == *pci;
|
||||
}
|
||||
|
||||
for (int neighbourIdx = 0; neighbourIdx < neighbour_config->neighbour_cells->size; neighbourIdx++) {
|
||||
nr_neighbour_gnb_configuration_t *neighbour =
|
||||
(nr_neighbour_gnb_configuration_t *)seq_arr_at(neighbour_config->neighbour_cells, neighbourIdx);
|
||||
if (neighbour != NULL && neighbour->physicalCellId == neighbour_cell_phy_id)
|
||||
return neighbour;
|
||||
}
|
||||
const nr_neighbour_cell_t *get_neighbour_cell_by_pci(const neighbour_cell_configuration_t *cell, int pci)
|
||||
{
|
||||
seq_arr_t *head = cell->neighbour_cells;
|
||||
DevAssert(head != NULL);
|
||||
LOG_D(NR_RRC, "Number of neighbour cells: %ld\n", head->size);
|
||||
elm_arr_t e = find_if(head, &pci, eq_pci);
|
||||
if (e.found) {
|
||||
const nr_neighbour_cell_t *neighbour = (const nr_neighbour_cell_t *)e.it;
|
||||
LOG_D(NR_RRC, "Found matching neighbour cell with PCI %d and Cell ID %ld\n", neighbour->physicalCellId, neighbour->nrcell_id);
|
||||
return neighbour;
|
||||
}
|
||||
LOG_E(NR_RRC, "No matching neighbour cell found for Physical Cell ID: %d\n", pci);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -267,12 +270,17 @@ unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create srb-ToAddModList for RRCSetup and RRCReconfiguration messages
|
||||
*/
|
||||
static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish)
|
||||
/** @brief Create srb-ToAddModList for RRCSetup and RRCReconfiguration messages
|
||||
* @param reestablish bitmap to indicates whether PDCP should be re-established
|
||||
* for the SRB1 and/or SRB2. For convenience the bitmap is 0-based, with index 1
|
||||
* corresponding to SRB1, index 2 to SRB2. 3GPP TS 38.331 RadioBearerConfig
|
||||
* specifies that PDCP shall be re-established whenever the security key used
|
||||
* for the radio bearer changes, with some expections for SRB1 (i.e. when resuming
|
||||
* an RRC connection, or at the first reconfiguration after RRC connection
|
||||
* reestablishment in NR, do not re-establish PDCP) */
|
||||
static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish)
|
||||
{
|
||||
if (!ue->Srb[1].Active) {
|
||||
if (!ue->Srb[SRB1].Active) {
|
||||
LOG_E(NR_RRC, "Call SRB list while SRB1 doesn't exist\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -281,9 +289,11 @@ static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish)
|
||||
if (ue->Srb[i].Active) {
|
||||
asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb);
|
||||
srb->srb_Identity = i;
|
||||
/* Set reestablishPDCP only for SRB2 */
|
||||
if (reestablish && i == 2) {
|
||||
/* Based on the bitmap, set reestablishPDCP for SRB1 and SRB2 */
|
||||
if ((i == SRB1 || i == SRB2) && (reestablish & (1 << i))) {
|
||||
asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true);
|
||||
} else {
|
||||
DevAssert(!(reestablish & (1 << i)));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
@@ -312,12 +322,7 @@ static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish)
|
||||
|
||||
static void freeSRBlist(NR_SRB_ToAddModList_t *l)
|
||||
{
|
||||
if (l) {
|
||||
for (int i = 0; i < l->list.count; i++)
|
||||
free(l->list.array[i]);
|
||||
free(l);
|
||||
} else
|
||||
LOG_E(NR_RRC, "Call free SRB list on NULL pointer\n");
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SRB_ToAddModList, l);
|
||||
}
|
||||
|
||||
static void activate_srb(gNB_RRC_UE_t *UE, int srb_id)
|
||||
@@ -542,15 +547,20 @@ static NR_ReportConfigToAddMod_t *prepare_a3_event_report(const nr_a3_event_t *a
|
||||
return rc_A3;
|
||||
}
|
||||
|
||||
static int rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc,
|
||||
gNB_RRC_UE_t *UE,
|
||||
uint8_t xid,
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *nas_messages,
|
||||
uint8_t *buf,
|
||||
int max_len,
|
||||
bool reestablish)
|
||||
void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params)
|
||||
{
|
||||
NR_CellGroupConfig_t *cellGroupConfig = UE->masterCellGroup;
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, params.drb_release_list);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, params.drb_config_list);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SRB_ToAddModList, params.srb_config_list);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SecurityConfig, params.security_config);
|
||||
for (int i = 0; i < params.num_nas_msg; i++)
|
||||
FREE_AND_ZERO_BYTE_ARRAY(params.dedicated_NAS_msg_list[i]);
|
||||
}
|
||||
|
||||
/** @brief Prepare the instance of RRCReconfigurationParams to be pass to RRC encoding */
|
||||
nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish)
|
||||
{
|
||||
uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id);
|
||||
nr_rrc_du_container_t *du = get_du_for_ue(rrc, UE->rrc_ue_id);
|
||||
DevAssert(du != NULL);
|
||||
f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info;
|
||||
@@ -564,7 +574,7 @@ static int rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc,
|
||||
int band = get_dl_band(cell_info);
|
||||
const NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming;
|
||||
const NR_MeasTiming_t *mt = mtlist->list.array[0];
|
||||
const neighbour_cell_configuration_t *neighbour_config = get_neighbour_config(cell_info->nr_cellid);
|
||||
const neighbour_cell_configuration_t *neighbour_config = get_neighbour_cell_config(rrc, cell_info->nr_cellid);
|
||||
seq_arr_t *neighbour_cells = NULL;
|
||||
if (neighbour_config)
|
||||
neighbour_cells = neighbour_config->neighbour_cells;
|
||||
@@ -583,7 +593,7 @@ static int rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc,
|
||||
LOG_D(NR_RRC, "HO LOG: Preparing A3 Event Measurement Configuration!\n");
|
||||
bool is_default_a3_added = false;
|
||||
for (int i = 0; i < neighbour_cells->size; i++) {
|
||||
nr_neighbour_gnb_configuration_t *neighbourCell = (nr_neighbour_gnb_configuration_t *)seq_arr_at(neighbour_cells, i);
|
||||
nr_neighbour_cell_t *neighbourCell = (nr_neighbour_cell_t *)seq_arr_at(neighbour_cells, i);
|
||||
if (!neighbourCell->isIntraFrequencyNeighbour)
|
||||
continue;
|
||||
seq_arr_push_back(pci_seq, &neighbourCell->physicalCellId, sizeof(int));
|
||||
@@ -608,93 +618,91 @@ static int rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc,
|
||||
|
||||
UE->measConfig = measconfig;
|
||||
|
||||
NR_SRB_ToAddModList_t *SRBs = createSRBlist(UE, reestablish);
|
||||
NR_DRB_ToAddModList_t *DRBs = createDRBlist(UE, reestablish);
|
||||
// Re-establish PDCP for SRB2 only
|
||||
NR_SRB_ToAddModList_t *SRBs = createSRBlist(UE, srb_reest_bitmap);
|
||||
NR_DRB_ToAddModList_t *DRBs = createDRBlist(UE, drb_reestablish);
|
||||
|
||||
int size = do_RRCReconfiguration(UE->rrc_ue_id,
|
||||
buf,
|
||||
max_len,
|
||||
xid,
|
||||
SRBs,
|
||||
DRBs,
|
||||
UE->DRB_ReleaseList,
|
||||
NULL,
|
||||
measconfig,
|
||||
nas_messages,
|
||||
cellGroupConfig);
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buf, size, "[MSG] RRC Reconfiguration\n");
|
||||
freeSRBlist(SRBs);
|
||||
freeDRBlist(DRBs);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, UE->DRB_ReleaseList);
|
||||
UE->DRB_ReleaseList = NULL;
|
||||
nr_rrc_reconfig_param_t params = {.cell_group_config = UE->masterCellGroup,
|
||||
.transaction_id = xid,
|
||||
.drb_config_list = DRBs,
|
||||
.drb_release_list = UE->DRB_ReleaseList,
|
||||
.meas_config = UE->measConfig,
|
||||
.srb_config_list = SRBs};
|
||||
UE->DRB_ReleaseList = NULL; // pointer transferred to params
|
||||
|
||||
return size;
|
||||
for (int i = 0; i < UE->nb_of_pdusessions; i++) {
|
||||
if (UE->pduSession[i].param.nas_pdu.len > 0) {
|
||||
params.dedicated_NAS_msg_list[params.num_nas_msg++] = UE->pduSession[i].param.nas_pdu;
|
||||
UE->pduSession[i].param.nas_pdu.buf = NULL;
|
||||
UE->pduSession[i].param.nas_pdu.len = 0;
|
||||
LOG_D(NR_RRC, "Transfer NAS info with size %ld (pdusession idx %d) to RRCReconfiguration params\n", UE->pduSession[i].param.nas_pdu.len, i);
|
||||
}
|
||||
}
|
||||
if (UE->nas_pdu.len > 0) {
|
||||
params.dedicated_NAS_msg_list[params.num_nas_msg++] = UE->nas_pdu;
|
||||
UE->nas_pdu.buf = NULL;
|
||||
UE->nas_pdu.len = 0;
|
||||
LOG_D(NR_RRC, "Transfer NAS info with size %ld to RRCReconfiguration params\n", UE->nas_pdu.len);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
byte_array_t rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, nr_rrc_reconfig_param_t params)
|
||||
{
|
||||
byte_array_t msg = do_RRCReconfiguration(¶ms);
|
||||
if (msg.len <= 0) {
|
||||
LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", UE->rrc_ue_id);
|
||||
return msg;
|
||||
}
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, msg.buf, msg.len, "[MSG] RRC Reconfiguration\n");
|
||||
return msg;
|
||||
}
|
||||
|
||||
static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p)
|
||||
{
|
||||
uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id);
|
||||
ue_p->xids[xid] = RRC_PDUSESSION_ESTABLISH;
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = CALLOC(1, sizeof(*dedicatedNAS_MessageList));
|
||||
/* do not re-establish PDCP for any bearer */
|
||||
nr_rrc_reconfig_param_t params = get_RRCReconfiguration_params(rrc, ue_p, 0, false);
|
||||
ue_p->xids[params.transaction_id] = RRC_PDUSESSION_ESTABLISH;
|
||||
byte_array_t msg = rrc_gNB_encode_RRCReconfiguration(rrc, ue_p, params);
|
||||
if (msg.len <= 0) {
|
||||
LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", ue_p->rrc_ue_id);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
|
||||
if (ue_p->pduSession[i].param.nas_pdu.buf != NULL) {
|
||||
asn1cSequenceAdd(dedicatedNAS_MessageList->list, NR_DedicatedNAS_Message_t, msg);
|
||||
OCTET_STRING_fromBuf(msg, (char *)ue_p->pduSession[i].param.nas_pdu.buf, ue_p->pduSession[i].param.nas_pdu.len);
|
||||
|
||||
LOG_D(NR_RRC, "add NAS info with size %ld (pdusession idx %d)\n", ue_p->pduSession[i].param.nas_pdu.len, i);
|
||||
ue_p->pduSession[i].xid = xid;
|
||||
ue_p->pduSession[i].xid = params.transaction_id;
|
||||
}
|
||||
if (ue_p->pduSession[i].status < PDU_SESSION_STATUS_ESTABLISHED) {
|
||||
ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ue_p->nas_pdu.len) {
|
||||
asn1cSequenceAdd(dedicatedNAS_MessageList->list, NR_DedicatedNAS_Message_t, msg);
|
||||
OCTET_STRING_fromBuf(msg, (char *)ue_p->nas_pdu.buf, ue_p->nas_pdu.len);
|
||||
}
|
||||
|
||||
/* If list is empty free the list and reset the address */
|
||||
if (dedicatedNAS_MessageList->list.count == 0) {
|
||||
free(dedicatedNAS_MessageList);
|
||||
dedicatedNAS_MessageList = NULL;
|
||||
}
|
||||
|
||||
/* Free all NAS PDUs */
|
||||
for (int i = 0; i < ue_p->nb_of_pdusessions; i++)
|
||||
FREE_AND_ZERO_BYTE_ARRAY(ue_p->pduSession[i].param.nas_pdu);
|
||||
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE] = {0};
|
||||
// TODO refactor dedicatedNAS_MessageList
|
||||
int size = rrc_gNB_encode_RRCReconfiguration(rrc, ue_p, xid, dedicatedNAS_MessageList, buffer, sizeof(buffer), false);
|
||||
DevAssert(size > 0 && size <= sizeof(buffer));
|
||||
|
||||
LOG_UE_DL_EVENT(ue_p, "Generate RRCReconfiguration (bytes %d, xid %d)\n", size, xid);
|
||||
LOG_UE_DL_EVENT(ue_p, "Generate RRCReconfiguration (bytes %ld, xid %d)\n", msg.len, params.transaction_id);
|
||||
const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration;
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, buffer, size);
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, msg.buf, msg.len);
|
||||
free_RRCReconfiguration_params(params);
|
||||
free_byte_array(msg);
|
||||
}
|
||||
|
||||
void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p)
|
||||
{
|
||||
int qos_flow_index = 0;
|
||||
uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id);
|
||||
ue_p->xids[xid] = RRC_PDUSESSION_MODIFY;
|
||||
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList =
|
||||
CALLOC(1, sizeof(*dedicatedNAS_MessageList));
|
||||
nr_rrc_reconfig_param_t params = get_RRCReconfiguration_params(rrc, ue_p, 0, false);
|
||||
ue_p->xids[params.transaction_id] = RRC_PDUSESSION_MODIFY;
|
||||
|
||||
for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
|
||||
rrc_pdu_session_param_t *session = &ue_p->pduSession[i];
|
||||
// bypass the new and already configured pdu sessions
|
||||
if (session->status >= PDU_SESSION_STATUS_DONE) {
|
||||
session->xid = xid;
|
||||
session->xid = params.transaction_id;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (session->cause.type != NGAP_CAUSE_NOTHING) {
|
||||
// set xid of failure pdu session
|
||||
session->xid = xid;
|
||||
session->xid = params.transaction_id;
|
||||
session->status = PDU_SESSION_STATUS_FAILED;
|
||||
continue;
|
||||
}
|
||||
@@ -709,7 +717,7 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
|
||||
|
||||
if (j == MAX_DRBS_PER_UE) {
|
||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_unspecified};
|
||||
session->xid = xid;
|
||||
session->xid = params.transaction_id;
|
||||
session->status = PDU_SESSION_STATUS_FAILED;
|
||||
session->cause = cause;
|
||||
continue;
|
||||
@@ -734,7 +742,7 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
|
||||
LOG_E(NR_RRC, "not supported 5qi %lu\n", session->param.qos[qos_flow_index].fiveQI);
|
||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_not_supported_5QI_value};
|
||||
session->status = PDU_SESSION_STATUS_FAILED;
|
||||
session->xid = xid;
|
||||
session->xid = params.transaction_id;
|
||||
session->cause = cause;
|
||||
continue;
|
||||
}
|
||||
@@ -742,44 +750,20 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
|
||||
}
|
||||
|
||||
session->status = PDU_SESSION_STATUS_DONE;
|
||||
session->xid = xid;
|
||||
|
||||
if (session->param.nas_pdu.buf != NULL) {
|
||||
asn1cSequenceAdd(dedicatedNAS_MessageList->list,NR_DedicatedNAS_Message_t, dedicatedNAS_Message);
|
||||
OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)session->param.nas_pdu.buf, session->param.nas_pdu.len);
|
||||
LOG_I(NR_RRC, "add NAS info with size %ld (pdusession id %d)\n", session->param.nas_pdu.len, session->param.pdusession_id);
|
||||
}
|
||||
session->xid = params.transaction_id;
|
||||
}
|
||||
|
||||
/* If list is empty free the list and reset the address */
|
||||
if (dedicatedNAS_MessageList->list.count == 0) {
|
||||
free(dedicatedNAS_MessageList);
|
||||
dedicatedNAS_MessageList = NULL;
|
||||
byte_array_t msg = do_RRCReconfiguration(¶ms);
|
||||
if (msg.len <= 0) {
|
||||
LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", ue_p->rrc_ue_id);
|
||||
return;
|
||||
}
|
||||
|
||||
NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false);
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE];
|
||||
int size = do_RRCReconfiguration(ue_p->rrc_ue_id,
|
||||
buffer,
|
||||
NR_RRC_BUF_SIZE,
|
||||
xid,
|
||||
NULL,
|
||||
DRBs,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
dedicatedNAS_MessageList,
|
||||
NULL);
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n");
|
||||
freeDRBlist(DRBs);
|
||||
|
||||
/* Free all NAS PDUs */
|
||||
for (int i = 0; i < ue_p->nb_of_pdusessions; i++)
|
||||
FREE_AND_ZERO_BYTE_ARRAY(ue_p->pduSession[i].param.nas_pdu);
|
||||
|
||||
LOG_I(NR_RRC, "UE %d: Generate RRCReconfiguration (bytes %d)\n", ue_p->rrc_ue_id, size);
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, msg.buf, msg.len, "[MSG] RRC Reconfiguration\n");
|
||||
LOG_I(NR_RRC, "UE %d: Generate RRCReconfiguration (bytes %ld)\n", ue_p->rrc_ue_id, msg.len);
|
||||
const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration;
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, buffer, size);
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, msg.buf, msg.len);
|
||||
free_RRCReconfiguration_params(params);
|
||||
free_byte_array(msg);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -799,40 +783,22 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc,
|
||||
}
|
||||
}
|
||||
|
||||
/* If list is empty free the list and reset the address */
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = NULL;
|
||||
nr_rrc_reconfig_param_t params = {.drb_release_list = DRB_Release_configList2, .transaction_id = xid};
|
||||
if (nas_length > 0) {
|
||||
dedicatedNAS_MessageList = CALLOC(1, sizeof(*dedicatedNAS_MessageList));
|
||||
asn1cSequenceAdd(dedicatedNAS_MessageList->list, NR_DedicatedNAS_Message_t, dedicatedNAS_Message);
|
||||
OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)nas_buffer, nas_length);
|
||||
LOG_I(NR_RRC,"add NAS info with size %d\n", nas_length);
|
||||
} else {
|
||||
LOG_W(NR_RRC,"dedlicated NAS list is empty\n");
|
||||
params.dedicated_NAS_msg_list[params.num_nas_msg].buf = nas_buffer;
|
||||
params.dedicated_NAS_msg_list[params.num_nas_msg++].len = nas_length;
|
||||
}
|
||||
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE] = {0};
|
||||
int size = do_RRCReconfiguration(ue_p->rrc_ue_id,
|
||||
buffer,
|
||||
NR_RRC_BUF_SIZE,
|
||||
xid,
|
||||
NULL,
|
||||
NULL,
|
||||
DRB_Release_configList2,
|
||||
NULL,
|
||||
NULL,
|
||||
dedicatedNAS_MessageList,
|
||||
NULL);
|
||||
LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, "[MSG] RRC Reconfiguration\n");
|
||||
|
||||
/* Free all NAS PDUs */
|
||||
if (nas_length > 0) {
|
||||
/* Free the NAS PDU buffer and invalidate it */
|
||||
free(nas_buffer);
|
||||
byte_array_t msg = do_RRCReconfiguration(¶ms);
|
||||
if (msg.len <= 0) {
|
||||
LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", ue_p->rrc_ue_id);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_I(NR_RRC, "UE %d: Generate NR_RRCReconfiguration (bytes %d)\n", ue_p->rrc_ue_id, size);
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, msg.buf, msg.len, "[MSG] RRC Reconfiguration\n");
|
||||
LOG_I(NR_RRC, "UE %d: Generate NR_RRCReconfiguration (bytes %ld)\n", ue_p->rrc_ue_id, msg.len);
|
||||
const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration;
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, buffer, size);
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, msg.buf, msg.len);
|
||||
free_RRCReconfiguration_params(params);
|
||||
free_byte_array(msg);
|
||||
}
|
||||
|
||||
static void fill_security_info(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, security_information_t *secInfo)
|
||||
@@ -1065,39 +1031,35 @@ static void rrc_gNB_process_RRCReestablishmentComplete(gNB_RRC_INST *rrc, gNB_RR
|
||||
/* PDCP Reestablishment of DRBs according to 5.3.5.6.5 of 3GPP TS 38.331 (over E1) */
|
||||
cuup_notify_reestablishment(rrc, ue_p);
|
||||
|
||||
/* Create srb-ToAddModList */
|
||||
NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, true);
|
||||
/* Create srb-ToAddModList, 3GPP TS 38.331 RadioBearerConfig:
|
||||
* do not re-establish PDCP for SRB1, when resuming an RRC connection,
|
||||
* or at the first reconfiguration after RRC connection reestablishment in NR */
|
||||
NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, 1 << SRB2); // Re-establish PDCP for SRB2 only
|
||||
/* Create drb-ToAddModList */
|
||||
NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, true);
|
||||
|
||||
uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id);
|
||||
ue_p->xids[new_xid] = RRC_REESTABLISH_COMPLETE;
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE] = {0};
|
||||
int size = do_RRCReconfiguration(ue_p->rrc_ue_id,
|
||||
buffer,
|
||||
NR_RRC_BUF_SIZE,
|
||||
new_xid,
|
||||
SRBs,
|
||||
DRBs,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, // MeasObj_list,
|
||||
NULL,
|
||||
cellGroupConfig);
|
||||
freeSRBlist(SRBs);
|
||||
freeDRBlist(DRBs);
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n");
|
||||
|
||||
AssertFatal(size > 0, "cannot encode RRC Reconfiguration\n");
|
||||
nr_rrc_reconfig_param_t params = {.cell_group_config = cellGroupConfig,
|
||||
.drb_config_list = DRBs,
|
||||
.srb_config_list = SRBs,
|
||||
.transaction_id = new_xid};
|
||||
byte_array_t msg = do_RRCReconfiguration(¶ms);
|
||||
if (msg.len <= 0) {
|
||||
LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", ue_p->rrc_ue_id);
|
||||
return;
|
||||
}
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, msg.buf, msg.len, "[MSG] RRC Reconfiguration\n");
|
||||
LOG_I(NR_RRC,
|
||||
"UE %d RNTI %04x: Generate NR_RRCReconfiguration after reestablishment complete (bytes %d)\n",
|
||||
"UE %d RNTI %04x: Generate NR_RRCReconfiguration after reestablishment complete (bytes %ld)\n",
|
||||
ue_p->rrc_ue_id,
|
||||
ue_p->rnti,
|
||||
size);
|
||||
msg.len);
|
||||
const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration;
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, buffer, size);
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, msg.buf, msg.len);
|
||||
free_RRCReconfiguration_params(params);
|
||||
free_byte_array(msg);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int nr_rrc_reconfiguration_req(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p, const int dl_bwp_id, const int ul_bwp_id)
|
||||
{
|
||||
@@ -1114,22 +1076,16 @@ int nr_rrc_reconfiguration_req(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p, const int
|
||||
*masterCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = ul_bwp_id;
|
||||
}
|
||||
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE];
|
||||
int size = do_RRCReconfiguration(ue_p->rrc_ue_id,
|
||||
buffer,
|
||||
NR_RRC_BUF_SIZE,
|
||||
xid,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
masterCellGroup);
|
||||
|
||||
nr_rrc_reconfig_param_t params = {.cell_group_config = masterCellGroup, .transaction_id = xid};
|
||||
byte_array_t msg = do_RRCReconfiguration(¶ms);
|
||||
if (msg.len <= 0) {
|
||||
LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", ue_p->rrc_ue_id);
|
||||
return -1;
|
||||
}
|
||||
const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration;
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, buffer, size);
|
||||
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, msg.buf, msg.len);
|
||||
free_byte_array(msg);
|
||||
free_RRCReconfiguration_params(params);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1391,7 +1347,7 @@ static void process_Event_Based_Measurement_Report(gNB_RRC_INST *rrc,
|
||||
|
||||
int servingCellRSRP = 0;
|
||||
int neighbourCellRSRP = 0;
|
||||
int servingCellId = -1;
|
||||
int scell_pci = -1;
|
||||
|
||||
switch (event_triggered->eventId.present) {
|
||||
case NR_EventTriggerConfig__eventId_PR_eventA2:
|
||||
@@ -1408,7 +1364,7 @@ static void process_Event_Based_Measurement_Report(gNB_RRC_INST *rrc,
|
||||
|
||||
for (int serving_cell_idx = 0; serving_cell_idx < measResults->measResultServingMOList.list.count; serving_cell_idx++) {
|
||||
const NR_MeasResultServMO_t *meas_result_serv_MO = measResults->measResultServingMOList.list.array[serving_cell_idx];
|
||||
servingCellId = *(meas_result_serv_MO->measResultServingCell.physCellId);
|
||||
scell_pci = *(meas_result_serv_MO->measResultServingCell.physCellId);
|
||||
if (meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsSSB_Cell) {
|
||||
servingCellRSRP = *(meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsSSB_Cell->rsrp) - 157;
|
||||
} else {
|
||||
@@ -1426,7 +1382,7 @@ static void process_Event_Based_Measurement_Report(gNB_RRC_INST *rrc,
|
||||
const NR_MeasResultListNR_t *measResultListNR = measResults->measResultNeighCells->choice.measResultListNR;
|
||||
for (int neigh_meas_idx = 0; neigh_meas_idx < measResultListNR->list.count; neigh_meas_idx++) {
|
||||
const NR_MeasResultNR_t *meas_result_neigh_cell = (measResultListNR->list.array[neigh_meas_idx]);
|
||||
const int neighbourCellId = *(meas_result_neigh_cell->physCellId);
|
||||
const int neighbour_pci = *(meas_result_neigh_cell->physCellId);
|
||||
|
||||
// TS 138 133 Table 10.1.6.1-1: SS-RSRP and CSI-RSRP measurement report mapping
|
||||
const struct NR_MeasResultNR__measResult__cellResults *cellResults = &(meas_result_neigh_cell->measResult.cellResults);
|
||||
@@ -1439,13 +1395,13 @@ static void process_Event_Based_Measurement_Report(gNB_RRC_INST *rrc,
|
||||
|
||||
LOG_I(NR_RRC,
|
||||
"HO LOG: Measurement Report for the neighbour %d with RSRP: %d\n",
|
||||
neighbourCellId,
|
||||
neighbour_pci,
|
||||
neighbourCellRSRP);
|
||||
|
||||
const f1ap_served_cell_info_t *neigh_cell = get_cell_information_by_phycellId(neighbourCellId);
|
||||
const f1ap_served_cell_info_t *serving_cell = get_cell_information_by_phycellId(servingCellId);
|
||||
const nr_neighbour_gnb_configuration_t *neighbour =
|
||||
get_neighbour_cell_information(serving_cell->nr_cellid, neighbourCellId);
|
||||
const f1ap_served_cell_info_t *neigh_cell = get_cell_information_by_phycellId(neighbour_pci);
|
||||
const f1ap_served_cell_info_t *serving_cell = get_cell_information_by_phycellId(scell_pci);
|
||||
const neighbour_cell_configuration_t *cell = get_neighbour_cell_config(rrc, serving_cell->nr_cellid);
|
||||
const nr_neighbour_cell_t *neighbour = get_neighbour_cell_by_pci(cell, neighbour_pci);
|
||||
// CU does not have f1 connection with neighbour cell context. So check does serving cell has this phyCellId as a
|
||||
// neighbour.
|
||||
if (!neigh_cell && neighbour) {
|
||||
@@ -1465,7 +1421,7 @@ static void process_Event_Based_Measurement_Report(gNB_RRC_INST *rrc,
|
||||
nr_rrc_du_container_t *target_du = get_du_by_cell_id(rrc, neigh_cell->nr_cellid);
|
||||
nr_rrc_trigger_f1_ho(rrc, ue, source_du, target_du);
|
||||
} else {
|
||||
LOG_W(NR_RRC, "UE %d: received A3 event for stronger neighbor PCI %d, but no such neighbour in configuration\n", ue->rrc_ue_id, neighbourCellId);
|
||||
LOG_W(NR_RRC, "UE %d: received A3 event for stronger neighbor PCI %d, but no such neighbour in configuration\n", ue->rrc_ue_id, neighbour_pci);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2180,17 +2136,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance
|
||||
DevAssert(resp->crnti != NULL);
|
||||
UE->ho_context->target->du_ue_id = resp->gNB_DU_ue_id;
|
||||
UE->ho_context->target->new_rnti = *resp->crnti;
|
||||
|
||||
uint8_t xid = rrc_gNB_get_next_transaction_identifier(0);
|
||||
UE->xids[xid] = RRC_DEDICATED_RECONF;
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE] = {0};
|
||||
int size = rrc_gNB_encode_RRCReconfiguration(rrc, UE, xid, NULL, buffer, sizeof(buffer), true);
|
||||
DevAssert(size > 0 && size <= sizeof(buffer));
|
||||
|
||||
// TODO N2 38.413 sec 9.3.1.21: admitted PDU sessions (in UE), Target to
|
||||
// Source Transparent Container (9.3.1.21) which encodes the RRC
|
||||
// reconfiguration above
|
||||
UE->ho_context->target->ho_req_ack(rrc, UE, buffer, size);
|
||||
UE->ho_context->target->ho_req_ack(rrc, UE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -397,7 +397,8 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
|
||||
pduSession,
|
||||
rrc->configuration.enable_sdap,
|
||||
rrc->security.do_drb_integrity,
|
||||
rrc->security.do_drb_ciphering);
|
||||
rrc->security.do_drb_ciphering,
|
||||
&rrc->pdcp_config);
|
||||
|
||||
pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding
|
||||
for (int j=0; j < pdu->numDRB2Setup; j++) {
|
||||
@@ -940,7 +941,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
|
||||
return;
|
||||
}
|
||||
|
||||
if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, msg->pdusession_setup_params, msg->ueAggMaxBitRateDownlink)) {
|
||||
if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, msg->pdusession_setup_params, msg->ueAggMaxBitRate.br_dl)) {
|
||||
// Reject PDU Session Resource setup if there's no CU-UP associated
|
||||
LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in PDU Session Resource Setup Response\n", UE->rrc_ue_id);
|
||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE};
|
||||
|
||||
@@ -202,7 +202,7 @@ const struct f1ap_served_cell_info_t *get_cell_information_by_phycellId(int phyC
|
||||
static void is_intra_frequency_neighbour(void *ssb_arfcn, void *neighbour_cell)
|
||||
{
|
||||
uint32_t *ssb_arfcn_ptr = (uint32_t *)ssb_arfcn;
|
||||
nr_neighbour_gnb_configuration_t *neighbour_cell_ptr = (nr_neighbour_gnb_configuration_t *)neighbour_cell;
|
||||
nr_neighbour_cell_t *neighbour_cell_ptr = (nr_neighbour_cell_t *)neighbour_cell;
|
||||
|
||||
if (*ssb_arfcn_ptr == neighbour_cell_ptr->absoluteFrequencySSB) {
|
||||
LOG_D(NR_RRC, "HO LOG: found intra frequency neighbour %lu!\n", neighbour_cell_ptr->nrcell_id);
|
||||
@@ -237,7 +237,7 @@ static bool valid_du_in_neighbour_configs(const seq_arr_t *neighbour_cell_config
|
||||
for (int c = 0; c < neighbour_cell_configuration->size; c++) {
|
||||
const neighbour_cell_configuration_t *neighbour_config = seq_arr_at(neighbour_cell_configuration, c);
|
||||
for (int ni = 0; ni < neighbour_config->neighbour_cells->size; ni++) {
|
||||
const nr_neighbour_gnb_configuration_t *nc = seq_arr_at(neighbour_config->neighbour_cells, ni);
|
||||
const nr_neighbour_cell_t *nc = seq_arr_at(neighbour_config->neighbour_cells, ni);
|
||||
if (nc->nrcell_id != cell->nr_cellid)
|
||||
continue;
|
||||
// current cell is in the nc config, check that config matches
|
||||
|
||||
@@ -61,6 +61,46 @@ static void free_ho_ctx(nr_handover_context_t *ho_ctx)
|
||||
free(ho_ctx);
|
||||
}
|
||||
|
||||
static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_be_setup_t drbs[MAX_DRBS_PER_UE])
|
||||
{
|
||||
int nb_drb = 0;
|
||||
for (int i = 0; i < MAX_DRBS_PER_UE; ++i) {
|
||||
drb_t *rrc_drb = &ue->established_drbs[i];
|
||||
if (rrc_drb->status == DRB_INACTIVE)
|
||||
continue;
|
||||
|
||||
f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb];
|
||||
nb_drb++;
|
||||
drb->drb_id = rrc_drb->drb_id;
|
||||
drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM;
|
||||
memcpy(&drb->up_ul_tnl[0].tl_address, &rrc_drb->cuup_tunnel_config.addr.buffer, sizeof(uint8_t) * 4);
|
||||
drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
|
||||
drb->up_ul_tnl[0].teid = rrc_drb->cuup_tunnel_config.teid;
|
||||
drb->up_ul_tnl_length = 1;
|
||||
|
||||
/* fetch an existing PDU session for this DRB */
|
||||
rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, drb->drb_id);
|
||||
AssertFatal(pdu != NULL, "no PDU session for DRB ID %ld\n", drb->drb_id);
|
||||
drb->nssai = pdu->param.nssai;
|
||||
|
||||
// for the moment, we only support one QoS flow. Put a reminder in case
|
||||
// this changes
|
||||
AssertFatal(pdu->param.nb_qos == 1, "only 1 Qos flow supported\n");
|
||||
drb->drb_info.flows_to_be_setup_length = 1;
|
||||
drb->drb_info.flows_mapped_to_drb = calloc_or_fail(1, sizeof(drb->drb_info.flows_mapped_to_drb[0]));
|
||||
AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n");
|
||||
int qfi = rrc_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[0];
|
||||
DevAssert(qfi > 0);
|
||||
drb->drb_info.flows_mapped_to_drb[0].qfi = qfi;
|
||||
pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(qfi, pdu);
|
||||
drb->drb_info.flows_mapped_to_drb[0].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char);
|
||||
|
||||
/* the DRB QoS parameters: we just reuse the ones from the first flow */
|
||||
drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params;
|
||||
}
|
||||
return nb_drb;
|
||||
}
|
||||
|
||||
/* \brief Initiate a handover of UE to a specific target cell handled by this
|
||||
* CU.
|
||||
* \param ue a UE context for which the handover should be triggered. The UE
|
||||
@@ -73,8 +113,7 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc,
|
||||
gNB_RRC_UE_t *ue,
|
||||
const nr_rrc_du_container_t *source_du,
|
||||
const nr_rrc_du_container_t *target_du,
|
||||
uint8_t *ho_prep_buf,
|
||||
uint32_t ho_prep_len,
|
||||
byte_array_t *ho_prep_info,
|
||||
ho_req_ack_t ack,
|
||||
ho_success_t success,
|
||||
ho_cancel_t cancel)
|
||||
@@ -83,7 +122,7 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc,
|
||||
DevAssert(ue != NULL);
|
||||
DevAssert(target_du != NULL);
|
||||
// source_du might be NULL -> inter-CU handover
|
||||
DevAssert(ho_prep_buf != NULL && ho_prep_len > 0);
|
||||
DevAssert(ho_prep_info->buf != NULL && ho_prep_info->len > 0);
|
||||
|
||||
if (ue->ho_context != NULL) {
|
||||
LOG_E(NR_RRC, "handover for UE %u ongoing, cannot trigger new\n", ue->rrc_ue_id);
|
||||
@@ -130,45 +169,12 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc,
|
||||
target_du->setup_req->cell[0].info.nr_pci);
|
||||
|
||||
cu_to_du_rrc_information_t cu2du = {
|
||||
.handoverPreparationInfo = ho_prep_buf,
|
||||
.handoverPreparationInfo_length = ho_prep_len,
|
||||
.handoverPreparationInfo = ho_prep_info->buf,
|
||||
.handoverPreparationInfo_length = ho_prep_info->len,
|
||||
};
|
||||
|
||||
f1ap_drb_to_be_setup_t drbs[MAX_DRBS_PER_UE] = {0};
|
||||
int nb_drb = 0;
|
||||
for (int i = 0; i < sizeofArray(drbs); ++i) {
|
||||
drb_t *rrc_drb = &ue->established_drbs[i];
|
||||
if (rrc_drb->status == DRB_INACTIVE)
|
||||
continue;
|
||||
|
||||
f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb];
|
||||
nb_drb++;
|
||||
drb->drb_id = rrc_drb->drb_id;
|
||||
drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM;
|
||||
memcpy(&drb->up_ul_tnl[0].tl_address, &rrc_drb->cuup_tunnel_config.addr.buffer, sizeof(uint8_t) * 4);
|
||||
drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
|
||||
drb->up_ul_tnl[0].teid = rrc_drb->cuup_tunnel_config.teid;
|
||||
drb->up_ul_tnl_length = 1;
|
||||
|
||||
/* fetch an existing PDU session for this DRB */
|
||||
rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, drb->drb_id);
|
||||
AssertFatal(pdu != NULL, "no PDU session for DRB ID %ld\n", drb->drb_id);
|
||||
drb->nssai = pdu->param.nssai;
|
||||
|
||||
// for the moment, we only support one QoS flow. Put a reminder in case
|
||||
// this changes
|
||||
AssertFatal(pdu->param.nb_qos == 1, "only 1 Qos flow supported\n");
|
||||
drb->drb_info.flows_to_be_setup_length = 1;
|
||||
drb->drb_info.flows_mapped_to_drb = calloc_or_fail(1, sizeof(f1ap_flows_mapped_to_drb_t));
|
||||
int qfi = rrc_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[0];
|
||||
DevAssert(qfi > 0);
|
||||
drb->drb_info.flows_mapped_to_drb[0].qfi = qfi;
|
||||
pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(qfi, pdu);
|
||||
drb->drb_info.flows_mapped_to_drb[0].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char);
|
||||
|
||||
/* the DRB QoS parameters: we just reuse the ones from the first flow */
|
||||
drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params;
|
||||
}
|
||||
int nb_drb = fill_drb_to_be_setup(rrc, ue, drbs);
|
||||
|
||||
f1ap_srb_to_be_setup_t srbs[2] = {{.srb_id = 1, .lcid = 1}, {.srb_id = 2, .lcid = 2}};
|
||||
f1ap_served_cell_info_t *cell_info = &target_du->setup_req->cell[0].info;
|
||||
@@ -252,15 +258,24 @@ static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_
|
||||
#endif
|
||||
}
|
||||
|
||||
static void nr_rrc_f1_ho_acknowledge(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t *rrc_reconf_buf, uint32_t rrc_reconf_len)
|
||||
static void nr_rrc_f1_ho_acknowledge(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE)
|
||||
{
|
||||
// N2/Xn HO: fill with UE caps, as-context, rrc reconf, send to source CU
|
||||
// also, fill the UE->rnti from the new one (in F1 case, happens after
|
||||
// confirmation of ue ctxt modif
|
||||
/* 3GPP TS 38.331 specifies that PDCP shall be re-established whenever the security key
|
||||
* used for the radio bearer changes, with some expections for SRB1 (i.e. when resuming
|
||||
* an RRC connection, or at the first reconfiguration after RRC connection reestablishment
|
||||
* in NR, do not re-establish PDCP */
|
||||
nr_rrc_reconfig_param_t params = get_RRCReconfiguration_params(rrc, UE, (1 << SRB2), true);
|
||||
UE->xids[params.transaction_id] = RRC_DEDICATED_RECONF;
|
||||
byte_array_t buffer = rrc_gNB_encode_RRCReconfiguration(rrc, UE, params);
|
||||
free_RRCReconfiguration_params(params);
|
||||
if (!buffer.len) {
|
||||
LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", UE->rrc_ue_id);
|
||||
return;
|
||||
}
|
||||
|
||||
// F1 HO: handling of "source CU" information
|
||||
DevAssert(UE->ho_context->source != NULL);
|
||||
rrc_gNB_trigger_reconfiguration_for_handover(rrc, UE, rrc_reconf_buf, rrc_reconf_len);
|
||||
rrc_gNB_trigger_reconfiguration_for_handover(rrc, UE, buffer.buf, buffer.len);
|
||||
LOG_A(NR_RRC, "HO acknowledged: Send reconfiguration for UE %u/RNTI %04x...\n", UE->rrc_ue_id, UE->rnti);
|
||||
|
||||
/* Re-establish SRB2 according to clause 5.3.5.6.3 of 3GPP TS 38.331
|
||||
@@ -327,7 +342,8 @@ void nr_rrc_trigger_f1_ho(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, nr_rrc_du_contain
|
||||
ho_req_ack_t ack = nr_rrc_f1_ho_acknowledge;
|
||||
ho_success_t success = nr_rrc_f1_ho_complete;
|
||||
ho_cancel_t cancel = nr_rrc_cancel_f1_ho;
|
||||
nr_initiate_handover(rrc, ue, source_du, target_du, buf, size, ack, success, cancel);
|
||||
byte_array_t hpi = {.buf = buf, .len = size};
|
||||
nr_initiate_handover(rrc, ue, source_du, target_du, &hpi, ack, success, cancel);
|
||||
}
|
||||
|
||||
void nr_rrc_finalize_ho(gNB_RRC_UE_t *ue)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define RRC_GNB_MOBILITY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common/utils/ds/byte_array.h"
|
||||
|
||||
/* forward declarations */
|
||||
typedef struct gNB_RRC_INST_s gNB_RRC_INST;
|
||||
@@ -49,7 +50,7 @@ typedef struct nr_ho_source_cu {
|
||||
} nr_ho_source_cu_t;
|
||||
|
||||
/* acknowledgement of handover request. buf+len is the RRC Reconfiguration */
|
||||
typedef void (*ho_req_ack_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, uint8_t *buf, uint32_t len);
|
||||
typedef void (*ho_req_ack_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue);
|
||||
typedef void (*ho_success_t)(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue);
|
||||
typedef struct nr_ho_target_cu {
|
||||
/// pointer to the (target) DU structure
|
||||
|
||||
@@ -141,7 +141,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_
|
||||
uint32_t cgci_len = 0;
|
||||
if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) {
|
||||
DevAssert(m == NULL);
|
||||
UE->rb_config = get_default_rbconfig(10 /* EPS bearer ID */, 1 /* drb ID */, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master);
|
||||
UE->rb_config = get_default_rbconfig(10 /* EPS bearer ID */, 1 /* drb ID */, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master, &rrc->pdcp_config);
|
||||
cgci_len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp);
|
||||
DevAssert(cgci_len > 0);
|
||||
cgci_buf = tmp;
|
||||
@@ -223,7 +223,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_
|
||||
exit(1);
|
||||
}
|
||||
|
||||
UE->rb_config = get_default_rbconfig(m->e_rabs_tobeadded[0].e_rab_id, m->e_rabs_tobeadded[0].drb_ID, cipher_algo, NR_SecurityConfig__keyToUse_secondary);
|
||||
UE->rb_config = get_default_rbconfig(m->e_rabs_tobeadded[0].e_rab_id, m->e_rabs_tobeadded[0].drb_ID, cipher_algo, NR_SecurityConfig__keyToUse_secondary, &rrc->pdcp_config);
|
||||
}
|
||||
|
||||
if(m!=NULL) {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "common/utils/T/T.h"
|
||||
#include "ngap_messages_types.h"
|
||||
#include "oai_asn1.h"
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h"
|
||||
|
||||
rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create)
|
||||
{
|
||||
@@ -71,13 +72,16 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id)
|
||||
return &ue->established_drbs[drb_id - 1];
|
||||
}
|
||||
|
||||
void set_default_drb_pdcp_config(struct pdcp_config_s *pdcp_config, int do_drb_integrity, int do_drb_ciphering)
|
||||
void set_default_drb_pdcp_config(struct pdcp_config_s *pdcp_config,
|
||||
int do_drb_integrity,
|
||||
int do_drb_ciphering,
|
||||
const nr_pdcp_configuration_t *default_pdcp_config)
|
||||
{
|
||||
AssertError(pdcp_config != NULL, return, "Failed to set default PDCP configuration for DRB!\n");
|
||||
pdcp_config->discardTimer = NR_PDCP_Config__drb__discardTimer_infinity;
|
||||
pdcp_config->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits;
|
||||
pdcp_config->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits;
|
||||
pdcp_config->t_Reordering = NR_PDCP_Config__t_Reordering_ms100;
|
||||
pdcp_config->discardTimer = encode_discard_timer(default_pdcp_config->drb.discard_timer);
|
||||
pdcp_config->pdcp_SN_SizeDL = encode_sn_size_dl(default_pdcp_config->drb.sn_size);
|
||||
pdcp_config->pdcp_SN_SizeUL = encode_sn_size_ul(default_pdcp_config->drb.sn_size);
|
||||
pdcp_config->t_Reordering = encode_t_reordering(default_pdcp_config->drb.t_reordering);
|
||||
pdcp_config->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
|
||||
pdcp_config->headerCompression.NotUsed = 0;
|
||||
pdcp_config->integrityProtection = do_drb_integrity ? NR_PDCP_Config__drb__integrityProtection_enabled : 1;
|
||||
@@ -99,7 +103,8 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
const rrc_pdu_session_param_t *pduSession,
|
||||
bool enable_sdap,
|
||||
int do_drb_integrity,
|
||||
int do_drb_ciphering)
|
||||
int do_drb_ciphering,
|
||||
const nr_pdcp_configuration_t *pdcp_config)
|
||||
{
|
||||
DevAssert(ue != NULL);
|
||||
|
||||
@@ -130,7 +135,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
est_drb->status = DRB_ACTIVE;
|
||||
}
|
||||
/* PDCP Configuration */
|
||||
set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering);
|
||||
set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering, pdcp_config);
|
||||
|
||||
drb_t *rrc_drb = get_drb(ue, drb_id);
|
||||
DevAssert(rrc_drb == est_drb); /* to double check that we create the same which we would retrieve */
|
||||
|
||||
@@ -49,13 +49,15 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id);
|
||||
/// @param enable_sdap If true the SDAP header will be added to the packet, else it will not add or search for SDAP header.
|
||||
/// @param do_drb_integrity
|
||||
/// @param do_drb_ciphering
|
||||
/// @param pdcp_config
|
||||
/// @return returns a pointer to the generated DRB structure
|
||||
drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
uint8_t drb_id,
|
||||
const rrc_pdu_session_param_t *pduSession,
|
||||
bool enable_sdap,
|
||||
int do_drb_integrity,
|
||||
int do_drb_ciphering);
|
||||
int do_drb_ciphering,
|
||||
const nr_pdcp_configuration_t *pdcp_config);
|
||||
|
||||
/// @brief return the next available (inactive) DRB ID of UE ue
|
||||
uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue);
|
||||
|
||||
@@ -1030,11 +1030,16 @@ static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, NR_Rec
|
||||
return;
|
||||
}
|
||||
|
||||
if (reconfigurationWithSync->spCellConfigCommon &&
|
||||
reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon &&
|
||||
reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL &&
|
||||
reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB)
|
||||
rrc->arfcn_ssb = *reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB;
|
||||
if (reconfigurationWithSync->spCellConfigCommon) {
|
||||
/* if the frequencyInfoDL is included, consider the target SpCell
|
||||
to be one on the SSB frequency indicated by the frequencyInfoDL */
|
||||
const NR_DownlinkConfigCommon_t *dcc = reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon;
|
||||
if (dcc && dcc->frequencyInfoDL && dcc->frequencyInfoDL->absoluteFrequencySSB)
|
||||
rrc->arfcn_ssb = *dcc->frequencyInfoDL->absoluteFrequencySSB;
|
||||
|
||||
// consider the target SpCell to be one with a physical cell identity indicated by the physCellId
|
||||
rrc->phyCellID = *reconfigurationWithSync->spCellConfigCommon->physCellId;
|
||||
}
|
||||
|
||||
NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants;
|
||||
nr_timer_stop(&tac->T310);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user