Merge branch 'integration_2025_w23' into 'develop'

Integration: `2025.w23`

Closes #962, #956, and #801

See merge request oai/openairinterface5g!3464

* !3302 Enhance UE identity management in Initial UE Message and other NGAP improvements
* !3400 T bugfix: check input data a bit better
* !3459 Improvements in NR band tables according to Rel.17
* !3465 Fix checking that amf_ip_address section is not set.
* !3463 Move RRC radio parameters file to DU
* CI: Use host network mode in NSA-B200 pipeline
* !3389 Relax NR_UE_CAPABILITY_SLOT_RX_TO_TX asserts
* !3417 Imscope updates
* !3443 Fix data race in NR UE MSG3 scheduling
* !3467 remove dead globals
This commit is contained in:
Robert Schmidt
2025-06-04 20:14:00 +00:00
57 changed files with 768 additions and 642 deletions
+1 -1
View File
@@ -1147,7 +1147,6 @@ set(L2_NR_SRC
${NR_RRC_DIR}/rrc_gNB.c
${NR_RRC_DIR}/mac_rrc_dl_direct.c
${NR_RRC_DIR}/mac_rrc_dl_f1ap.c
${NR_RRC_DIR}/nr_rrc_config.c
${NR_RRC_DIR}/rrc_gNB_nsa.c
${NR_RRC_DIR}/rrc_gNB_UE_context.c
${NR_RRC_DIR}/rrc_gNB_NGAP.c
@@ -1230,6 +1229,7 @@ set (MAC_NR_SRC
${NR_GNB_MAC_DIR}/mac_rrc_dl_handler.c
${NR_GNB_MAC_DIR}/mac_rrc_ul_direct.c
${NR_GNB_MAC_DIR}/mac_rrc_ul_f1ap.c
${NR_GNB_MAC_DIR}/nr_radio_config.c
)
@@ -169,10 +169,10 @@ gNBs =
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.68.194";
GNB_IPV4_ADDRESS_FOR_S1U = "192.168.68.194";
GNB_IPV4_ADDRESS_FOR_S1_MME = "172.21.16.109";
GNB_IPV4_ADDRESS_FOR_S1U = "172.21.16.109";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
GNB_IPV4_ADDRESS_FOR_X2C = "192.168.68.194";
GNB_IPV4_ADDRESS_FOR_X2C = "172.21.16.109";
GNB_PORT_FOR_X2C = 36422; # Spec 36422
};
@@ -9,6 +9,7 @@ services:
- IPC_LOCK
ulimits:
core: -1 # for core dumps
network_mode: "host"
environment:
USE_B2XX: 'yes'
USE_ADDITIONAL_OPTIONS: --nsa -E -q --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx --log_config.global_log_options level,nocolor,time,line_num,function
@@ -16,9 +17,6 @@ services:
- /dev/bus/usb/:/dev/bus/usb/
volumes:
- ../../conf_files/gnb.nsa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf
networks:
public_net:
ipv4_address: 192.168.68.194
#entrypoint: /bin/bash -c "sleep infinity"
healthcheck:
# pgrep does NOT work
@@ -26,12 +24,3 @@ services:
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
name: nsa-b200-gnb-net
ipam:
config:
- subnet: 192.168.68.192/26
driver_opts:
com.docker.network.bridge.name: "nsa-gnb-net"
+10
View File
@@ -35,6 +35,16 @@ typedef struct nssai_s {
uint32_t sd;
} nssai_t;
// Globally Unique AMF Identifier
typedef struct nr_guami_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_len;
uint8_t amf_region_id;
uint16_t amf_set_id;
uint8_t amf_pointer;
} nr_guami_t;
typedef enum { NON_DYNAMIC, DYNAMIC } fiveQI_t;
#endif
+20 -1
View File
@@ -24,9 +24,11 @@ event get_event(int socket, OBUF *event_buffer, void *database)
again:
if (fullread(socket, &length, 4) == -1) goto read_error;
#ifdef T_SEND_TIME
if (length < sizeof(struct timespec)) goto error;
if (fullread(socket, &t, sizeof(struct timespec)) == -1) goto read_error;
length -= sizeof(struct timespec);
#endif
if (length < sizeof(int)) goto error;
if (fullread(socket, &type, sizeof(int)) == -1) goto read_error;
length -= sizeof(int);
if (event_buffer->omaxsize < length) {
@@ -48,6 +50,9 @@ again:
return new_event(type, length, event_buffer->obuf, database);
#endif
error:
printf("error: bad data in get_event()\n");
read_error:
return (event){.type = -1};
}
@@ -64,6 +69,9 @@ event new_event(int type, int length, char *buffer, void *database)
int i;
int offset;
/* arbitrary limit to 1GiB (to simplify size checks) */
if (length < 0 || length > 1024 * 1024 * 1024) goto fatal;
#ifdef T_SEND_TIME
e.sending_time = sending_time;
#endif
@@ -87,26 +95,33 @@ event new_event(int type, int length, char *buffer, void *database)
for (i = 0; i < f.count; i++) {
//e.e[i].offset = offset;
if (!strcmp(f.type[i], "int")) {
if (offset + 4 > length) goto fatal;
e.e[i].type = EVENT_INT;
e.e[i].i = *(int *)(&buffer[offset]);
offset += 4;
} else if (!strcmp(f.type[i], "ulong")) {
if (offset + sizeof(unsigned long) > length) goto fatal;
e.e[i].type = EVENT_ULONG;
e.e[i].ul = *(unsigned long *)(&buffer[offset]);
offset += sizeof(unsigned long);
} else if (!strcmp(f.type[i], "float")) {
if (offset + sizeof(float) > length) goto fatal;
e.e[i].type = EVENT_FLOAT;
e.e[i].f = *(float *)(&buffer[offset]);
offset += sizeof(float);
} else if (!strcmp(f.type[i], "string")) {
if (offset + 1 > length) goto fatal;
e.e[i].type = EVENT_STRING;
e.e[i].s = &buffer[offset];
while (buffer[offset]) offset++;
while (offset < length && buffer[offset]) offset++;
if (offset == length) goto fatal;
offset++;
} else if (!strcmp(f.type[i], "buffer")) {
if (offset + sizeof(int) > length) goto fatal;
int len;
e.e[i].type = EVENT_BUFFER;
len = *(int *)(&buffer[offset]);
if (len <= 0 || offset + len + sizeof(int) > length) goto fatal;
e.e[i].bsize = len;
e.e[i].b = &buffer[offset+sizeof(int)];
offset += len+sizeof(int);
@@ -119,4 +134,8 @@ event new_event(int type, int length, char *buffer, void *database)
if (e.ecount==0) { printf("FORMAT not set in event %d\n", type); abort(); }
return e;
fatal:
printf("fatal: bad buffer in new_event\n");
abort();
}
+2 -2
View File
@@ -46,8 +46,8 @@ int main(int n, char **v)
/* read event from file */
if (fread(&length, 4, 1, in) != 1) break;
if (ebuf.omaxsize < length) {
ebuf.omaxsize = (length + 65535) & ~65535;
if (ebuf.omaxsize < length + 4) {
ebuf.omaxsize = (length + 4 + 65535) & ~65535;
ebuf.obuf = realloc(ebuf.obuf, ebuf.omaxsize);
if (ebuf.obuf == NULL) { printf("out of memory\n"); exit(1); }
}
@@ -157,8 +157,8 @@ int main(int n, char **v)
/* read event from file */
if (fread(&length, 4, 1, in) != 1) break;
if (ebuf.omaxsize < length) {
ebuf.omaxsize = (length + 65535) & ~65535;
if (ebuf.omaxsize < length + 4) {
ebuf.omaxsize = (length + 4 + 65535) & ~65535;
ebuf.obuf = realloc(ebuf.obuf, ebuf.omaxsize);
if (ebuf.obuf == NULL) { printf("out of memory\n"); exit(1); }
}
+4 -2
View File
@@ -114,8 +114,8 @@ int read_tracee(int s, OBUF *ebuf, int *_type, int32_t *_length)
int vpos = 0;
if (fullread(s, &length, 4) == -1) return -1;
if (ebuf->omaxsize < length) {
ebuf->omaxsize = (length + 65535) & ~65535;
if (ebuf->omaxsize < length + 4) {
ebuf->omaxsize = (length + 4 + 65535) & ~65535;
ebuf->obuf = realloc(ebuf->obuf, ebuf->omaxsize);
if (ebuf->obuf == NULL) { printf("out of memory\n"); exit(1); }
}
@@ -123,10 +123,12 @@ int read_tracee(int s, OBUF *ebuf, int *_type, int32_t *_length)
memcpy(v+vpos, &length, 4);
vpos += 4;
#ifdef T_SEND_TIME
if (length < sizeof(struct timespec)) return -1;
if (fullread(s,v+vpos,sizeof(struct timespec))==-1) return -1;
vpos += sizeof(struct timespec);
length -= sizeof(struct timespec);
#endif
if (length < sizeof(int)) return -1;
if (fullread(s, &type, sizeof(int)) == -1) return -1;
memcpy(v+vpos, &type, sizeof(int));
vpos += sizeof(int);
+4 -2
View File
@@ -133,8 +133,8 @@ int main(int n, char **v)
int vpos = 0;
if (fullread(socket, &length, 4) == -1) goto read_error;
if (ebuf.omaxsize < length) {
ebuf.omaxsize = (length + 65535) & ~65535;
if (ebuf.omaxsize < length + 4) {
ebuf.omaxsize = (length + 4 + 65535) & ~65535;
ebuf.obuf = realloc(ebuf.obuf, ebuf.omaxsize);
if (ebuf.obuf == NULL) { printf("out of memory\n"); exit(1); }
}
@@ -142,10 +142,12 @@ int main(int n, char **v)
memcpy(v+vpos, &length, 4);
vpos += 4;
#ifdef T_SEND_TIME
if (length < sizeof(struct timespec)) goto read_error;
if (fullread(socket,v+vpos,sizeof(struct timespec))==-1) goto read_error;
vpos += sizeof(struct timespec);
length -= sizeof(struct timespec);
#endif
if (length < sizeof(int)) goto read_error;
if (fullread(socket, &type, sizeof(int)) == -1) goto read_error;
memcpy(v+vpos, &type, sizeof(int));
vpos += sizeof(int);
+2 -2
View File
@@ -146,8 +146,8 @@ int main(int n, char **v)
/* read event from file */
if (fread(&length, 4, 1, in) != 1) break;
if (ebuf.omaxsize < length) {
ebuf.omaxsize = (length + 65535) & ~65535;
if (ebuf.omaxsize < length + 4) {
ebuf.omaxsize = (length + 4 + 65535) & ~65535;
ebuf.obuf = realloc(ebuf.obuf, ebuf.omaxsize);
if (ebuf.obuf == NULL) { printf("out of memory\n"); exit(1); }
}
+12 -6
View File
@@ -23,15 +23,21 @@
#include <assert.h>
#include <string.h>
#include "common/utils/utils.h" // for malloc_or_fail
byte_array_t create_byte_array(const size_t len, const uint8_t* buffer)
{
byte_array_t result = {.len = len};
if (len) {
result.buf = malloc_or_fail(len);
memcpy(result.buf, buffer, len);
}
return result;
}
byte_array_t copy_byte_array(byte_array_t src)
{
byte_array_t dst = {0};
dst.buf = malloc(src.len);
assert(dst.buf != NULL && "Memory exhausted");
memcpy(dst.buf, src.buf, src.len);
dst.len = src.len;
return dst;
return create_byte_array(src.len, src.buf);
}
void free_byte_array(byte_array_t ba)
+8
View File
@@ -28,6 +28,13 @@
#include <stdint.h>
#include <stdlib.h>
#define FREE_AND_ZERO_BYTE_ARRAY(BA) \
do { \
free_byte_array(BA); \
BA.buf = NULL; \
BA.len = 0; \
} while (0)
typedef struct {
size_t len;
uint8_t* buf;
@@ -43,5 +50,6 @@ bool eq_byte_array(const byte_array_t* m0, const byte_array_t* m1);
byte_array_t cp_str_to_ba(const char* str);
char* cp_ba_to_str(const byte_array_t ba);
byte_array_t create_byte_array(const size_t len, const uint8_t* buffer);
#endif
+17 -4
View File
@@ -207,7 +207,7 @@ int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_
return -1; // not found
}
// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101)
// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) (Rel.17)
// Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101)
// Notes:
// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL
@@ -236,6 +236,7 @@ const nr_bandentry_t nr_bandtable[] = {{1, 1920000, 1980000, 2110000, 2170000, 2
{40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100},
{41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15},
{41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30},
{46, 5150000, 5925000, 5150000, 5925000, 1, 743334, 15},
{47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15},
{48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15},
{48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30},
@@ -273,6 +274,11 @@ const nr_bandentry_t nr_bandtable[] = {{1, 1920000, 1980000, 2110000, 2170000, 2
{94, 880000, 915000, 1432000, 1517000, 20, 286400, 100},
{95, 2010000, 2025000, 000, 000, 20, 402000, 100},
{96, 5925000, 7125000, 5925000, 7125000, 1, 795000, 15},
{100, 874400, 880000, 919400, 925000, 20, 174880, 100},
{101, 1900000, 1910000, 1900000, 1910000, 20, 380000, 100},
{102, 5925000, 6425000, 5925000, 6425000, 1, 795000, 15},
{104, 6425000, 7125000, 6425000, 7125000, 1, 828334, 15},
{104, 6425000, 7125000, 6425000, 7125000, 2, 828334, 30},
{254, 1610000, 1626500, 2483500, 2500000, 20, 496700, 100},
{254, 1610000, 1626500, 2483500, 2500000, 2, 496700, 10},
{255, 1626500, 1660500, 1525000, 1559000, 20, 305000, 100},
@@ -288,7 +294,7 @@ const nr_bandentry_t nr_bandtable[] = {{1, 1920000, 1980000, 2110000, 2170000, 2
{261, 27500040, 28350000, 27500040, 28350000, 1, 2070833, 60},
{261, 27500040, 28350000, 27500040, 28350000, 2, 2070833, 120}};
// synchronization raster per band tables (Rel.15)
// synchronization raster per band tables (Rel.17)
// (38.101-1 Table 5.4.3.3-1 and 38.101-2 Table 5.4.3.3-1)
// band nb, sub-carrier spacing index, Range of gscn (First, Step size, Last)
// clang-format off
@@ -321,8 +327,9 @@ const sync_raster_t sync_raster[] = {
{40, 1, 5762, 1, 5989},
{41, 0, 6246, 3, 6717},
{41, 1, 6252, 3, 6714},
{46, 1, 8993, 1, 9530},
{48, 1, 7884, 1, 7982},
{50, 0, 3584, 1, 3787},
{50, 1, 3590, 1, 3781},
{51, 0, 3572, 1, 3574},
{53, 0, 6215, 1, 6232},
{53, 1, 6221, 1, 6226},
@@ -343,7 +350,13 @@ const sync_raster_t sync_raster[] = {
{91, 0, 3572, 1, 3574},
{92, 0, 3584, 1, 3787},
{93, 0, 3572, 1, 3574},
{94, 0, 3584, 1, 3587},
{94, 0, 3584, 1, 3787},
{96, 1, 9531, 1, 10363},
{100, 0, 2303, 1, 2307},
{101, 0, 4754, 1, 4768},
{101, 1, 4760, 1, 4764},
{102, 1, 9531, 1, 9877},
{104, 1, 9882, 7, 10358},
{254, 0, 6215, 1, 6244},
{254, 1, 6218, 1, 6241},
{255, 0, 3818, 1, 3892},
+1 -1
View File
@@ -34,7 +34,7 @@
#include "openair2/RRC/NR/nr_rrc_defs.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "openair2/RRC/NR/nr_rrc_config.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c"
#include "common/utils/nr/nr_common.h"
+2 -2
View File
@@ -1677,6 +1677,7 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h \
@@ -1687,6 +1688,7 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/openair2_proc.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/RLC/rlc.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_UE/mac_tables.c \
@@ -1847,7 +1849,6 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/nr_rrc_defs.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/cucp_cuup_if.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/cucp_cuup_direct.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/nr_rrc_config.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/mac_rrc_dl_direct.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_radio_bearers.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_NGAP.h \
@@ -1858,7 +1859,6 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_UE_context.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/cucp_cuup_e1ap.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/nr_rrc_config.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_radio_bearers.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_NGAP.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/mac_rrc_dl_f1ap.c \
+37 -2
View File
@@ -43,6 +43,7 @@
#include "position_interface.h"
#include "nr_phy_common.h"
#include "common/utils/time_manager/time_manager.h"
#include "log.h"
/*
* NR SLOT PROCESSING SEQUENCE
@@ -545,6 +546,28 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
}
}
if (!IS_SOFTMODEM_RFSIM) {
uint64_t deadline_us = rxtxD->absolute_deadline_us;
struct timespec current_time;
if (clock_gettime(CLOCK_REALTIME, &current_time)) {
LOG_E(PHY, "clock_gettime failed\n");
}
uint64_t current_time_us = current_time.tv_sec * 1e6 + current_time.tv_nsec / 1e3;
if (current_time_us > deadline_us) {
static unsigned int deadline_warning_rate_limit = 0;
if (deadline_warning_rate_limit % 1000 == 0) {
LOG_W(PHY,
"Deadline missed for tx slot %d.%d (current time %lu us, deadline %lu us, missed by %lu)\n",
proc->frame_tx,
proc->nr_slot_tx,
current_time_us,
deadline_us,
current_time_us - deadline_us);
}
deadline_warning_rate_limit++;
}
}
openair0_timestamp writeTimestamp = proc->timestamp_tx;
int writeBlockSize = rxtxD->writeBlockSize;
// if writeBlockSize gets longer that slot size, fill with dummy
@@ -728,7 +751,8 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE,
}
sampleShift = pbch_pdcch_processing(UE, proc, phy_data);
if (phy_data->dlsch[0].active && phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_) {
if (phy_data->dlsch[0].active
&& (phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_ || phy_data->dlsch[0].rnti_type == TYPE_RA_RNTI_)) {
// indicate to tx thread to wait for DLSCH decoding
if (phy_data->dlsch[0].dlsch_config.k1_feedback) { // if feedback is 0 there is no HARQ associated with this DLSCH
const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch[0].dlsch_config.k1_feedback) % fp->slots_per_frame;
@@ -1138,8 +1162,13 @@ void *UE_thread(void *arg)
const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply;
openair0_timestamp rx_timestamp;
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, &rx_timestamp, rxp, readBlockSize, fp->nb_antennas_rx);
UEscopeCopy(UE, ueTimeDomainSamples, rxp[0], sizeof(c16_t), 1, readBlockSize, 0);
metadata meta = {.slot = curMsg.proc.nr_slot_rx, .frame = curMsg.proc.frame_rx};
UEscopeCopyWithMetadata(UE, ueTimeDomainSamples, rxp[0] - firstSymSamp * sizeof(c16_t), sizeof(c16_t), 1, readBlockSize, 0, &meta);
AssertFatal(readBlockSize == tmp, "");
struct timespec current_time;
if (clock_gettime(CLOCK_REALTIME, &current_time)) {
LOG_E(PHY, "clock_gettime failed\n");
}
if(slot_nr == (nb_slot_frame - 1)) {
// read in first symbol of next frame and adjust for timing drift
@@ -1162,6 +1191,11 @@ void *UE_thread(void *arg)
const openair0_timestamp writeTimestamp = rx_timestamp + fp->get_samples_slot_timestamp(slot_nr, fp, duration_rx_to_tx)
- firstSymSamp - UE->N_TA_offset - timing_advance;
// Calculate TX deadline, approximately 1 symbol before the first sample should be written
const uint64_t samples_diff = writeTimestamp - rx_timestamp - fp->ofdm_symbol_size;
const float deadline_us = samples_diff / UE->rfdevice.openair0_cfg->sample_rate * 1e6;
const uint64_t absolute_deadline_us = current_time.tv_sec * 1e6 + current_time.tv_nsec / 1e3 + deadline_us;
// but use current UE->timing_advance value to compute writeBlockSize
int writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply;
int new_timing_advance = UE->timing_advance;
@@ -1204,6 +1238,7 @@ void *UE_thread(void *arg)
curMsgTx->writeBlockSize = writeBlockSize;
curMsgTx->proc.timestamp_tx = writeTimestamp;
curMsgTx->UE = UE;
curMsgTx->absolute_deadline_us = absolute_deadline_us;
int slot = curMsgTx->proc.nr_slot_tx;
int slot_and_frame = slot + curMsgTx->proc.frame_tx * UE->frame_parms.slots_per_frame;
-3
View File
@@ -368,9 +368,6 @@ void start_oai_nrue_threads()
int NB_UE_INST = 1;
configmodule_interface_t *uniqCfg = NULL;
// A global var to reduce the changes size
ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0};
nrLDPC_coding_interface_t nrLDPC_coding_interface = {0};
int main(int argc, char **argv)
-5
View File
@@ -31,15 +31,10 @@ typedef struct ldpc_interface_s {
LDPC_encoderfunc_t *LDPCencoder;
} ldpc_interface_t;
// Global var to limit the rework of the dirty legacy code
extern ldpc_interface_t ldpc_interface, ldpc_interface_offload, ldpc_interface_segment;
/* functions to load the LDPC shared lib, implemented in openair1/PHY/CODING/nrLDPC_load.c */
int load_LDPClib(char *version, ldpc_interface_t *);
int free_LDPClib(ldpc_interface_t *ldpc_interface);
LDPC_initfunc_t LDPCinit;
LDPC_shutdownfunc_t LDPCshutdown;
LDPC_decoderfunc_t LDPCdecoder;
LDPC_encoderfunc_t LDPCencoder;
+5
View File
@@ -85,6 +85,11 @@ static const int nr_ssb_table[][3] = {
{93, 15, nr_ssb_type_A},
{94, 15, nr_ssb_type_A},
{96, 30, nr_ssb_type_C},
{100, 15, nr_ssb_type_A},
{101, 15, nr_ssb_type_A},
{101, 30, nr_ssb_type_C},
{102, 30, nr_ssb_type_C},
{104, 30, nr_ssb_type_C},
{254, 15, nr_ssb_type_A},
{254, 30, nr_ssb_type_C},
{255, 15, nr_ssb_type_A},
@@ -323,7 +323,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
int G,
uint32_t nvar)
uint32_t nvar,
pdsch_scope_req_t *scope_req)
{
const int nl = dlsch[0].Nl;
const int matrixSz = ue->frame_parms.nb_antennas_rx * nl;
@@ -463,6 +464,12 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
csi_res_bitmap,
ue->chest_time);
stop_meas_nr_ue_phy(ue, DLSCH_EXTRACT_RBS_STATS);
if (scope_req->copy_chanest_to_scope) {
size_t size = sizeof(c16_t) * dlsch_config->number_rbs * NR_NB_SC_PER_RB;
int copy_index = symbol - dlsch_config->start_symbol;
int offset = copy_index * size;
UEscopeCopyUnsafe(ue, pdschChanEstimates, dl_ch_estimates_ext[0], size, offset, copy_index);
}
if (meas_enabled) {
LOG_D(PHY,
"[AbsSFN %u.%d] Slot%d Symbol %d: Pilot/Data extraction %5.2f \n",
@@ -481,6 +488,12 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
nb_re_pdsch = (pilots == 1) ? ((config_type == NFAPI_NR_DMRS_TYPE1) ? nb_rb_pdsch * (12 - 6 * dlsch_config->n_dmrs_cdm_groups)
: nb_rb_pdsch * (12 - 4 * dlsch_config->n_dmrs_cdm_groups))
: (nb_rb_pdsch * 12);
if (scope_req->copy_rxdataF_to_scope) {
size_t size = sizeof(c16_t) * nb_re_pdsch;
int copy_index = symbol - dlsch_config->start_symbol;
UEscopeCopyUnsafe(ue, pdschRxdataF, rxdataF_ext[0], size, scope_req->scope_rxdataF_offset, copy_index);
scope_req->scope_rxdataF_offset += size;
}
//----------------------------------------------------------
//--------------------- Channel Scaling --------------------
//----------------------------------------------------------
@@ -41,6 +41,13 @@
#define NR_PUSCH_x 2 // UCI placeholder bit TS 38.212 V15.4.0 subclause 5.3.3.1
#define NR_PUSCH_y 3 // UCI placeholder bit
// Specifies the data that should be copied to the scope during PDSCH RX
typedef struct pdsch_scope_req_s {
bool copy_chanest_to_scope;
bool copy_rxdataF_to_scope;
size_t scope_rxdataF_offset;
} pdsch_scope_req_t;
// Functions below implement 36-211 and 36-212
/** @addtogroup _PHY_TRANSPORT_
@@ -314,7 +321,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
int G,
uint32_t nvar);
uint32_t nvar,
pdsch_scope_req_t *scope_req);
int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t slot, c16_t **txData);
+46
View File
@@ -248,6 +248,29 @@ class IQHist {
if (!ss.str().empty()) {
ImGui::Text("Data for %s", ss.str().c_str());
}
if (ImGui::Button("Save IQ")) {
std::stringstream ss;
ss << "iq_";
if (iq_data->meta.frame != -1) {
ss << iq_data->meta.frame << "_";
}
if (iq_data->meta.slot != -1) {
ss << iq_data->meta.slot << "_";
}
ss << scope_id_to_string(static_cast<enum scopeDataType>(iq_data->scope_id));
ss << ".csv";
std::ofstream file(ss.str());
if (file.is_open()) {
file << "real;imag\n";
for (int i = 0; i < iq_data->len; i++) {
file << iq_data->real[i] << ";" << iq_data->imag[i] << "\n";
}
file.close();
std::cout << "Saved IQ to file: " << ss.str() << std::endl;
} else {
std::cerr << "Unable to open file";
}
}
ImGui::EndGroup();
}
};
@@ -432,6 +455,29 @@ void ShowUeScope(void *data_void_ptr, float t)
}
ImGui::End();
if (ImGui::Begin("UE PDSCH Chan est")) {
static auto iq_data = new IQData();
static auto iq_hist = new IQHist("PDSCH Chan est IQ");
bool new_data = false;
if (iq_hist->ShouldReadData()) {
new_data = iq_data->TryCollect(&scope_array[pdschChanEstimates], t, iq_hist->GetEpsilon(), iq_procedure_timer);
}
iq_hist->Draw(iq_data, t, new_data);
}
ImGui::End();
if (ImGui::Begin("UE PDSCH IQ before compensation")) {
static auto iq_data = new IQData();
static auto iq_hist = new IQHist("PDSCH IQ before compensation");
bool new_data = false;
if (iq_hist->ShouldReadData()) {
new_data = iq_data->TryCollect(&scope_array[pdschRxdataF], t, iq_hist->GetEpsilon(), iq_procedure_timer);
}
iq_hist->Draw(iq_data, t, new_data);
}
ImGui::End();
if (ImGui::Begin("Time domain samples")) {
static auto iq_data = new IQData();
// Issue with imgui deferring draw calls until the end of the frame - cases segfault if scatterplot has too many points
@@ -131,12 +131,9 @@ void unlockScopeData(enum scopeDataType type)
total_size += scope_data.data.data_copied_per_offset[i];
}
if (total_size != (uint64_t)scope_data.data.scope_graph_data->dataSize) {
LOG_E(PHY,
"Scope is missing data - not all data that was expected was copied - possibly missed copyDataUnsafeWithOffset call. "
"scope = %s, total_size = %lu, dataSize = %d\n",
scope_id_to_string(type),
total_size,
scope_data.data.scope_graph_data->dataSize);
scope_data.data.scope_graph_data->dataSize = total_size;
scope_data.data.scope_graph_data->lineSz =
total_size / scope_data.data.scope_graph_data->elementSz / scope_data.data.scope_graph_data->colSz;
}
scope_data.data.scope_id = type;
scope_data.is_data_ready = true;
@@ -179,8 +176,12 @@ const char *scope_id_to_string(scopeDataType type) {
return "ueTimeDomainSamplesBeforeSync";
case gNbTimeDomainSamples:
return "gNbTimeDomainSamples";
case pdschChanEstimates:
return "pdschChanEstimates";
case pdschRxdataF:
return "pdschRxdataF";
default:
return "unknown type";
return "unknown scope type";
}
}
@@ -35,7 +35,7 @@
constexpr std::size_t hardware_destructive_interference_size = 64;
#endif
#define NUM_CACHED_DATA 4
#define NUM_CACHED_DATA 8
// Set maximum number of kilobytes written per recording session to 1GB. This is a safeguard against
// recoding thread writing too many files and exhausting disk space.
#define MAX_KBYTES_WRITTEN_PER_SESSION (1000 * 1000)
+2
View File
@@ -77,6 +77,8 @@ enum scopeDataType {
ueTimeDomainSamples,
ueTimeDomainSamplesBeforeSync,
gNbTimeDomainSamples,
pdschChanEstimates,
pdschRxdataF,
EXTRA_SCOPE_TYPES
};
+1
View File
@@ -598,6 +598,7 @@ typedef struct nr_rxtx_thread_data_s {
int writeBlockSize;
nr_phy_data_t phy_data;
dynamic_barrier_t* next_barrier;
uint64_t absolute_deadline_us;
} nr_rxtx_thread_data_t;
typedef struct LDPCDecode_ue_s {
+35 -3
View File
@@ -606,6 +606,24 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
int32_t log2_maxh = 0;
start_meas_nr_ue_phy(ue, RX_PDSCH_STATS);
pdsch_scope_req_t scope_req = { .copy_chanest_to_scope = false,
.copy_rxdataF_to_scope = false,
.scope_rxdataF_offset = 0 };
if (UEScopeHasTryLock(ue)) {
metadata mt = {.frame = proc->frame_rx, .slot = proc->nr_slot_rx};
scope_req.copy_chanest_to_scope = UETryLockScopeData(ue,
pdschChanEstimates,
sizeof(c16_t),
1,
dlschCfg->number_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols,
&mt);
scope_req.copy_rxdataF_to_scope = UETryLockScopeData(ue,
pdschRxdataF,
sizeof(c16_t),
1,
dlschCfg->number_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols,
&mt);
}
for (int m = dlschCfg->start_symbol; m < (dlschCfg->number_symbols + dlschCfg->start_symbol); m++) {
bool first_symbol_flag = false;
if (m == first_symbol_with_data)
@@ -632,11 +650,25 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
ptrs_phase_per_slot,
ptrs_re_per_slot,
G,
nvar)
< 0)
nvar,
&scope_req)
< 0) {
if (scope_req.copy_chanest_to_scope) {
UEunlockScopeData(ue, pdschChanEstimates);
}
if (scope_req.copy_rxdataF_to_scope) {
UEunlockScopeData(ue, pdschRxdataF);
}
return -1;
}
} // CRNTI active
stop_meas_nr_ue_phy(ue, RX_PDSCH_STATS);
if (scope_req.copy_chanest_to_scope) {
UEunlockScopeData(ue, pdschChanEstimates);
}
if (scope_req.copy_rxdataF_to_scope) {
UEunlockScopeData(ue, pdschRxdataF);
}
free(toFree);
free(toFree2);
}
@@ -815,7 +847,7 @@ static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
}
// DLSCH decoding finished! don't wait anymore in Tx process, we know if we should answer ACK/NACK PUCCH
if (dlsch[0].rnti_type == TYPE_C_RNTI_ && dlsch[0].dlsch_config.k1_feedback) {
if ((dlsch[0].rnti_type == TYPE_C_RNTI_ || dlsch[0].rnti_type == TYPE_RA_RNTI_) && dlsch[0].dlsch_config.k1_feedback) {
const int ack_nack_slot_and_frame =
(proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) + proc->frame_rx * ue->frame_parms.slots_per_frame;
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]);
+1 -1
View File
@@ -37,6 +37,7 @@
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include "LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h"
#include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "LAYER2/NR_MAC_gNB/nr_radio_config.h"
#include "NR_BCCH-BCH-Message.h"
#include "NR_BWP-Downlink.h"
#include "NR_CellGroupConfig.h"
@@ -61,7 +62,6 @@
#include "PHY/defs_nr_common.h"
#include "PHY/impl_defs_nr.h"
#include "PHY/phy_vars_nr_ue.h"
#include "RRC/NR/nr_rrc_config.h"
#include "SCHED_NR/fapi_nr_l1.h"
#include "SCHED_NR/sched_nr.h"
#include "SCHED_NR_UE/defs.h"
+1 -1
View File
@@ -87,7 +87,7 @@
#include "openair1/SIMULATION/TOOLS/sim.h"
#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/RRC/NR/nr_rrc_config.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h"
#include "time_meas.h"
#include "utils.h"
+23 -45
View File
@@ -34,6 +34,7 @@
#include "common/platform_types.h"
#include "common/5g_platform_types.h"
#include "s1ap_messages_types.h"
#include "ds/byte_array.h"
// Defines to access message fields.
#define NGAP_REGISTER_GNB_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_register_gnb_req
@@ -199,15 +200,6 @@ typedef struct pdusession_level_qos_parameter_s {
ngap_allocation_retention_priority_t allocation_retention_priority;
} pdusession_level_qos_parameter_t;
typedef struct ngap_guami_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_len;
uint8_t amf_region_id;
uint16_t amf_set_id;
uint8_t amf_pointer;
} ngap_guami_t;
typedef struct fiveg_s_tmsi_s {
uint16_t amf_set_id;
uint8_t amf_pointer;
@@ -225,7 +217,6 @@ typedef struct ngap_ue_paging_identity_s {
} ngap_ue_paging_identity_t;
typedef enum ngap_ue_identities_presenceMask_e {
NGAP_UE_IDENTITIES_NONE = 0,
NGAP_UE_IDENTITIES_FiveG_s_tmsi = 1 << 1,
NGAP_UE_IDENTITIES_guami = 1 << 2,
} ngap_ue_identities_presenceMask_t;
@@ -233,16 +224,9 @@ typedef enum ngap_ue_identities_presenceMask_e {
typedef struct ngap_ue_identity_s {
ngap_ue_identities_presenceMask_t presenceMask;
fiveg_s_tmsi_t s_tmsi;
ngap_guami_t guami;
nr_guami_t guami;
} ngap_ue_identity_t;
typedef struct ngap_nas_pdu_s {
/* Octet string data */
uint8_t *buffer;
/* Length of the octet string */
uint32_t length;
} ngap_pdu_t;
typedef struct ngap_mobility_restriction_s{
ngap_plmn_identity_t serving_plmn;
}ngap_mobility_restriction_t;
@@ -258,8 +242,8 @@ typedef enum pdu_session_type_e {
typedef struct pdusession_s {
/* Unique pdusession_id for the UE. */
int pdusession_id;
ngap_pdu_t nas_pdu;
ngap_pdu_t pdusessionTransfer;
byte_array_t nas_pdu;
byte_array_t pdusessionTransfer;
uint8_t nb_qos;
/* Quality of service for this pdusession */
pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE];
@@ -506,22 +490,16 @@ typedef struct ngap_deregistered_gnb_ind_s {
* will be the unique identifier used between RRC and NGAP.
*/
typedef struct ngap_nas_first_req_s {
/* UE id for initial connection to NGAP */
// RAN UE NGAP ID (mandatory)
uint32_t gNB_ue_ngap_id;
/* the chosen PLMN identity as index, see TS 36.331 6.2.2 RRC Connection
* Setup Complete. This index here is zero-based, unlike the standard! */
int selected_plmn_identity;
/* Establishment cause as sent by UE */
/* PLMN: Selected PLMN Identity (optional)
* User Location Information (mandatory) */
plmn_id_t plmn;
// RRC Establishment Cause (mandatory)
ngap_rrc_establishment_cause_t establishment_cause;
/* NAS PDU */
ngap_pdu_t nas_pdu;
/* If this flag is set NGAP layer is expecting the GUAMI. If = 0,
* the temporary s-tmsi is used.
*/
// NAS-PDU (mandatory)
byte_array_t nas_pdu;
// UE identity: 5G-S-TMSI, GUAMI
ngap_ue_identity_t ue_identity;
} ngap_nas_first_req_t;
@@ -529,12 +507,12 @@ typedef struct ngap_uplink_nas_s {
/* Unique UE identifier within an gNB */
uint32_t gNB_ue_ngap_id;
/* NAS pdu */
ngap_pdu_t nas_pdu;
byte_array_t nas_pdu;
} ngap_uplink_nas_t;
typedef struct ngap_ue_cap_info_ind_s {
uint32_t gNB_ue_ngap_id;
ngap_pdu_t ue_radio_cap;
byte_array_t ue_radio_cap;
} ngap_ue_cap_info_ind_t;
typedef struct ngap_initial_context_setup_resp_s {
@@ -561,7 +539,7 @@ typedef struct ngap_initial_context_setup_fail_s {
typedef struct ngap_nas_non_delivery_ind_s {
uint32_t gNB_ue_ngap_id;
ngap_pdu_t nas_pdu;
byte_array_t nas_pdu;
/* TODO: add cause */
} ngap_nas_non_delivery_ind_t;
@@ -599,7 +577,7 @@ typedef struct ngap_downlink_nas_s {
/* UE id for initial connection to NGAP */
uint32_t gNB_ue_ngap_id;
/* NAS pdu */
ngap_pdu_t nas_pdu;
byte_array_t nas_pdu;
} ngap_downlink_nas_t;
@@ -613,7 +591,7 @@ typedef struct ngap_initial_context_setup_req_s {
ngap_ambr_t ue_ambr;
/* guami */
ngap_guami_t guami;
nr_guami_t guami;
/* allowed nssai */
uint8_t nb_allowed_nssais;
@@ -636,7 +614,7 @@ typedef struct ngap_initial_context_setup_req_s {
/* Nas Pdu */
uint8_t nas_pdu_flag;
ngap_pdu_t nas_pdu;
byte_array_t nas_pdu;
} ngap_initial_context_setup_req_t;
@@ -665,8 +643,8 @@ typedef struct ngap_paging_ind_s {
typedef struct {
/* Unique pdusession_id for the UE. */
int pdusession_id;
ngap_pdu_t nas_pdu;
ngap_pdu_t pdusessionTransfer;
byte_array_t nas_pdu;
byte_array_t pdusessionTransfer;
} pdusession_setup_req_t;
typedef struct ngap_pdusession_setup_req_s {
@@ -719,7 +697,7 @@ typedef struct ngap_path_switch_req_s {
/* AMF UE id */
uint64_t amf_ue_ngap_id;
ngap_guami_t ue_guami;
nr_guami_t ue_guami;
uint16_t ue_initial_id;
/* Security algorithms */
@@ -792,7 +770,7 @@ typedef struct ngap_ue_release_command_s {
typedef struct pdusession_release_s {
/* Unique pdusession_id for the UE. */
uint8_t pdusession_id;
ngap_pdu_t data;
byte_array_t data;
} pdusession_release_t;
typedef struct ngap_ue_release_req_s {
@@ -840,7 +818,7 @@ typedef struct ngap_pdusession_release_command_s {
uint32_t gNB_ue_ngap_id;
/* The NAS PDU should be forwarded by the RRC layer to the NAS layer */
ngap_pdu_t nas_pdu;
byte_array_t nas_pdu;
/* Number of pdusession to be released in the list */
uint8_t nb_pdusessions_torelease;
+1 -2
View File
@@ -42,7 +42,6 @@
#include "PHY/INIT/nr_phy_init.h"
#include "PHY/defs_gNB.h"
#include "PHY/defs_nr_common.h"
#include "RRC/NR/nr_rrc_config.h"
#include "RRC_nr_paramsvalues.h"
#include "T.h"
#include "asn_SEQUENCE_OF.h"
@@ -885,7 +884,7 @@ void RCconfig_verify(configmodule_interface_t *cfg, ngran_node_t node_type)
verify_gnb_param_notset(gnbp, GNB_ENABLE_SDAP_IDX, GNB_CONFIG_STRING_ENABLE_SDAP);
verify_gnb_param_notset(gnbp, GNB_DRBS, GNB_CONFIG_STRING_DRBS);
verify_section_notset(cfg, GNB_CONFIG_STRING_GNB_LIST ".", GNB_CONFIG_STRING_AMF_IP_ADDRESS);
verify_section_notset(cfg, GNB_CONFIG_STRING_GNB_LIST ".[0]", GNB_CONFIG_STRING_AMF_IP_ADDRESS);
verify_section_notset(cfg, NULL, CONFIG_STRING_SECURITY);
} // else nothing to be checked
+17 -2
View File
@@ -368,8 +368,7 @@ NR_tda_info_t get_ul_tda_info(const NR_UE_UL_BWP_t *ul_bwp,
NR_PUSCH_TimeDomainResourceAllocationList_t *tdalist = get_ul_tdalist(ul_bwp, controlResourceSetId, ss_type, rnti_type);
// Definition of value j in Table 6.1.2.1.1-4 of 38.214
int scs = ul_bwp->scs;
AssertFatal(scs >= 0 && scs < 5, "Subcarrier spacing indicatior %d invalid value\n", scs);
int j = scs == 0 ? 1 : scs;
int j = get_j_for_k2(scs);
if (tdalist) {
tda_info.valid_tda = tda_index < tdalist->list.count;
if (!tda_info.valid_tda) {
@@ -5129,3 +5128,19 @@ int nr_get_prach_or_ul_mu(const NR_MsgA_ConfigCommon_r16_t *msgacc,
return mu;
}
int get_delta_for_k2(int mu)
{
// 38.214 Table 6.1.2.1.1-5: Definition of value Δ
int delta_table[] = {2, 3, 4, 6, 24, 48};
AssertFatal(mu >= 0 && mu < sizeofArray(delta_table), "Invalid numerology %d\n", mu);
return delta_table[mu];
}
int get_j_for_k2(int mu)
{
// 38.214 Table 6.1.2.1.1-4: Definition of value j
int j_table[] = {1, 1, 2, 3, 11, 21};
AssertFatal(mu >= 0 && mu < sizeofArray(j_table), "Invalid numerology %d\n", mu);
return j_table[mu];
}
@@ -318,4 +318,8 @@ int get_nrofHARQ_ProcessesForPUSCH(const NR_UE_ServingCell_Info_t *sc_info);
int nr_get_prach_or_ul_mu(const NR_MsgA_ConfigCommon_r16_t *msgacc, const NR_RACH_ConfigCommon_t *rach_ConfigCommon, const int ul_mu);
int get_delta_for_k2(int mu);
int get_j_for_k2(int mu);
#endif
+11 -2
View File
@@ -933,10 +933,19 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing);
uint16_t feedback_ti = 0;
if (rnti_type == TYPE_RA_RNTI_) {
// RA-RNTI indicates RAR. Ensure we can decode RAR before the earliest UL scheduler call
// that can process the MSG3. Also assume that RAR is sent in the same slot as DCI (k0 == 0)
// This is not perfect as the MSG3 might end up being scheduled later, so we could be
// halting the UL scheduler for a longer time than necessary.
feedback_ti = max(1 + GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing),
get_delta_for_k2(mac->current_UL_BWP->scs) + get_j_for_k2(mac->current_UL_BWP->scs));
}
if (rnti_type != TYPE_RA_RNTI_ && rnti_type != TYPE_SI_RNTI_) {
if (!get_FeedbackDisabled(mac->sc_info.downlinkHARQ_FeedbackDisabled_r17, dci->harq_pid.val)) {
feedback_ti = 1 + dci->pdsch_to_harq_feedback_timing_indicator.val + ntn_ue_koffset;
AssertFatal(feedback_ti > GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing),
AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing),
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld).\n",
feedback_ti,
GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing));
@@ -1232,7 +1241,7 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
if (!get_FeedbackDisabled(mac->sc_info.downlinkHARQ_FeedbackDisabled_r17, dci->harq_pid.val)) {
feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0] + ntn_ue_koffset;
AssertFatal(feedback_ti > GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing),
AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing),
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld). Min feedback time set in config "
"file (min_rxtxtime).\n",
feedback_ti,
+2 -17
View File
@@ -1547,22 +1547,7 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
if (is_Msg3) {
switch (mu) {
case 0:
delta = 2;
break;
case 1:
delta = 3;
break;
case 2:
delta = 4;
break;
case 3:
delta = 6;
break;
default:
AssertFatal(1 == 0, "Invalid numerology %i\n", mu);
}
delta = get_delta_for_k2(mu);
AssertFatal((k2 + delta) > GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
"Slot offset (%ld) for Msg3 needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to "
@@ -1575,7 +1560,7 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
*slot_tx = (current_slot + k2 + delta) % slots_per_frame;
*frame_tx = (current_frame + (current_slot + k2 + delta) / slots_per_frame) % MAX_FRAME_NUMBER;
} else {
AssertFatal(k2 > GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
AssertFatal(k2 >= GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
"Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to %ld in "
"gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
k2,
-1
View File
@@ -44,7 +44,6 @@
#include "NR_BCCH-BCH-Message.h"
#include "NR_ServingCellConfigCommon.h"
#include "NR_MIB.h"
#include "RRC/NR/nr_rrc_config.h"
#include "SCHED_NR/phy_frame_config_nr.h"
#include "T.h"
#include "asn_internal.h"
@@ -58,8 +58,6 @@ static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu,
int fh);
static void nr_fill_rar(uint8_t Mod_idP, NR_UE_info_t *UE, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu);
static const uint8_t DELTA[4] = {2, 3, 4, 6};
static const float ssb_per_rach_occasion[8] = {0.125, 0.25, 0.5, 1, 2, 4, 8};
static int16_t ssb_index_from_prach(module_id_t module_idP,
@@ -1566,7 +1564,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
bool ret = get_feasible_msg3_tda(scc,
DELTA[ul_bwp->scs],
get_delta_for_k2(ul_bwp->scs),
ul_bwp->tdaList_Common,
frameP,
slotP,
@@ -22,6 +22,7 @@
#include "mac_rrc_dl_handler.h"
#include "mac_proto.h"
#include "nr_radio_config.h"
#include "openair2/F1AP/f1ap_ids.h"
#include "openair2/F1AP/f1ap_common.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
-2
View File
@@ -53,8 +53,6 @@
#include "NR_ServingCellConfig.h"
#include "NR_ServingCellConfigCommon.h"
#include "NR_TAG.h"
#include "RRC/NR/MESSAGES/asn1_msg.h"
#include "RRC/NR/nr_rrc_config.h"
#include "assertions.h"
#include "common/ngran_types.h"
#include "common/ran_context.h"
+1 -1
View File
@@ -74,7 +74,7 @@
#include "NR_BCCH-BCH-Message.h"
#include "NR_CellGroupConfig.h"
#include "NR_BCCH-DL-SCH-Message.h"
#include "openair2/RRC/NR/nr_rrc_config.h"
#include "nr_radio_config.h"
/* PHY */
#include "time_meas.h"
@@ -19,26 +19,14 @@
* contact@openairinterface.org
*/
/*! \file nr_rrc_config.c
* \brief rrc config for gNB
* \author Raymond Knopp, WEI-TAI CHEN
* \date 2018
* \version 1.0
* \company Eurecom, NTUST
* \email: raymond.knopp@eurecom.fr, kroempa@gmail.com
*/
#include "nr_radio_config.h"
#include "nr_rrc_config.h"
#include <endian.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "BIT_STRING.h"
#include "NULL.h"
#include "RRC/NR/MESSAGES/asn1_msg.h"
#include "RRC/NR/nr_rrc_proto.h"
#include "SIMULATION/TOOLS/sim.h"
#include "T.h"
#include "asn_SET_OF.h"
#include "asn_codecs.h"
#include "asn_internal.h"
@@ -49,15 +37,18 @@
#include "constr_TYPE.h"
#include "executables/softmodem-common.h"
#include "oai_asn1.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#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 "NR_MeasurementTimingConfiguration.h"
#include "uper_decoder.h"
#include "uper_encoder.h"
#include "utils.h"
#include "xer_encoder.h"
#define NR_MAX_SUPPORTED_DL_LAYERS 4
#define PUCCH2_SIZE 8
const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160};
@@ -1066,7 +1057,6 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay)
AssertFatal(tda->list.count == 0, "already have pusch_TimeDomainAllocationList members\n");
const int k2 = min_fb_delay;
uint8_t DELTA[4]= {2,3,4,6}; // Delta parameter for Msg3
int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing;
struct NR_SetupRelease_PUSCH_ConfigCommon *pusch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon;
@@ -1099,7 +1089,7 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay)
int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon);
int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx);
int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame;
int k2_msg3 = nb_slots_per_period - DELTA[mu];
int k2_msg3 = nb_slots_per_period - get_delta_for_k2(mu);
struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAllocMsg3 = set_TimeDomainResourceAllocation(k2_msg3, 3, ul_symb);
if (*puschTdrAllocMsg3->k2 < min_fb_delay)
*puschTdrAllocMsg3->k2 += nb_slots_per_period;
@@ -3348,6 +3338,116 @@ 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 *rlc_BearerConfig = NULL;
rlc_BearerConfig = calloc(1, sizeof(NR_RLC_BearerConfig_t));
rlc_BearerConfig->logicalChannelIdentity = channelId;
rlc_BearerConfig->servedRadioBearer = calloc(1, sizeof(*rlc_BearerConfig->servedRadioBearer));
rlc_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity;
rlc_BearerConfig->servedRadioBearer->choice.srb_Identity = channelId;
rlc_BearerConfig->reestablishRLC = NULL;
NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t));
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->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_BearerConfig->rlc_Config = rlc_Config;
NR_LogicalChannelConfig_t *logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t));
logicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*logicalChannelConfig->ul_SpecificParameters));
logicalChannelConfig->ul_SpecificParameters->priority = priority;
logicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
logicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = bucketSizeDuration;
long *logicalChannelGroup = CALLOC(1, sizeof(long));
*logicalChannelGroup = 0;
logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = logicalChannelGroup;
logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = CALLOC(1, sizeof(*logicalChannelConfig->ul_SpecificParameters->schedulingRequestID));
*logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = 0;
logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = 0;
logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = 0;
rlc_BearerConfig->mac_LogicalChannelConfig = logicalChannelConfig;
return rlc_BearerConfig;
}
static void nr_drb_config(struct NR_RLC_Config *rlc_Config, NR_RLC_Config_PR rlc_config_pr)
{
switch (rlc_config_pr) {
case NR_RLC_Config_PR_um_Bi_Directional:
// RLC UM Bi-directional Bearer configuration
LOG_I(RLC, "RLC UM Bi-directional Bearer configuration selected \n");
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->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;
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->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;
break;
default:
AssertFatal(false, "RLC config type %d not handled\n", rlc_config_pr);
break;
}
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 *rlc_BearerConfig = calloc(1, sizeof(NR_RLC_BearerConfig_t));
rlc_BearerConfig->logicalChannelIdentity = lcChannelId;
rlc_BearerConfig->servedRadioBearer = calloc(1, sizeof(*rlc_BearerConfig->servedRadioBearer));
rlc_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity;
rlc_BearerConfig->servedRadioBearer->choice.drb_Identity = drbId;
rlc_BearerConfig->reestablishRLC = NULL;
NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t));
nr_drb_config(rlc_Config, rlc_conf);
rlc_BearerConfig->rlc_Config = rlc_Config;
NR_LogicalChannelConfig_t *logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t));
logicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*logicalChannelConfig->ul_SpecificParameters));
logicalChannelConfig->ul_SpecificParameters->priority = priority;
logicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8;
logicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms100;
long *logicalChannelGroup = CALLOC(1, sizeof(long));
*logicalChannelGroup = 1;
logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = logicalChannelGroup;
logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = CALLOC(1, sizeof(*logicalChannelConfig->ul_SpecificParameters->schedulingRequestID));
*logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = 0;
logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = 0;
logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = 0;
rlc_BearerConfig->mac_LogicalChannelConfig = logicalChannelConfig;
return rlc_BearerConfig;
}
NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
const NR_ServingCellConfigCommon_t *scc,
const NR_ServingCellConfig_t *servingcellconfigdedicated,
@@ -19,17 +19,8 @@
* contact@openairinterface.org
*/
/*! \file nr_rrc_config.c
* \brief rrc config for gNB
* \author Raymond Knopp, WEI-TAI CHEN
* \date 2018
* \version 1.0
* \company Eurecom, NTUST
* \email: raymond.knopp@eurecom.fr, kroempa@gmail.com
*/
#ifndef __NR_RRC_CONFIG_H__
#define __NR_RRC_CONFIG_H__
#ifndef __NR_MAC_RRC_CONFIG_H__
#define __NR_MAC_RRC_CONFIG_H__
#include <stdbool.h>
#include <stdint.h>
@@ -116,4 +107,7 @@ 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);
#endif
-112
View File
@@ -269,118 +269,6 @@ int do_RRCReject(uint8_t *const buffer)
return (enc_rval.encoded + 7) / 8;
}
NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId,
long priority,
e_NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration bucketSizeDuration)
{
NR_RLC_BearerConfig_t *rlc_BearerConfig = NULL;
rlc_BearerConfig = calloc(1, sizeof(NR_RLC_BearerConfig_t));
rlc_BearerConfig->logicalChannelIdentity = channelId;
rlc_BearerConfig->servedRadioBearer = calloc(1, sizeof(*rlc_BearerConfig->servedRadioBearer));
rlc_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity;
rlc_BearerConfig->servedRadioBearer->choice.srb_Identity = channelId;
rlc_BearerConfig->reestablishRLC = NULL;
NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t));
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->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_BearerConfig->rlc_Config = rlc_Config;
NR_LogicalChannelConfig_t *logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t));
logicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*logicalChannelConfig->ul_SpecificParameters));
logicalChannelConfig->ul_SpecificParameters->priority = priority;
logicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
logicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = bucketSizeDuration;
long *logicalChannelGroup = CALLOC(1, sizeof(long));
*logicalChannelGroup = 0;
logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = logicalChannelGroup;
logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = CALLOC(1, sizeof(*logicalChannelConfig->ul_SpecificParameters->schedulingRequestID));
*logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = 0;
logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = 0;
logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = 0;
rlc_BearerConfig->mac_LogicalChannelConfig = logicalChannelConfig;
return rlc_BearerConfig;
}
static void nr_drb_config(struct NR_RLC_Config *rlc_Config, NR_RLC_Config_PR rlc_config_pr)
{
switch (rlc_config_pr) {
case NR_RLC_Config_PR_um_Bi_Directional:
// RLC UM Bi-directional Bearer configuration
LOG_I(RLC, "RLC UM Bi-directional Bearer configuration selected \n");
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->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;
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->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;
break;
default:
AssertFatal(false, "RLC config type %d not handled\n", rlc_config_pr);
break;
}
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 *rlc_BearerConfig = calloc(1, sizeof(NR_RLC_BearerConfig_t));
rlc_BearerConfig->logicalChannelIdentity = lcChannelId;
rlc_BearerConfig->servedRadioBearer = calloc(1, sizeof(*rlc_BearerConfig->servedRadioBearer));
rlc_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity;
rlc_BearerConfig->servedRadioBearer->choice.drb_Identity = drbId;
rlc_BearerConfig->reestablishRLC = NULL;
NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t));
nr_drb_config(rlc_Config, rlc_conf);
rlc_BearerConfig->rlc_Config = rlc_Config;
NR_LogicalChannelConfig_t *logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t));
logicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*logicalChannelConfig->ul_SpecificParameters));
logicalChannelConfig->ul_SpecificParameters->priority = priority;
logicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8;
logicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms100;
long *logicalChannelGroup = CALLOC(1, sizeof(long));
*logicalChannelGroup = 1;
logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = logicalChannelGroup;
logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = CALLOC(1, sizeof(*logicalChannelConfig->ul_SpecificParameters->schedulingRequestID));
*logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = 0;
logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = 0;
logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = 0;
rlc_BearerConfig->mac_LogicalChannelConfig = logicalChannelConfig;
return rlc_BearerConfig;
}
/* returns a default radio bearer config suitable for NSA etc */
NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
int rb_id,
-6
View File
@@ -69,12 +69,6 @@ int do_SIB2_NR(uint8_t **msg_SIB2, NR_SSB_MTC_t *ssbmtc);
int do_RRCReject(uint8_t *const buffer);
NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(
long channelId,
long priority,
e_NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration bucketSizeDuration);
NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, long drbId, NR_RLC_Config_PR rlc_conf, long priority);
NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
int rb_id,
e_NR_CipheringAlgorithm ciphering_algorithm,
+3 -11
View File
@@ -86,15 +86,6 @@ typedef struct nr_e_rab_param_s {
uint8_t xid; // transaction_id
} __attribute__ ((__packed__)) nr_e_rab_param_t;
typedef struct nr_rrc_guami_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_len;
uint8_t amf_region_id;
uint16_t amf_set_id;
uint8_t amf_pointer;
} nr_rrc_guami_t;
typedef enum pdu_session_satus_e {
PDU_SESSION_STATUS_NEW,
PDU_SESSION_STATUS_DONE,
@@ -217,7 +208,8 @@ typedef struct gNB_RRC_UE_s {
uint64_t nr_cellid;
uint32_t rrc_ue_id;
uint64_t amf_ue_ngap_id;
nr_rrc_guami_t ue_guami;
// Globally Unique AMF Identifier
nr_guami_t ue_guami;
ngap_security_capabilities_t security_capabilities;
//NSA block
@@ -247,7 +239,7 @@ typedef struct gNB_RRC_UE_s {
pdusession_t *initial_pdus;
/* Nas Pdu */
ngap_pdu_t nas_pdu;
byte_array_t nas_pdu;
/* hack, see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() for more info */
int max_delays_pdu_session;
-2
View File
@@ -39,8 +39,6 @@
#include "NR_CG-ConfigInfo.h"
#include "NR_RRCReconfiguration.h"
#define NR_MAX_SUPPORTED_DL_LAYERS 4
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);
void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context);
+36 -51
View File
@@ -95,6 +95,7 @@
#include "E1AP/lib/e1ap_bearer_context_management.h"
#include "E1AP/lib/e1ap_interface_management.h"
#include "NR_DL-DCCH-Message.h"
#include "ds/byte_array.h"
#ifdef E2_AGENT
#include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h"
@@ -123,17 +124,6 @@ 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 clear_nas_pdu(ngap_pdu_t *pdu)
{
DevAssert(pdu != NULL);
free(pdu->buffer); // does nothing if NULL
pdu->buffer = NULL;
pdu->length = 0;
}
static void freeDRBlist(NR_DRB_ToAddModList_t *list)
{
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, list);
@@ -648,13 +638,11 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = CALLOC(1, sizeof(*dedicatedNAS_MessageList));
for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) {
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.buffer,
ue_p->pduSession[i].param.nas_pdu.length);
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 %d (pdusession idx %d)\n", ue_p->pduSession[i].param.nas_pdu.length, i);
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;
}
if (ue_p->pduSession[i].status < PDU_SESSION_STATUS_ESTABLISHED) {
@@ -662,9 +650,9 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_
}
}
if (ue_p->nas_pdu.length) {
if (ue_p->nas_pdu.len) {
asn1cSequenceAdd(dedicatedNAS_MessageList->list, NR_DedicatedNAS_Message_t, msg);
OCTET_STRING_fromBuf(msg, (char *)ue_p->nas_pdu.buffer, ue_p->nas_pdu.length);
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 */
@@ -675,7 +663,7 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_
/* Free all NAS PDUs */
for (int i = 0; i < ue_p->nb_of_pdusessions; i++)
clear_nas_pdu(&ue_p->pduSession[i].param.nas_pdu);
FREE_AND_ZERO_BYTE_ARRAY(ue_p->pduSession[i].param.nas_pdu);
uint8_t buffer[NR_RRC_BUF_SIZE] = {0};
// TODO refactor dedicatedNAS_MessageList
@@ -697,16 +685,17 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
CALLOC(1, sizeof(*dedicatedNAS_MessageList));
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 (ue_p->pduSession[i].status >= PDU_SESSION_STATUS_DONE) {
ue_p->pduSession[i].xid = xid;
if (session->status >= PDU_SESSION_STATUS_DONE) {
session->xid = xid;
continue;
}
if (ue_p->pduSession[i].cause.type != NGAP_CAUSE_NOTHING) {
if (session->cause.type != NGAP_CAUSE_NOTHING) {
// set xid of failure pdu session
ue_p->pduSession[i].xid = xid;
ue_p->pduSession[i].status = PDU_SESSION_STATUS_FAILED;
session->xid = xid;
session->status = PDU_SESSION_STATUS_FAILED;
continue;
}
@@ -714,21 +703,21 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
int j;
for (j = 0; i < MAX_DRBS_PER_UE; j++) {
if (ue_p->established_drbs[j].status != DRB_INACTIVE
&& ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == ue_p->pduSession[i].param.pdusession_id)
&& ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == session->param.pdusession_id)
break;
}
if (j == MAX_DRBS_PER_UE) {
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_unspecified};
ue_p->pduSession[i].xid = xid;
ue_p->pduSession[i].status = PDU_SESSION_STATUS_FAILED;
ue_p->pduSession[i].cause = cause;
session->xid = xid;
session->status = PDU_SESSION_STATUS_FAILED;
session->cause = cause;
continue;
}
// Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping
for (qos_flow_index = 0; qos_flow_index < ue_p->pduSession[i].param.nb_qos; qos_flow_index++) {
switch (ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI) {
for (qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) {
switch (session->param.qos[qos_flow_index].fiveQI) {
case 1: //100ms
case 2: //150ms
case 3: //50ms
@@ -742,27 +731,23 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
break;
default:
LOG_E(NR_RRC, "not supported 5qi %lu\n", ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI);
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};
ue_p->pduSession[i].status = PDU_SESSION_STATUS_FAILED;
ue_p->pduSession[i].xid = xid;
ue_p->pduSession[i].cause = cause;
session->status = PDU_SESSION_STATUS_FAILED;
session->xid = xid;
session->cause = cause;
continue;
}
LOG_I(NR_RRC,
"index %d, QOS flow %d, 5QI %ld \n",
i,
qos_flow_index,
ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI);
LOG_I(NR_RRC, "index %d, QOS flow %d, 5QI %ld \n", i, qos_flow_index, session->param.qos[qos_flow_index].fiveQI);
}
ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE;
ue_p->pduSession[i].xid = xid;
session->status = PDU_SESSION_STATUS_DONE;
session->xid = xid;
if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) {
if (session->param.nas_pdu.buf != NULL) {
asn1cSequenceAdd(dedicatedNAS_MessageList->list,NR_DedicatedNAS_Message_t, dedicatedNAS_Message);
OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)ue_p->pduSession[i].param.nas_pdu.buffer, ue_p->pduSession[i].param.nas_pdu.length);
LOG_I(NR_RRC, "add NAS info with size %d (pdusession id %d)\n", ue_p->pduSession[i].param.nas_pdu.length, ue_p->pduSession[i].param.pdusession_id);
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);
}
}
@@ -790,7 +775,7 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
/* Free all NAS PDUs */
for (int i = 0; i < ue_p->nb_of_pdusessions; i++)
clear_nas_pdu(&ue_p->pduSession[i].param.nas_pdu);
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);
const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration;
@@ -1571,21 +1556,21 @@ static int handle_rrcReestablishmentComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE
*/
void rrc_forward_ue_nas_message(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE)
{
if (UE->nas_pdu.buffer == NULL || UE->nas_pdu.length == 0)
if (UE->nas_pdu.buf == NULL || UE->nas_pdu.len == 0)
return; // no problem: the UE will re-request a NAS PDU
LOG_UE_DL_EVENT(UE, "Send DL Information Transfer [%d bytes]\n", UE->nas_pdu.length);
LOG_UE_DL_EVENT(UE, "Send DL Information Transfer [%ld bytes]\n", UE->nas_pdu.len);
uint8_t buffer[4096];
unsigned int xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id);
uint32_t length = do_NR_DLInformationTransfer(buffer, sizeof(buffer), xid, UE->nas_pdu.length, UE->nas_pdu.buffer);
uint32_t length = do_NR_DLInformationTransfer(buffer, sizeof(buffer), xid, UE->nas_pdu.len, UE->nas_pdu.buf);
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, buffer, length, "[MSG] RRC DL Information Transfer\n");
rb_id_t srb_id = UE->Srb[2].Active ? DL_SCH_LCID_DCCH1 : DL_SCH_LCID_DCCH;
const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer;
nr_rrc_transfer_protected_rrc_message(rrc, UE, srb_id, msg_id, buffer, length);
// no need to free UE->nas_pdu.buffer, do_NR_DLInformationTransfer() did that
UE->nas_pdu.buffer = NULL;
UE->nas_pdu.length = 0;
// no need to free UE->nas_pdu.buf, do_NR_DLInformationTransfer() did that
UE->nas_pdu.buf = NULL;
UE->nas_pdu.len = 0;
}
static void handle_ueCapabilityInformation(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_UECapabilityInformation_t *ue_cap_info)
+73 -58
View File
@@ -148,67 +148,78 @@ void nr_rrc_pdcp_config_security(gNB_RRC_UE_t *UE, bool enable_ciphering)
nr_pdcp_config_set_security(UE->rrc_ue_id, DL_SCH_LCID_DCCH, true, &security_parameters);
}
//------------------------------------------------------------------------------
/*
* Initial UE NAS message on S1AP.
*/
/** @brief Process AMF Identifier and fill GUAMI struct members */
static nr_guami_t get_guami(const uint32_t amf_Id, const plmn_id_t plmn)
{
nr_guami_t guami = {0};
guami.amf_region_id = (amf_Id >> 16) & 0xff;
guami.amf_set_id = (amf_Id >> 6) & 0x3ff;
guami.amf_pointer = amf_Id & 0x3f;
guami.mcc = plmn.mcc;
guami.mnc = plmn.mnc;
guami.mnc_len = plmn.mnc_digit_length;
return guami;
}
/**
* @brief Prepare the Initial UE Message (Uplink NAS) to be forwarded to the AMF over N2
* extracts NAS PDU, Selected PLMN and Registered AMF from the RRCSetupComplete
*/
void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRCSetupComplete_IEs_t *rrcSetupComplete)
//------------------------------------------------------------------------------
{
MessageDef *message_p = itti_alloc_new_message(TASK_RRC_GNB, rrc->module_id, NGAP_NAS_FIRST_REQ);
ngap_nas_first_req_t *req = &NGAP_NAS_FIRST_REQ(message_p);
memset(req, 0, sizeof(*req));
// RAN UE NGAP ID
req->gNB_ue_ngap_id = UE->rrc_ue_id;
// RRC Establishment Cause
/* Assume that cause is coded in the same way in RRC and NGap, just check that the value is in NGap range */
AssertFatal(UE->establishment_cause < NGAP_RRC_CAUSE_LAST, "Establishment cause invalid (%jd/%d)!", UE->establishment_cause, NGAP_RRC_CAUSE_LAST);
req->establishment_cause = UE->establishment_cause;
/* Forward NAS message */
req->nas_pdu.length = rrcSetupComplete->dedicatedNAS_Message.size;
req->nas_pdu.buffer = malloc(req->nas_pdu.length);
AssertFatal(req->nas_pdu.buffer != NULL, "out of memory\n");
memcpy(req->nas_pdu.buffer, rrcSetupComplete->dedicatedNAS_Message.buf, req->nas_pdu.length);
// extract_imsi(NGAP_NAS_FIRST_REQ (message_p).nas_pdu.buffer,
// NGAP_NAS_FIRST_REQ (message_p).nas_pdu.length,
// ue_context_pP);
// NAS-PDU
req->nas_pdu = create_byte_array(rrcSetupComplete->dedicatedNAS_Message.size, rrcSetupComplete->dedicatedNAS_Message.buf);
/* selected_plmn_identity: IE is 1-based, convert to 0-based (C array) */
int selected_plmn_identity = rrcSetupComplete->selectedPLMN_Identity - 1;
if (selected_plmn_identity != 0)
LOG_E(NGAP, "UE %u: sent selected PLMN identity %ld, but only one PLMN supported\n", req->gNB_ue_ngap_id, rrcSetupComplete->selectedPLMN_Identity);
/* Selected PLMN Identity (Optional)
* selectedPLMN-Identity in RRCSetupComplete: Index of the PLMN selected by the UE from the plmn-IdentityInfoList (SIB1)
* Selected PLMN Identity in INITIAL UE MESSAGE: Indicates the selected PLMN id for the non-3GPP access.*/
if (rrcSetupComplete->selectedPLMN_Identity > rrc->configuration.num_plmn) {
LOG_E(NGAP,
"Failed to send Initial UE Message: selected PLMN (%ld) identity is out of bounds (%d)\n",
rrcSetupComplete->selectedPLMN_Identity,
rrc->configuration.num_plmn);
return;
}
int selected_plmn_identity = rrcSetupComplete->selectedPLMN_Identity - 1; // Convert 1-based PLMN Identity IE to 0-based index
req->plmn = rrc->configuration.plmn[selected_plmn_identity]; // Select from the stored list
LOG_I(NGAP, "Selected PLMN in the NG Initial UE Message: MCC %u, MNC %u\n", req->plmn.mcc, req->plmn.mnc);
req->selected_plmn_identity = 0; /* always zero because we only support one */
/* Fill UE identities with available information */
/* 5G-S-TMSI */
if (UE->Initialue_identity_5g_s_TMSI.presence) {
/* Fill s-TMSI */
req->ue_identity.presenceMask = NGAP_UE_IDENTITIES_FiveG_s_tmsi;
req->ue_identity.presenceMask |= NGAP_UE_IDENTITIES_FiveG_s_tmsi;
req->ue_identity.s_tmsi.amf_set_id = UE->Initialue_identity_5g_s_TMSI.amf_set_id;
req->ue_identity.s_tmsi.amf_pointer = UE->Initialue_identity_5g_s_TMSI.amf_pointer;
req->ue_identity.s_tmsi.m_tmsi = UE->Initialue_identity_5g_s_TMSI.fiveg_tmsi;
} else if (rrcSetupComplete->registeredAMF != NULL) {
}
/* Process Registered AMF IE */
if (rrcSetupComplete->registeredAMF != NULL) {
/* Fetch the AMF-Identifier from the registeredAMF IE
* The IE AMF-Identifier (AMFI) comprises of an AMF Region ID (8b),
* an AMF Set ID (10b) and an AMF Pointer (6b)
* as specified in TS 23.003 [21], clause 2.10.1. */
NR_RegisteredAMF_t *r_amf = rrcSetupComplete->registeredAMF;
req->ue_identity.presenceMask = NGAP_UE_IDENTITIES_guami;
/* The IE AMF-Identifier (AMFI) comprises of an AMF Region ID (8b), an AMF Set ID (10b) and an AMF Pointer (6b) as specified in TS 23.003 [21], clause 2.10.1. */
req->ue_identity.presenceMask |= NGAP_UE_IDENTITIES_guami;
uint32_t amf_Id = BIT_STRING_to_uint32(&r_amf->amf_Identifier);
req->ue_identity.guami.amf_region_id = (amf_Id >> 16) & 0xff;
req->ue_identity.guami.amf_set_id = (amf_Id >> 6) & 0x3ff;
req->ue_identity.guami.amf_pointer = amf_Id & 0x3f;
UE->ue_guami.amf_region_id = req->ue_identity.guami.amf_region_id;
UE->ue_guami.amf_set_id = req->ue_identity.guami.amf_set_id;
UE->ue_guami.amf_pointer = req->ue_identity.guami.amf_pointer;
UE->ue_guami = req->ue_identity.guami = get_guami(amf_Id, req->plmn);
LOG_I(NGAP,
"Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUAMI amf_set_id %u amf_region_id %u ue %x\n",
"GUAMI in NGAP_NAS_FIRST_REQ (UE %04x): AMF Set ID %u, Region ID %u, Pointer %u\n",
UE->rnti,
req->ue_identity.guami.amf_set_id,
req->ue_identity.guami.amf_region_id,
UE->rnti);
} else {
req->ue_identity.presenceMask = NGAP_UE_IDENTITIES_NONE;
req->ue_identity.guami.amf_pointer);
}
itti_send_msg_to_task(TASK_NGAP, rrc->module_id, message_p);
@@ -247,8 +258,13 @@ static int decodePDUSessionResourceSetup(pdusession_t *session)
{
NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = NULL;
asn_codec_ctx_t st = {.max_stack_size = 100 * 1000};
asn_dec_rval_t dec_rval =
aper_decode(&st, &asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, (void **)&pdusessionTransfer, session->pdusessionTransfer.buffer, session->pdusessionTransfer.length, 0, 0);
asn_dec_rval_t dec_rval = aper_decode(&st,
&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
(void **)&pdusessionTransfer,
session->pdusessionTransfer.buf,
session->pdusessionTransfer.len,
0,
0);
if (dec_rval.code != RC_OK) {
LOG_E(NR_RRC, "can not decode PDUSessionResourceSetupRequestTransfer\n");
@@ -491,14 +507,8 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
UE->amf_ue_ngap_id = req->amf_ue_ngap_id;
/* store guami in gNB_RRC_UE_t context;
* we copy individual members because the guami types are different (nr_rrc_guami_t and ngap_guami_t) */
UE->ue_guami.mcc = req->guami.mcc;
UE->ue_guami.mnc = req->guami.mnc;
UE->ue_guami.mnc_len = req->guami.mnc_len;
UE->ue_guami.amf_region_id = req->guami.amf_region_id;
UE->ue_guami.amf_set_id = req->guami.amf_set_id;
UE->ue_guami.amf_pointer = req->guami.amf_pointer;
// Directly copy the entire guami structure
UE->ue_guami = req->guami;
/* NAS PDU */
// this is malloced pointers, we pass it for later free()
@@ -713,8 +723,7 @@ int rrc_gNB_process_NGAP_DOWNLINK_NAS(MessageDef *msg_p, instance_t instance, mu
msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_NAS_NON_DELIVERY_IND);
ngap_nas_non_delivery_ind_t *msg = &NGAP_NAS_NON_DELIVERY_IND(msg_fail_p);
msg->gNB_ue_ngap_id = req->gNB_ue_ngap_id;
msg->nas_pdu.length = req->nas_pdu.length;
msg->nas_pdu.buffer = req->nas_pdu.buffer;
msg->nas_pdu = req->nas_pdu;
// TODO add failure cause when defined!
itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p);
return (-1);
@@ -746,8 +755,8 @@ void rrc_gNB_send_NGAP_UPLINK_NAS(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_
memcpy(buf, nas->buf, nas->size);
MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, rrc->module_id, NGAP_UPLINK_NAS);
NGAP_UPLINK_NAS(msg_p).gNB_ue_ngap_id = UE->rrc_ue_id;
NGAP_UPLINK_NAS(msg_p).nas_pdu.length = nas->size;
NGAP_UPLINK_NAS(msg_p).nas_pdu.buffer = buf;
NGAP_UPLINK_NAS(msg_p).nas_pdu.len = nas->size;
NGAP_UPLINK_NAS(msg_p).nas_pdu.buf = buf;
itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p);
}
@@ -972,10 +981,16 @@ static void fill_qos2(NGAP_QosFlowAddOrModifyRequestList_t *qos, pdusession_t *s
session->nb_qos = qos->list.count;
}
static void decodePDUSessionResourceModify(pdusession_t *param, const ngap_pdu_t pdu)
static void decodePDUSessionResourceModify(pdusession_t *param, const byte_array_t pdu)
{
NGAP_PDUSessionResourceModifyRequestTransfer_t *pdusessionTransfer = NULL;
asn_dec_rval_t dec_rval = aper_decode(NULL, &asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, (void **)&pdusessionTransfer, pdu.buffer, pdu.length, 0, 0);
asn_dec_rval_t dec_rval = aper_decode(NULL,
&asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer,
(void **)&pdusessionTransfer,
pdu.buf,
pdu.len,
0,
0);
if (dec_rval.code != RC_OK) {
LOG_E(NR_RRC, "could not decode PDUSessionResourceModifyRequestTransfer\n");
@@ -1074,7 +1089,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins
sess->status = PDU_SESSION_STATUS_NEW;
sess->param.pdusession_id = sessMod->pdusession_id;
sess->cause.type = NGAP_CAUSE_NOTHING;
if (sessMod->nas_pdu.buffer != NULL) {
if (sessMod->nas_pdu.buf != NULL) {
UE->pduSession[i].param.nas_pdu = sessMod->nas_pdu;
}
// Save new pdu session parameters, qos, upf addr, teid
@@ -1347,8 +1362,8 @@ void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE,
ngap_ue_cap_info_ind_t *ind = &NGAP_UE_CAPABILITIES_IND(msg_p);
memset(ind, 0, sizeof(*ind));
ind->gNB_ue_ngap_id = UE->rrc_ue_id;
ind->ue_radio_cap.length = encoded;
ind->ue_radio_cap.buffer = buf2;
ind->ue_radio_cap.len = encoded;
ind->ue_radio_cap.buf = buf2;
itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p);
LOG_I(NR_RRC,"Send message to ngap: NGAP_UE_CAPABILITIES_IND\n");
}
@@ -1427,7 +1442,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_
if (found) {
// TODO RRCReconfiguration To UE
LOG_I(NR_RRC, "Send RRCReconfiguration To UE \n");
rrc_gNB_generate_dedicatedRRCReconfiguration_release(rrc, UE, xid, cmd->nas_pdu.length, cmd->nas_pdu.buffer);
rrc_gNB_generate_dedicatedRRCReconfiguration_release(rrc, UE, xid, cmd->nas_pdu.len, cmd->nas_pdu.buf);
} else {
// gtp tunnel delete
LOG_I(NR_RRC, "gtp tunnel delete all tunnels for UE %04x\n", UE->rnti);
-1
View File
@@ -40,7 +40,6 @@
#include <string.h>
#include "MESSAGES/asn1_msg.h"
#include "OCTET_STRING.h"
#include "RRC/NR/nr_rrc_config.h"
#include "T.h"
#include "asn_codecs.h"
#include "asn_internal.h"
+58 -36
View File
@@ -52,15 +52,6 @@
#include "oai_asn1.h"
#include "queue.h"
static void allocCopy(ngap_pdu_t *out, OCTET_STRING_t in)
{
if (in.size) {
out->buffer = malloc(in.size);
memcpy(out->buffer, in.buf, in.size);
}
out->length = in.size;
}
char *ngap_direction2String(int ngap_dir) {
static char *ngap_direction_String[] = {
"", /* Nothing */
@@ -145,6 +136,36 @@ static int ngap_gNB_handle_ng_setup_failure(sctp_assoc_t assoc_id, uint32_t stre
return 0;
}
static void ngap_dump_served_guami(const ngap_gNB_amf_data_t *amf_desc_p)
{
const struct served_guami_s *guami_p;
const struct plmn_identity_s *plmn_p;
const struct served_region_id_s *region_p;
const struct amf_set_id_s *set_id_p;
const struct amf_pointer_s *pointer_p;
NGAP_DEBUG("Served GUAMIs for AMF %s (assoc_id=%d):\n",
amf_desc_p->amf_name ? amf_desc_p->amf_name : "(no name)",
amf_desc_p->assoc_id);
STAILQ_FOREACH(guami_p, &amf_desc_p->served_guami, next)
{
NGAP_DEBUG(" GUAMI:\n");
STAILQ_FOREACH(plmn_p, &guami_p->served_plmns, next) {
NGAP_DEBUG(" PLMN: MCC=%03d, MNC=%0*d\n", plmn_p->mcc, plmn_p->mnc_digit_length, plmn_p->mnc);
}
STAILQ_FOREACH(region_p, &guami_p->served_region_ids, next) {
NGAP_DEBUG(" AMF Region ID: %d\n", region_p->amf_region_id);
}
STAILQ_FOREACH(set_id_p, &guami_p->amf_set_ids, next) {
NGAP_DEBUG(" AMF Set ID: %d\n", set_id_p->amf_set_id);
}
STAILQ_FOREACH(pointer_p, &guami_p->amf_pointers, next) {
NGAP_DEBUG(" AMF Pointer: %d\n", pointer_p->amf_pointer);
}
}
}
static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
{
NGAP_NGSetupResponse_t *container;
@@ -173,7 +194,6 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
/* The list of served guami can contain at most 256 elements.
* NR related guami is the first element in the list, i.e with an id of 0.
*/
NGAP_DEBUG("servedGUAMIs.list.count %d\n", ie->value.choice.ServedGUAMIList.list.count);
DevAssert(ie->value.choice.ServedGUAMIList.list.count > 0);
DevAssert(ie->value.choice.ServedGUAMIList.list.count <= NGAP_maxnoofServedGUAMIs);
@@ -197,32 +217,27 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
STAILQ_INSERT_TAIL(&new_guami_p->served_plmns, new_plmn_identity_p, next);
new_guami_p->nb_served_plmns++;
NGAP_AMFRegionID_t *amf_region_id_p;
struct served_region_id_s *new_region_id_p;
amf_region_id_p = &guami_item_p->gUAMI.aMFRegionID;
new_region_id_p = calloc(1, sizeof(struct served_region_id_s));
OCTET_STRING_TO_INT8(amf_region_id_p, new_region_id_p->amf_region_id);
new_region_id_p->amf_region_id = BIT_STRING_to_uint8(&guami_item_p->gUAMI.aMFRegionID);
STAILQ_INSERT_TAIL(&new_guami_p->served_region_ids, new_region_id_p, next);
new_guami_p->nb_region_id++;
NGAP_AMFSetID_t *amf_set_id_p;
struct amf_set_id_s *new_amf_set_id_p;
amf_set_id_p = &guami_item_p->gUAMI.aMFSetID;
new_amf_set_id_p = calloc(1, sizeof(struct amf_set_id_s));
OCTET_STRING_TO_INT16(amf_set_id_p, new_amf_set_id_p->amf_set_id);
new_amf_set_id_p->amf_set_id = BIT_STRING_to_uint16(&guami_item_p->gUAMI.aMFSetID);
STAILQ_INSERT_TAIL(&new_guami_p->amf_set_ids, new_amf_set_id_p, next);
new_guami_p->nb_amf_set_id++;
NGAP_AMFPointer_t *amf_pointer_p;
struct amf_pointer_s *new_amf_pointer_p;
amf_pointer_p = &guami_item_p->gUAMI.aMFPointer;
new_amf_pointer_p = calloc(1, sizeof(struct amf_pointer_s));
OCTET_STRING_TO_INT8(amf_pointer_p, new_amf_pointer_p->amf_pointer);
new_amf_pointer_p->amf_pointer = BIT_STRING_to_uint8(&guami_item_p->gUAMI.aMFPointer);
STAILQ_INSERT_TAIL(&new_guami_p->amf_pointers, new_amf_pointer_p, next);
new_guami_p->nb_amf_pointer++;
STAILQ_INSERT_TAIL(&amf_desc_p->served_guami, new_guami_p, next);
}
ngap_dump_served_guami(amf_desc_p);
/* Set the capacity of this AMF */
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container,
@@ -245,13 +260,12 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container,
NGAP_ProtocolIE_ID_id_PLMNSupportList, true);
NGAP_DEBUG("PLMNSupportList.list.count %d\n", ie->value.choice.PLMNSupportList.list.count);
DevAssert(ie->value.choice.PLMNSupportList.list.count > 0);
DevAssert(ie->value.choice.PLMNSupportList.list.count <= NGAP_maxnoofPLMNs);
STAILQ_INIT(&amf_desc_p->plmn_supports);
for (i = 0; i < ie->value.choice.ServedGUAMIList.list.count; i++) {
for (i = 0; i < ie->value.choice.PLMNSupportList.list.count; i++) {
NGAP_PLMNSupportItem_t *plmn_support_item_p;
struct plmn_support_s *new_plmn_support_p;
NGAP_SliceSupportItem_t *slice_support_item_p;
@@ -260,11 +274,10 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
plmn_support_item_p = ie->value.choice.PLMNSupportList.list.array[i];
new_plmn_support_p = calloc(1, sizeof(struct plmn_support_s));
TBCD_TO_MCC_MNC(&plmn_support_item_p->pLMNIdentity, new_plmn_support_p->plmn_identity.mcc,
new_plmn_support_p->plmn_identity.mnc, new_plmn_support_p->plmn_identity.mnc_digit_length);
NGAP_DEBUG("PLMNSupportList.list.count %d\n", plmn_support_item_p->sliceSupportList.list.count);
struct plmn_identity_s *plmn = &new_plmn_support_p->plmn_identity;
TBCD_TO_MCC_MNC(&plmn_support_item_p->pLMNIdentity, plmn->mcc, plmn->mnc, plmn->mnc_digit_length);
NGAP_INFO("Supported PLMN %d: MCC=%03d MNC=%0*d\n", i, plmn->mcc, plmn->mnc_digit_length, plmn->mnc);
DevAssert(plmn_support_item_p->sliceSupportList.list.count > 0);
DevAssert(plmn_support_item_p->sliceSupportList.list.count <= NGAP_maxnoofSliceItems);
@@ -282,6 +295,12 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
new_slice_support_p->sD[1] = slice_support_item_p->s_NSSAI.sD->buf[1];
new_slice_support_p->sD[2] = slice_support_item_p->s_NSSAI.sD->buf[2];
}
NGAP_INFO("Supported slice (PLMN %d): SST=0x%02x SD=%d%d%d\n",
i,
new_slice_support_p->sST,
new_slice_support_p->sD[0],
new_slice_support_p->sD[1],
new_slice_support_p->sD[2]);
STAILQ_INSERT_TAIL(&new_plmn_support_p->slice_supports, new_slice_support_p, next);
}
@@ -772,9 +791,10 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32
}
if (item_p->nAS_PDU) {
allocCopy(&msg->pdusession_param[i].nas_pdu, *item_p->nAS_PDU);
msg->pdusession_param[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf);
}
allocCopy(&msg->pdusession_param[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer;
msg->pdusession_param[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
}
}
@@ -841,7 +861,7 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32
NGAP_ProtocolIE_ID_id_NAS_PDU, false);
if (ie)
allocCopy(&msg->nas_pdu, ie->value.choice.NAS_PDU);
msg->nas_pdu = create_byte_array(ie->value.choice.NAS_PDU.size, ie->value.choice.NAS_PDU.buf);
itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
@@ -985,9 +1005,9 @@ static int ngap_gNB_handle_pdusession_setup_request(sctp_assoc_t assoc_id, uint3
} else {
msg->pdusession_setup_params[i].nssai.sd = 0xffffff;
}
allocCopy(&msg->pdusession_setup_params[i].nas_pdu, *item_p->pDUSessionNAS_PDU);
allocCopy(&msg->pdusession_setup_params[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer;
msg->pdusession_setup_params[i].nas_pdu = create_byte_array(item_p->pDUSessionNAS_PDU->size, item_p->pDUSessionNAS_PDU->buf);
msg->pdusession_setup_params[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
}
itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
@@ -1164,8 +1184,9 @@ static int ngap_gNB_handle_pdusession_modify_request(sctp_assoc_t assoc_id, uint
// check for the NAS PDU
if (item_p->nAS_PDU != NULL && item_p->nAS_PDU->size > 0) {
allocCopy(&msg->pdusession_modify_params[i].nas_pdu, *item_p->nAS_PDU);
allocCopy(&msg->pdusession_modify_params[i].pdusessionTransfer, item_p->pDUSessionResourceModifyRequestTransfer);
msg->pdusession_modify_params[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf);
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceModifyRequestTransfer;
msg->pdusession_modify_params[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
} else {
LOG_W(NGAP, "received pdu session modify with void content for UE %u, pdu session %lu\n", msg->gNB_ue_ngap_id, item_p->pDUSessionID);
continue;
@@ -1241,7 +1262,7 @@ static int ngap_gNB_handle_pdusession_release_command(sctp_assoc_t assoc_id, uin
NGAP_ProtocolIE_ID_id_NAS_PDU, false);
if (ie)
allocCopy(&msg->nas_pdu, ie->value.choice.NAS_PDU);
msg->nas_pdu = create_byte_array(ie->value.choice.NAS_PDU.size, ie->value.choice.NAS_PDU.buf);
/* id-PDUSessionResourceToReleaseListRelCmd */
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container,
@@ -1252,8 +1273,9 @@ static int ngap_gNB_handle_pdusession_release_command(sctp_assoc_t assoc_id, uin
for (i = 0; i < ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; i++) {
NGAP_PDUSessionResourceToReleaseItemRelCmd_t *item_p;
item_p = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.array[i];
msg->pdusession_release_params[i].pdusession_id = item_p->pDUSessionID;
allocCopy(&msg->pdusession_release_params[i].data, item_p->pDUSessionResourceReleaseCommandTransfer);
pdusession_release_t *r = &msg->pdusession_release_params[i];
r->pdusession_id = item_p->pDUSessionID;
r->data = create_byte_array(item_p->pDUSessionResourceReleaseCommandTransfer.size, item_p->pDUSessionResourceReleaseCommandTransfer.buf);
}
itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
+1 -3
View File
@@ -64,9 +64,7 @@ void ngap_gNB_itti_send_nas_downlink_ind(instance_t instance, uint32_t gNB_ue_ng
ngap_downlink_nas = &message_p->ittiMsg.ngap_downlink_nas;
ngap_downlink_nas->gNB_ue_ngap_id = gNB_ue_ngap_id;
ngap_downlink_nas->nas_pdu.buffer = malloc(sizeof(uint8_t) * nas_pdu_length);
memcpy(ngap_downlink_nas->nas_pdu.buffer, nas_pdu, nas_pdu_length);
ngap_downlink_nas->nas_pdu.length = nas_pdu_length;
ngap_downlink_nas->nas_pdu = create_byte_array(nas_pdu_length, nas_pdu);
itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p);
}
@@ -38,6 +38,7 @@
#include "ngap_gNB_defs.h"
#include "queue.h"
#include "tree.h"
#include "ds/byte_array.h"
static ngap_gNB_internal_data_t ngap_gNB_internal_data;
@@ -28,6 +28,8 @@
* @ingroup _ngap
*/
#include "ds/byte_array.h"
#ifndef NGAP_GNB_MANAGEMENT_PROCEDURES_H_
#define NGAP_GNB_MANAGEMENT_PROCEDURES_H_
+136 -151
View File
@@ -58,15 +58,6 @@
#include "s1ap_messages_types.h"
#include "xer_encoder.h"
static void allocCopy(OCTET_STRING_t *out, ngap_pdu_t in)
{
if (in.length) {
out->buf = malloc(in.length);
memcpy(out->buf, in.buffer, in.length);
}
out->size = in.length;
}
static void allocAddrCopy(BIT_STRING_t *out, transport_layer_addr_t in)
{
if (in.length) {
@@ -77,20 +68,106 @@ static void allocAddrCopy(BIT_STRING_t *out, transport_layer_addr_t in)
}
}
//------------------------------------------------------------------------------
int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEfirstReq)
//------------------------------------------------------------------------------
/** @brief Selects the AMF instance for a given UE based on identity information.
* It attempts to select an AMF using the following prioritized criteria:
* 1. GUAMI, if provided and valid (via Region ID, Set ID, Pointer).
* 2. 5G-S-TMSI, using AMF Set ID if GUAMI is unavailable or unusable.
* 3. Selected PLMN identity and local PLMN configuration.
* 4. Fallback to AMF with highest relative capacity, considering load balancing.
* @ref AMF Discovery and Selection (3GPP TS 23.501 clause 6.3.5) */
static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ngap_nas_first_req_t *msg)
{
ngap_gNB_instance_t *instance_p = NULL;
struct ngap_gNB_amf_data_s *amf_desc_p = NULL;
NGAP_NGAP_PDU_t pdu;
uint8_t *buffer = NULL;
uint32_t length = 0;
ngap_gNB_amf_data_t *amf = NULL;
// Select the AMF corresponding to the GUAMI from the RegisteredAMF IE
if (msg->ue_identity.presenceMask & NGAP_UE_IDENTITIES_guami) {
const nr_guami_t *guami = &msg->ue_identity.guami;
NGAP_DEBUG("GUAMI is present: MCC=%03d MNC=%03d RegionID=%d SetID=%d Pointer=%d\n",
guami->mcc,
guami->mnc,
guami->amf_region_id,
guami->amf_set_id,
guami->amf_pointer);
amf = ngap_gNB_nnsf_select_amf_by_guami(instance_p, msg->establishment_cause, *guami);
if (amf) {
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through GUAMI MCC %d MNC %d AMFRI %d AMFSI %d AMFPT %d\n",
msg->gNB_ue_ngap_id,
amf->amf_name,
amf->assoc_id,
guami->mcc,
guami->mnc,
guami->amf_region_id,
guami->amf_set_id,
guami->amf_pointer);
return amf;
}
}
// Select the AMF corresponding to the provided 5G-S-TMSI
if (amf == NULL) {
if (msg->ue_identity.presenceMask & NGAP_UE_IDENTITIES_FiveG_s_tmsi) {
const fiveg_s_tmsi_t *fgs_tmsi = &msg->ue_identity.s_tmsi;
amf = ngap_gNB_nnsf_select_amf_by_amf_setid(instance_p, msg->establishment_cause, msg->plmn, fgs_tmsi->amf_set_id);
if (amf) {
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through S-TMSI AMFSI %d and selected PLMN MCC %d MNC %d\n",
msg->gNB_ue_ngap_id,
amf->amf_name,
amf->assoc_id,
fgs_tmsi->amf_set_id,
msg->plmn.mcc,
msg->plmn.mnc);
return amf;
}
}
}
// No UE identity (5G-S-TMSI or GUAMI) is present
if (msg->ue_identity.presenceMask == 0) {
// Select the AMF based on the selected PLMN identity received through RRCSetupComplete
amf = ngap_gNB_nnsf_select_amf_by_plmn_id(instance_p, msg->establishment_cause, msg->plmn);
if (amf) {
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through selected PLMN MCC %d MNC %d\n",
msg->gNB_ue_ngap_id,
amf->amf_name,
amf->assoc_id,
msg->plmn.mcc,
msg->plmn.mnc);
return amf;
} else {
// Select the AMF with the highest capacity
amf = ngap_gNB_nnsf_select_amf(instance_p, msg->establishment_cause);
if (amf) {
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through highest relative capacity\n", msg->gNB_ue_ngap_id, amf->amf_name, amf->assoc_id);
return amf;
}
}
}
return amf;
}
/** @brief NAS Transport Messages: Initial UE Message
* forward the first received (layer 3) uplink NAS message
* from the radio interface to the AMF over N2
* NG-RAN node -> AMF (9.2.5.1, 3GPP TS 38.413) */
int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEfirstReq)
{
NGAP_NGAP_PDU_t pdu = {0};
uint8_t *buffer = NULL;
uint32_t length = 0;
DevAssert(UEfirstReq != NULL);
/* Retrieve the NGAP gNB instance associated with Mod_id */
instance_p = ngap_gNB_get_instance(instance);
ngap_gNB_instance_t *instance_p = ngap_gNB_get_instance(instance);
DevAssert(instance_p != NULL);
memset(&pdu, 0, sizeof(pdu));
// AMF selection from the Initial UE message contents
struct ngap_gNB_amf_data_s *amf = select_amf(instance_p, UEfirstReq);
if (amf == NULL) {
NGAP_WARN("No AMF is associated to the gNB\n");
return -1;
}
// Message Type (M)
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
asn1cCalloc(pdu.choice.initiatingMessage, head);
head->procedureCode = NGAP_ProcedureCode_id_InitialUEMessage;
@@ -98,98 +175,18 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
head->value.present = NGAP_InitiatingMessage__value_PR_InitialUEMessage;
NGAP_InitialUEMessage_t *out = &head->value.choice.InitialUEMessage;
/* Select the AMF corresponding to the provided GUAMI. */
//TODO have not be test. it's should be test
if (UEfirstReq->ue_identity.presenceMask & NGAP_UE_IDENTITIES_guami) {
amf_desc_p = ngap_gNB_nnsf_select_amf_by_guami(instance_p, UEfirstReq->establishment_cause, UEfirstReq->ue_identity.guami);
if (amf_desc_p) {
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through GUAMI MCC %d MNC %d AMFRI %d AMFSI %d AMFPT %d\n",
UEfirstReq->gNB_ue_ngap_id,
amf_desc_p->amf_name,
amf_desc_p->assoc_id,
UEfirstReq->ue_identity.guami.mcc,
UEfirstReq->ue_identity.guami.mnc,
UEfirstReq->ue_identity.guami.amf_region_id,
UEfirstReq->ue_identity.guami.amf_set_id,
UEfirstReq->ue_identity.guami.amf_pointer);
}
}
if (amf_desc_p == NULL) {
/* Select the AMF corresponding to the provided s-TMSI. */
//TODO have not be test. it's should be test
if (UEfirstReq->ue_identity.presenceMask & NGAP_UE_IDENTITIES_FiveG_s_tmsi) {
amf_desc_p = ngap_gNB_nnsf_select_amf_by_amf_setid(instance_p, UEfirstReq->establishment_cause, UEfirstReq->selected_plmn_identity, UEfirstReq->ue_identity.s_tmsi.amf_set_id);
if (amf_desc_p) {
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through S-TMSI AMFSI %d and selected PLMN Identity index %d MCC %d MNC %d\n",
UEfirstReq->gNB_ue_ngap_id,
amf_desc_p->amf_name,
amf_desc_p->assoc_id,
UEfirstReq->ue_identity.s_tmsi.amf_set_id,
UEfirstReq->selected_plmn_identity,
instance_p->plmn[UEfirstReq->selected_plmn_identity].plmn.mcc,
instance_p->plmn[UEfirstReq->selected_plmn_identity].plmn.mnc);
}
}
}
if (amf_desc_p == NULL) {
/* Select AMF based on the selected PLMN identity, received through RRC
* Connection Setup Complete */
//TODO have not be test. it's should be test
amf_desc_p = ngap_gNB_nnsf_select_amf_by_plmn_id(instance_p, UEfirstReq->establishment_cause, UEfirstReq->selected_plmn_identity);
if (amf_desc_p) {
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through selected PLMN Identity index %d MCC %d MNC %d\n",
UEfirstReq->gNB_ue_ngap_id,
amf_desc_p->amf_name,
amf_desc_p->assoc_id,
UEfirstReq->selected_plmn_identity,
instance_p->plmn[UEfirstReq->selected_plmn_identity].plmn.mcc,
instance_p->plmn[UEfirstReq->selected_plmn_identity].plmn.mnc);
}
}
if (amf_desc_p == NULL) {
/*
* If no AMF corresponds to the GUAMI, the s-TMSI, or the selected PLMN
* identity, selects the AMF with the highest capacity.
*/
//TODO have not be test. it's should be test
amf_desc_p = ngap_gNB_nnsf_select_amf(instance_p, UEfirstReq->establishment_cause);
if (amf_desc_p) {
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through highest relative capacity\n", UEfirstReq->gNB_ue_ngap_id, amf_desc_p->amf_name, amf_desc_p->assoc_id);
}
}
if (amf_desc_p == NULL) {
/*
* In case gNB has no AMF associated, the gNB should inform RRC and discard
* this request.
*/
NGAP_WARN("No AMF is associated to the gNB\n");
// TODO: Inform RRC
return -1;
}
/* The gNB should allocate a unique gNB UE NGAP ID for this UE. The value
* will be used for the duration of the connectivity.
*/
struct ngap_gNB_ue_context_s *ue_desc_p = calloc(1, sizeof(*ue_desc_p));
/* Store the UE context in NGAP with:
* selected AMF, selected PLMN identity, gNB ID
* the unique gNB UE NGAP ID, used for the duration of the connectivity */
struct ngap_gNB_ue_context_s *ue_desc_p = calloc_or_fail(1, sizeof(*ue_desc_p));
DevAssert(ue_desc_p != NULL);
/* Keep a reference to the selected AMF */
ue_desc_p->amf_ref = amf_desc_p;
ue_desc_p->amf_ref = amf;
ue_desc_p->gNB_ue_ngap_id = UEfirstReq->gNB_ue_ngap_id;
ue_desc_p->gNB_instance = instance_p;
ue_desc_p->selected_plmn_identity = UEfirstReq->selected_plmn_identity;
// insert in master table
ue_desc_p->selected_plmn_identity = UEfirstReq->plmn;
ngap_store_ue_context(ue_desc_p);
/* mandatory */
// RAN UE NGAP ID (M)
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
@@ -197,47 +194,43 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_RAN_UE_NGAP_ID;
ie->value.choice.RAN_UE_NGAP_ID = ue_desc_p->gNB_ue_ngap_id;
}
/* mandatory */
/* NAS-PDU (M): transferred transparently */
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_NAS_PDU;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_NAS_PDU;
allocCopy(&ie->value.choice.NAS_PDU, UEfirstReq->nas_pdu);
OCTET_STRING_fromBuf(&ie->value.choice.NAS_PDU, (const char *)UEfirstReq->nas_pdu.buf, UEfirstReq->nas_pdu.len);
}
/* mandatory */
// User Location Information (M)
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_UserLocationInformation;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_UserLocationInformation;
ie->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR;
asn1cCalloc(ie->value.choice.UserLocationInformation.choice.userLocationInformationNR, userinfo_nr_p);
/* Set nRCellIdentity. default userLocationInformationNR */
MACRO_GNB_ID_TO_CELL_IDENTITY(instance_p->gNB_id,
0, // Cell ID
&userinfo_nr_p->nR_CGI.nRCellIdentity);
MCC_MNC_TO_TBCD(instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn.mcc,
instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn.mnc,
instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn.mnc_digit_length,
&userinfo_nr_p->nR_CGI.pLMNIdentity);
/* Set TAI */
plmn_id_t *plmn = &ue_desc_p->selected_plmn_identity;
MCC_MNC_TO_TBCD(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->nR_CGI.pLMNIdentity);
/* In case of network sharing,
the selected PLMN is indicated by the PLMN Identity IE within the TAI IE */
INT24_TO_OCTET_STRING(instance_p->tac, &userinfo_nr_p->tAI.tAC);
MCC_MNC_TO_PLMNID(instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn.mcc,
instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn.mnc,
instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn.mnc_digit_length,
&userinfo_nr_p->tAI.pLMNIdentity);
MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->tAI.pLMNIdentity);
}
/* Set the establishment cause according to those provided by RRC */
DevCheck(UEfirstReq->establishment_cause < NGAP_RRC_CAUSE_LAST, UEfirstReq->establishment_cause, NGAP_RRC_CAUSE_LAST, 0);
/* mandatory */
// RRC Establishment Cause (M)
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_RRCEstablishmentCause;
@@ -246,7 +239,7 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
ie->value.choice.RRCEstablishmentCause = UEfirstReq->establishment_cause;
}
/* optional */
// 5G-S-TMSI (O)
if (UEfirstReq->ue_identity.presenceMask & NGAP_UE_IDENTITIES_FiveG_s_tmsi) {
NGAP_DEBUG("FIVEG_S_TMSI_PRESENT\n");
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
@@ -258,7 +251,8 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
M_TMSI_TO_OCTET_STRING(UEfirstReq->ue_identity.s_tmsi.m_tmsi, &ie->value.choice.FiveG_S_TMSI.fiveG_TMSI);
}
/* optional */
/* UE Context Request (O): instruct the AMF to trigger an
Initial Context Setup procedure towards the NG-RAN node. */
{
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_UEContextRequest;
@@ -267,10 +261,8 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
ie->value.choice.UEContextRequest = NGAP_UEContextRequest_requested;
}
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
/* Failed to encode message */
DevMessage("Failed to encode initial UE message\n");
}
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0)
DevMessage("Failed to encode initial UE message\n");
/* Update the current NGAP UE state */
ue_desc_p->ue_state = NGAP_UE_WAITING_CSR;
@@ -286,16 +278,13 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
* the stream should not be changed during the communication of the
* UE-associated signalling.
*/
amf_desc_p->nextstream = (amf_desc_p->nextstream + 1) % amf_desc_p->out_streams;
if ((amf_desc_p->nextstream == 0) && (amf_desc_p->out_streams > 1)) {
amf_desc_p->nextstream += 1;
amf->nextstream = (amf->nextstream + 1) % amf->out_streams;
if ((amf->nextstream == 0) && (amf->out_streams > 1)) {
amf->nextstream += 1;
}
ue_desc_p->tx_stream = amf_desc_p->nextstream;
ue_desc_p->tx_stream = amf->nextstream;
/* Send encoded message over sctp */
ngap_gNB_itti_send_sctp_data_req(instance_p->instance, amf_desc_p->assoc_id,
buffer, length, ue_desc_p->tx_stream);
ngap_gNB_itti_send_sctp_data_req(instance_p->instance, amf->assoc_id, buffer, length, ue_desc_p->tx_stream);
return 0;
}
@@ -436,8 +425,8 @@ int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_
ie->id = NGAP_ProtocolIE_ID_id_NAS_PDU;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_UplinkNASTransport_IEs__value_PR_NAS_PDU;
ie->value.choice.NAS_PDU.buf = ngap_uplink_nas_p->nas_pdu.buffer;
ie->value.choice.NAS_PDU.size = ngap_uplink_nas_p->nas_pdu.length;
ie->value.choice.NAS_PDU.buf = ngap_uplink_nas_p->nas_pdu.buf;
ie->value.choice.NAS_PDU.size = ngap_uplink_nas_p->nas_pdu.len;
}
/* mandatory */
{
@@ -453,17 +442,12 @@ int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_
MACRO_GNB_ID_TO_CELL_IDENTITY(ngap_gNB_instance_p->gNB_id,
0, // Cell ID
&userinfo_nr_p->nR_CGI.nRCellIdentity);
MCC_MNC_TO_TBCD(ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mcc,
ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mnc,
ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mnc_digit_length,
&userinfo_nr_p->nR_CGI.pLMNIdentity);
plmn_id_t *plmn = &ue_context_p->selected_plmn_identity;
MCC_MNC_TO_TBCD(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->nR_CGI.pLMNIdentity);
/* Set TAI */
INT24_TO_OCTET_STRING(ngap_gNB_instance_p->tac, &userinfo_nr_p->tAI.tAC);
MCC_MNC_TO_PLMNID(ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mcc,
ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mnc,
ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mnc_digit_length,
&userinfo_nr_p->tAI.pLMNIdentity);
MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->tAI.pLMNIdentity);
}
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
NGAP_ERROR("Failed to encode uplink NAS transport\n");
@@ -532,8 +516,8 @@ int ngap_gNB_nas_non_delivery_ind(instance_t instance,
ie->id = NGAP_ProtocolIE_ID_id_NAS_PDU;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_NASNonDeliveryIndication_IEs__value_PR_NAS_PDU;
ie->value.choice.NAS_PDU.buf = ngap_nas_non_delivery_ind->nas_pdu.buffer;
ie->value.choice.NAS_PDU.size = ngap_nas_non_delivery_ind->nas_pdu.length;
ie->value.choice.NAS_PDU.buf = ngap_nas_non_delivery_ind->nas_pdu.buf;
ie->value.choice.NAS_PDU.size = ngap_nas_non_delivery_ind->nas_pdu.len;
}
/* mandatory */
{
@@ -861,8 +845,8 @@ int ngap_gNB_ue_capabilities(instance_t instance, ngap_ue_cap_info_ind_t *ue_cap
ie->id = NGAP_ProtocolIE_ID_id_UERadioCapability;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_UERadioCapabilityInfoIndicationIEs__value_PR_UERadioCapability;
ie->value.choice.UERadioCapability.buf = ue_cap_info_ind_p->ue_radio_cap.buffer;
ie->value.choice.UERadioCapability.size = ue_cap_info_ind_p->ue_radio_cap.length;
ie->value.choice.UERadioCapability.buf = ue_cap_info_ind_p->ue_radio_cap.buf;
ie->value.choice.UERadioCapability.size = ue_cap_info_ind_p->ue_radio_cap.len;
}
/* optional */
//NGAP_UERadioCapabilityForPaging TBD
@@ -1224,8 +1208,9 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_releas
for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) {
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceReleasedListRelRes.list, NGAP_PDUSessionResourceReleasedItemRelRes_t, item);
item->pDUSessionID = pdusession_release_resp_p->pdusession_release[i].pdusession_id;
allocCopy(&item->pDUSessionResourceReleaseResponseTransfer, pdusession_release_resp_p->pdusession_release[i].data);
pdusession_release_t *r = &pdusession_release_resp_p->pdusession_release[i];
item->pDUSessionID = r->pdusession_id;
OCTET_STRING_fromBuf(&item->pDUSessionResourceReleaseResponseTransfer, (const char *)r->data.buf, r->data.len);
NGAP_DEBUG("pdusession_release_resp: pdusession ID %ld\n", item->pDUSessionID);
}
}
+14 -24
View File
@@ -33,9 +33,7 @@
#include "queue.h"
#include "tree.h"
struct ngap_gNB_amf_data_s *
ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p,
ngap_rrc_establishment_cause_t cause)
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause)
{
struct ngap_gNB_amf_data_s *amf_data_p = NULL;
struct ngap_gNB_amf_data_s *amf_highest_capacity_p = NULL;
@@ -86,10 +84,9 @@ ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p,
return amf_highest_capacity_p;
}
struct ngap_gNB_amf_data_s *
ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p,
ngap_rrc_establishment_cause_t cause,
int selected_plmn_identity)
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p,
const ngap_rrc_establishment_cause_t cause,
const plmn_id_t selected_plmn_identity)
{
struct ngap_gNB_amf_data_s *amf_data_p = NULL;
struct ngap_gNB_amf_data_s *amf_highest_capacity_p = NULL;
@@ -135,8 +132,7 @@ ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p,
/* Looking for served GUAMI PLMN Identity selected matching the one provided by the UE */
STAILQ_FOREACH(guami_p, &amf_data_p->served_guami, next) {
STAILQ_FOREACH(served_plmn_p, &guami_p->served_plmns, next) {
if ((served_plmn_p->mcc == instance_p->plmn[selected_plmn_identity].plmn.mcc)
&& (served_plmn_p->mnc == instance_p->plmn[selected_plmn_identity].plmn.mnc)) {
if ((served_plmn_p->mcc == selected_plmn_identity.mcc) && (served_plmn_p->mnc == selected_plmn_identity.mnc)) {
break;
}
}
@@ -156,11 +152,10 @@ ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p,
return amf_highest_capacity_p;
}
struct ngap_gNB_amf_data_s *
ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p,
ngap_rrc_establishment_cause_t cause,
int selected_plmn_identity,
uint8_t amf_setid)
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p,
const ngap_rrc_establishment_cause_t cause,
const plmn_id_t selected_plmn_identity,
uint8_t amf_setid)
{
struct ngap_gNB_amf_data_s *amf_data_p = NULL;
@@ -207,8 +202,7 @@ ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p,
struct plmn_identity_s *served_plmn_p = NULL;
STAILQ_FOREACH(served_plmn_p, &guami_p->served_plmns, next) {
if ((served_plmn_p->mcc == instance_p->plmn[selected_plmn_identity].plmn.mcc)
&& (served_plmn_p->mnc == instance_p->plmn[selected_plmn_identity].plmn.mnc)) {
if ((served_plmn_p->mcc == selected_plmn_identity.mcc) && (served_plmn_p->mnc == selected_plmn_identity.mnc)) {
break;
}
}
@@ -234,10 +228,9 @@ ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p,
return NULL;
}
struct ngap_gNB_amf_data_s *
ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p,
ngap_rrc_establishment_cause_t cause,
ngap_guami_t guami)
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p,
const ngap_rrc_establishment_cause_t cause,
const nr_guami_t guami)
{
struct ngap_gNB_amf_data_s *amf_data_p = NULL;
@@ -327,10 +320,7 @@ ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p,
return NULL;
}
struct ngap_gNB_amf_data_s *
ngap_gNB_nnsf_select_amf_by_guami_no_cause(ngap_gNB_instance_t *instance_p,
ngap_guami_t guami)
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami_no_cause(ngap_gNB_instance_t *instance_p, const nr_guami_t guami)
{
struct ngap_gNB_amf_data_s *amf_data_p = NULL;
struct ngap_gNB_amf_data_s *amf_highest_capacity_p = NULL;
+12 -19
View File
@@ -34,28 +34,21 @@
#include "ngap_gNB_defs.h"
#include "ngap_messages_types.h"
struct ngap_gNB_amf_data_s *
ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p,
ngap_rrc_establishment_cause_t cause);
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause);
struct ngap_gNB_amf_data_s *
ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p,
ngap_rrc_establishment_cause_t cause,
int selected_plmn_identity);
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p,
const ngap_rrc_establishment_cause_t cause,
const plmn_id_t selected_plmn_identity);
struct ngap_gNB_amf_data_s*
ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p,
ngap_rrc_establishment_cause_t cause,
int selected_plmn_identity,
uint8_t amf_setid);
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p,
const ngap_rrc_establishment_cause_t cause,
const plmn_id_t selected_plmn_identity,
uint8_t amf_setid);
struct ngap_gNB_amf_data_s*
ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p,
ngap_rrc_establishment_cause_t cause,
ngap_guami_t guami);
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p,
const ngap_rrc_establishment_cause_t cause,
const nr_guami_t guami);
struct ngap_gNB_amf_data_s*
ngap_gNB_nnsf_select_amf_by_guami_no_cause(ngap_gNB_instance_t *instance_p,
ngap_guami_t guami);
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami_no_cause(ngap_gNB_instance_t *instance_p, const nr_guami_t guami);
#endif /* NGAP_GNB_NNSF_H_ */
+1 -1
View File
@@ -72,7 +72,7 @@ typedef struct ngap_gNB_ue_context_s {
/* Signaled by the UE in RRC Connection Setup Complete and used in NAS Uplink
* to route NAS messages correctly. 0-based, not 1-based as in TS 36.331
* 6.2.2 RRC Connection Setup Complete! */
int selected_plmn_identity;
plmn_id_t selected_plmn_identity;
/* Reference to gNB data this UE is attached to */
ngap_gNB_instance_t *gNB_instance;