Merge branch 'integration_2024_w05' into 'develop'
Integration: 2024.w05 See merge request oai/openairinterface5g!2549 * !2537 Fix for UE PUSCH scheduler DURATION_RX_TO_TX assertion * !2538 Fix for UE MAC PDU LCID handling * !2542 Fix L1_SSB_CSI_RSRP table mapping and check validity * !2544 NR UE RRC timers improvement * !2546 Correcting the location of packages * !2493 Fix for computing SSB subcarrier offset * !2496 MCS for retransmission fix in case of dci failed detection at NR UE * !2503 Handle PDU Sessions in NG Initial UE context Setup and forward 5G-S-TMSI to core * enable caching in the docker build of the CI build steps * !2541 Fix RA bug, improve overall logging
This commit is contained in:
@@ -132,7 +132,7 @@ class Cluster:
|
||||
def _start_build(self, name):
|
||||
# will return "immediately" but build runs in background
|
||||
# if multiple builds are started at the same time, this can take some time, however
|
||||
ret = self.cmd.run(f'oc start-build {name} --from-file={self.eNBSourceCodePath}')
|
||||
ret = self.cmd.run(f'oc start-build {name} --from-dir={self.eNBSourceCodePath} --exclude=""')
|
||||
regres = re.search(r'build.build.openshift.io/(?P<jobname>[a-zA-Z0-9\-]+) started', ret.stdout)
|
||||
if ret.returncode != 0 or ret.stdout.count('Uploading finished') != 1 or regres is None:
|
||||
logging.error(f"error during oc start-build: {ret.stdout}")
|
||||
|
||||
@@ -357,11 +357,11 @@ class Containerize():
|
||||
if self.host == 'Ubuntu':
|
||||
self.cli = 'docker'
|
||||
self.dockerfileprefix = '.ubuntu20'
|
||||
self.cliBuildOptions = '--no-cache'
|
||||
self.cliBuildOptions = ''
|
||||
elif self.host == 'Red Hat':
|
||||
self.cli = 'sudo podman'
|
||||
self.dockerfileprefix = '.rhel9'
|
||||
self.cliBuildOptions = '--no-cache --disable-compression'
|
||||
self.cliBuildOptions = '--disable-compression'
|
||||
|
||||
# we always build the ran-build image with all targets
|
||||
# Creating a tupple with the imageName, the DockerFile prefix pattern, targetName and sanitized option
|
||||
@@ -509,7 +509,7 @@ class Containerize():
|
||||
cmd.run(f"{self.cli} volume prune --force")
|
||||
# Remove any cached artifacts: we don't use the cache for now, prevent
|
||||
# out of diskspace problem
|
||||
cmd.run(f"{self.cli} buildx prune --force")
|
||||
cmd.run(f"{self.cli} buildx prune --filter=until=6h --force")
|
||||
|
||||
# create a zip with all logs
|
||||
build_log_name = f'build_log_{self.testCase_id}'
|
||||
@@ -570,7 +570,7 @@ class Containerize():
|
||||
sys.exit(1)
|
||||
|
||||
self.cli = 'docker'
|
||||
self.cliBuildOptions = '--no-cache'
|
||||
self.cliBuildOptions = ''
|
||||
|
||||
# Workaround for some servers, we need to erase completely the workspace
|
||||
if self.forcedWorkspaceCleanup:
|
||||
|
||||
+2
-2
@@ -992,7 +992,7 @@ class RANManagement():
|
||||
NSA_RAPROC_PUSCH_check = 1
|
||||
|
||||
# Collect information on UE DLSCH and ULSCH statistics
|
||||
keys = {'dlsch_rounds','dlsch_total_bytes','ulsch_rounds','ulsch_total_bytes_scheduled'}
|
||||
keys = {'dlsch_rounds','ulsch_rounds'}
|
||||
for k in keys:
|
||||
result = re.search(k, line)
|
||||
if result is None:
|
||||
@@ -1161,7 +1161,7 @@ class RANManagement():
|
||||
dlcheckers = [] if 'd_retx_th' not in checkers else checkers['d_retx_th']
|
||||
retx_status[ue]['dl'] = self._analyzeUeRetx(dlulstat['dlsch_rounds'], dlcheckers, r'^.*dlsch_rounds\s+(\d+)\/(\d+)\/(\d+)\/(\d+),\s+dlsch_errors\s+(\d+)')
|
||||
ulcheckers = [] if 'u_retx_th' not in checkers else checkers['u_retx_th']
|
||||
retx_status[ue]['ul'] = self._analyzeUeRetx(dlulstat['ulsch_rounds'], ulcheckers, r'^.*ulsch_rounds\s+(\d+)\/(\d+)\/(\d+)\/(\d+),\s+.*,\s+ulsch_errors\s+(\d+)')
|
||||
retx_status[ue]['ul'] = self._analyzeUeRetx(dlulstat['ulsch_rounds'], ulcheckers, r'^.*ulsch_rounds\s+(\d+)\/(\d+)\/(\d+)\/(\d+),\s+ulsch_errors\s+(\d+)')
|
||||
|
||||
|
||||
#real time statistics
|
||||
|
||||
+26
-12
@@ -755,11 +755,25 @@ void SLIV2SL(int SLIV,int *S,int *L) {
|
||||
}
|
||||
}
|
||||
|
||||
int get_ssb_subcarrier_offset(uint32_t absoluteFrequencySSB, uint32_t absoluteFrequencyPointA)
|
||||
int get_ssb_subcarrier_offset(uint32_t absoluteFrequencySSB, uint32_t absoluteFrequencyPointA, int scs)
|
||||
{
|
||||
uint32_t absolute_diff = (absoluteFrequencySSB - absoluteFrequencyPointA);
|
||||
const int scaling_5khz = absoluteFrequencyPointA < 600000 ? 3 : 1;
|
||||
return ((absolute_diff / scaling_5khz) % 24);
|
||||
// for FR1 k_SSB expressed in terms of 15kHz SCS
|
||||
// for FR2 k_SSB expressed in terms of the subcarrier spacing provided by the higher-layer parameter subCarrierSpacingCommon
|
||||
// absoluteFrequencySSB and absoluteFrequencyPointA are ARFCN
|
||||
// NR-ARFCN delta frequency is 5kHz if f < 3 GHz, 15kHz for other FR1 freq and 60kHz for FR2
|
||||
const uint32_t absolute_diff = absoluteFrequencySSB - absoluteFrequencyPointA;
|
||||
int scaling = 1;
|
||||
if (absoluteFrequencyPointA < 600000) // correspond to 3GHz
|
||||
scaling = 3;
|
||||
if (scs > 2) // FR2
|
||||
scaling <<= (scs - 2);
|
||||
int sco_limit = scs == 1 ? 24 : 12;
|
||||
int subcarrier_offset = (absolute_diff / scaling) % sco_limit;
|
||||
// 30kHz is the only case where k_SSB is expressed in terms of a different SCS (15kHz)
|
||||
// the assertion is to avoid having an offset of half a subcarrier
|
||||
if (scs == 1)
|
||||
AssertFatal(subcarrier_offset % 2 == 0, "ssb offset %d invalid for scs %d\n", subcarrier_offset, scs);
|
||||
return subcarrier_offset;
|
||||
}
|
||||
|
||||
uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
|
||||
@@ -767,16 +781,16 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
|
||||
int ssbSubcarrierSpacing,
|
||||
int frequency_range)
|
||||
{
|
||||
// offset to pointA is expressed in terms of 15kHz SCS for FR1 and 60kHz for FR2
|
||||
// only difference wrt NR-ARFCN is delta frequency 5kHz if f < 3 GHz for ARFCN
|
||||
uint32_t absolute_diff = (absoluteFrequencySSB - absoluteFrequencyPointA);
|
||||
const int scaling_5khz = absoluteFrequencyPointA < 600000 ? 3 : 1;
|
||||
int sco = get_ssb_subcarrier_offset(absoluteFrequencySSB, absoluteFrequencyPointA);
|
||||
const int scs_scaling = frequency_range == FR2 ? 1 << (ssbSubcarrierSpacing - 2) : 1 << ssbSubcarrierSpacing;
|
||||
const int scaled_abs_diff = absolute_diff / scaling_5khz;
|
||||
const int ssb_offset_point_a =
|
||||
(scaled_abs_diff - sco) / 12
|
||||
- 10 * scs_scaling; // absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total
|
||||
AssertFatal(ssb_offset_point_a % scs_scaling == 0, "PRB offset %d can create frequency offset\n", ssb_offset_point_a);
|
||||
AssertFatal(sco % scs_scaling == 0, "ssb offset %d can create frequency offset\n", sco);
|
||||
const int scaling = frequency_range == FR2 ? 1 << (ssbSubcarrierSpacing - 2) : 1 << ssbSubcarrierSpacing;
|
||||
const int scaled_abs_diff = absolute_diff / (scaling_5khz * scaling);
|
||||
// absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total
|
||||
const int ssb_offset_point_a = ((scaled_abs_diff / 12) - 10) * scaling;
|
||||
// Offset to point A needs to be divisible by scaling
|
||||
AssertFatal(ssb_offset_point_a % scaling == 0, "PRB offset %d not valid for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing);
|
||||
return ssb_offset_point_a;
|
||||
}
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
|
||||
uint32_t absoluteFrequencyPointA,
|
||||
int ssbSubcarrierSpacing,
|
||||
int frequency_range);
|
||||
int get_ssb_subcarrier_offset(uint32_t absoluteFrequencySSB, uint32_t absoluteFrequencyPointA);
|
||||
int get_ssb_subcarrier_offset(uint32_t absoluteFrequencySSB, uint32_t absoluteFrequencyPointA, int scs);
|
||||
int get_delay_idx(int delay, int max_delay_comp);
|
||||
|
||||
void freq2time(uint16_t ofdm_symbol_size,
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
*\param[in] pointer to the BIT_STRING_t object.
|
||||
*\return the extracted value.
|
||||
*/
|
||||
static inline uint8_t BIT_STRING_to_uint8(BIT_STRING_t *asn) {
|
||||
static inline uint8_t BIT_STRING_to_uint8(const BIT_STRING_t *asn) {
|
||||
DevCheck ((asn->size == 1), asn->size, 0, 0);
|
||||
|
||||
return asn->buf[0] >> asn->bits_unused;
|
||||
@@ -43,7 +43,7 @@ static inline uint8_t BIT_STRING_to_uint8(BIT_STRING_t *asn) {
|
||||
*\param[in] pointer to the BIT_STRING_t object.
|
||||
*\return the extracted value.
|
||||
*/
|
||||
static inline uint16_t BIT_STRING_to_uint16(BIT_STRING_t *asn) {
|
||||
static inline uint16_t BIT_STRING_to_uint16(const BIT_STRING_t *asn) {
|
||||
uint16_t result = 0;
|
||||
int index = 0;
|
||||
|
||||
@@ -69,7 +69,7 @@ static inline uint16_t BIT_STRING_to_uint16(BIT_STRING_t *asn) {
|
||||
*\param[in] pointer to the BIT_STRING_t object.
|
||||
*\return the extracted value.
|
||||
*/
|
||||
static inline uint32_t BIT_STRING_to_uint32(BIT_STRING_t *asn) {
|
||||
static inline uint32_t BIT_STRING_to_uint32(const BIT_STRING_t *asn) {
|
||||
uint32_t result = 0;
|
||||
size_t index;
|
||||
|
||||
@@ -91,7 +91,7 @@ static inline uint32_t BIT_STRING_to_uint32(BIT_STRING_t *asn) {
|
||||
*\param[in] pointer to the BIT_STRING_t object.
|
||||
*\return the extracted value.
|
||||
*/
|
||||
static inline uint64_t BIT_STRING_to_uint64(BIT_STRING_t *asn) {
|
||||
static inline uint64_t BIT_STRING_to_uint64(const BIT_STRING_t *asn) {
|
||||
uint64_t result = 0;
|
||||
size_t index;
|
||||
int shift;
|
||||
|
||||
@@ -56,7 +56,7 @@ int get_single_rnti(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rrc_gNB_trigger_new_bearer(int rnti);
|
||||
//void rrc_gNB_trigger_new_bearer(int rnti);
|
||||
int add_bearer(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
int rnti = -1;
|
||||
@@ -75,12 +75,13 @@ int add_bearer(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
if (!rrcue)
|
||||
ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti);
|
||||
|
||||
rrc_gNB_trigger_new_bearer(rnti);
|
||||
AssertFatal(false, "not implemented\n");
|
||||
//rrc_gNB_trigger_new_bearer(rnti);
|
||||
prnt("called rrc_gNB_trigger_new_bearer(%04x)\n", rnti);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rrc_gNB_trigger_release_bearer(int rnti);
|
||||
//void rrc_gNB_trigger_release_bearer(int rnti);
|
||||
int release_bearer(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
int rnti = -1;
|
||||
@@ -99,7 +100,8 @@ int release_bearer(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
if (!rrcue)
|
||||
ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti);
|
||||
|
||||
rrc_gNB_trigger_release_bearer(rnti);
|
||||
AssertFatal(false, "not implemented\n");
|
||||
//rrc_gNB_trigger_release_bearer(rnti);
|
||||
prnt("called rrc_gNB_trigger_release_bearer(%04x)\n", rnti);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -92,10 +92,10 @@ int get_reestab_count(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
ERROR_MSG_RET("could not find UE with RNTI %04x in RRC\n");
|
||||
}
|
||||
|
||||
prnt("UE RNTI %04x reestab %d reconf_after_reestab %d\n",
|
||||
prnt("UE RNTI %04x reestab %d reconfig %d\n",
|
||||
ue->ue_context.rnti,
|
||||
ue->ue_context.ue_reestablishment_counter,
|
||||
ue->ue_context.ue_reconfiguration_after_reestablishment_counter);
|
||||
ue->ue_context.ue_reconfiguration_counter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,12 +40,12 @@ RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install --yes \
|
||||
libsctp1 \
|
||||
libconfig9 \
|
||||
iproute2 \
|
||||
net-tools \
|
||||
openssl && \
|
||||
# if the --sanitize option was used to build, additional packages are required
|
||||
/bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \
|
||||
libasan5 \
|
||||
iproute2 \
|
||||
net-tools \
|
||||
libubsan1 \
|
||||
liblapacke; fi' && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -1812,10 +1812,6 @@ void init_NR_RU(configmodule_interface_t *cfg, char *rf_config_file)
|
||||
LOG_E(PHY,"%s() DJP - ru->gNB_list ru->num_gNB are not initialized - so do it manually\n", __FUNCTION__);
|
||||
ru->gNB_list[0] = RC.gNB[0];
|
||||
ru->num_gNB=1;
|
||||
//
|
||||
//
|
||||
} else {
|
||||
LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -239,9 +239,9 @@ typedef struct {
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t rv_index;
|
||||
uint8_t harq_process_id;
|
||||
uint8_t new_data_indicator;
|
||||
uint8_t rv_index;
|
||||
uint8_t harq_process_id;
|
||||
bool new_data_indicator;
|
||||
uint32_t tb_size;
|
||||
uint16_t num_cb;
|
||||
uint8_t cb_present_and_position[(NFAPI_UE_MAX_NUM_CB+7) / 8];
|
||||
@@ -455,13 +455,13 @@ typedef struct {
|
||||
uint8_t rate_matching_ind;
|
||||
uint8_t zp_csi_rs_trigger;
|
||||
uint8_t mcs;
|
||||
uint8_t ndi;
|
||||
bool new_data_indicator;
|
||||
uint8_t rv;
|
||||
uint16_t targetCodeRate;
|
||||
uint8_t qamModOrder;
|
||||
uint32_t TBS;
|
||||
uint8_t tb2_mcs;
|
||||
uint8_t tb2_ndi;
|
||||
bool tb2_new_data_indicator;
|
||||
uint8_t tb2_rv;
|
||||
uint8_t harq_process_nbr;
|
||||
vrb_to_prb_mapping_t vrb_to_prb_mapping;
|
||||
|
||||
@@ -347,10 +347,12 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
fp->freq_range = (fp->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2;
|
||||
|
||||
uint8_t sco = 0;
|
||||
if (((fp->freq_range == nr_FR1) && (config->ssb_table.ssb_subcarrier_offset<24)) ||
|
||||
((fp->freq_range == nr_FR2) && (config->ssb_table.ssb_subcarrier_offset<12)) ) {
|
||||
if (((fp->freq_range == nr_FR1) && (config->ssb_table.ssb_subcarrier_offset < 24)) ||
|
||||
((fp->freq_range == nr_FR2) && (config->ssb_table.ssb_subcarrier_offset < 12))) {
|
||||
if (fp->freq_range == nr_FR1)
|
||||
sco = config->ssb_table.ssb_subcarrier_offset>>config->ssb_config.scs_common;
|
||||
else
|
||||
sco = config->ssb_table.ssb_subcarrier_offset;
|
||||
}
|
||||
|
||||
fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco);
|
||||
|
||||
@@ -104,8 +104,6 @@ typedef struct {
|
||||
typedef struct {
|
||||
/// Indicator of first reception
|
||||
uint8_t first_rx;
|
||||
/// Last Ndi received for this process on DCI (used for C-RNTI only)
|
||||
uint8_t Ndi;
|
||||
/// DLSCH status flag indicating
|
||||
SCH_status_t status;
|
||||
/// Transport block size
|
||||
|
||||
@@ -304,7 +304,14 @@ static void configure_dlsch(NR_UE_DLSCH_t *dlsch0,
|
||||
if ((dlsch_config_pdu->dmrs_ports>>i)&0x01) Nl += 1;
|
||||
}
|
||||
dlsch0->Nl = Nl;
|
||||
downlink_harq_process(dlsch0_harq, current_harq_pid, dlsch_config_pdu->ndi, dlsch_config_pdu->rv, dlsch0->rnti_type);
|
||||
if (dlsch_config_pdu->new_data_indicator) {
|
||||
dlsch0_harq->first_rx = true;
|
||||
dlsch0_harq->DLround = 0;
|
||||
} else {
|
||||
dlsch0_harq->first_rx = false;
|
||||
dlsch0_harq->DLround++;
|
||||
}
|
||||
downlink_harq_process(dlsch0_harq, current_harq_pid, dlsch_config_pdu->new_data_indicator, dlsch_config_pdu->rv, dlsch0->rnti_type);
|
||||
if (dlsch0_harq->status != ACTIVE) {
|
||||
// dlsch0_harq->status not ACTIVE due to false retransmission
|
||||
// Reset the following flag to skip PDSCH procedures in that case and retrasmit harq status
|
||||
|
||||
@@ -115,7 +115,6 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq)
|
||||
dl_harq->status = SCH_IDLE;
|
||||
dl_harq->first_rx = 1;
|
||||
dl_harq->DLround = 0;
|
||||
dl_harq->Ndi = 2; // set to an invalid value
|
||||
dl_harq->ack = DL_ACKNACK_NO_SET;
|
||||
}
|
||||
|
||||
@@ -152,32 +151,9 @@ void downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int dci_ndi,
|
||||
rv,
|
||||
dci_ndi,
|
||||
rnti_type,
|
||||
dl_harq->Ndi != dci_ndi ? "yes" : "no");
|
||||
dci_ndi ? "yes" : "no");
|
||||
AssertFatal(rv<4 && rv>=0, "invalid redondancy version %d\n", rv);
|
||||
if (dci_ndi!=dl_harq->Ndi) {
|
||||
if (dl_harq->ack == DL_NACK)
|
||||
LOG_D(PHY,"New transmission on a harq pid (%d) never acknowledged\n", harq_pid);
|
||||
else
|
||||
LOG_D(PHY,"Starting new transmission on a harq pid (%d)\n", harq_pid);
|
||||
} else {
|
||||
if (dl_harq->ack != DL_NACK)
|
||||
LOG_D(PHY,"gNB asked for retransmission even if we sent ACK\n");
|
||||
else
|
||||
LOG_D(PHY,"Starting retransmission on a harq pid (%d), rv (%d)\n", harq_pid, rv);
|
||||
}
|
||||
|
||||
if (dci_ndi!=dl_harq->Ndi) {
|
||||
dl_harq->first_rx = true;
|
||||
dl_harq->DLround = 0;
|
||||
} else {
|
||||
dl_harq->first_rx = false;
|
||||
dl_harq->DLround++;
|
||||
}
|
||||
|
||||
dl_harq->status = ACTIVE;
|
||||
|
||||
dl_harq->Ndi = dci_ndi;
|
||||
//dl_harq->status = SCH_IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -665,7 +665,7 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bear
|
||||
asn1cSequenceAdd(ieC6_1->dRB_To_Setup_List_NG_RAN.list, E1AP_DRB_To_Setup_Item_NG_RAN_t, ieC6_1_1);
|
||||
ieC6_1_1->dRB_ID = j->id;
|
||||
|
||||
ieC6_1_1->sDAP_Configuration.defaultDRB = j->defaultDRB;
|
||||
ieC6_1_1->sDAP_Configuration.defaultDRB = j->defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false;
|
||||
ieC6_1_1->sDAP_Configuration.sDAP_Header_UL = j->sDAP_Header_UL;
|
||||
ieC6_1_1->sDAP_Configuration.sDAP_Header_DL = j->sDAP_Header_DL;
|
||||
|
||||
@@ -971,7 +971,7 @@ void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_beare
|
||||
|
||||
drb->id = drb2Setup->dRB_ID;
|
||||
|
||||
drb->defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB;
|
||||
drb->defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB == E1AP_DefaultDRB_true;
|
||||
drb->sDAP_Header_UL = drb2Setup->sDAP_Configuration.sDAP_Header_UL;
|
||||
drb->sDAP_Header_DL = drb2Setup->sDAP_Configuration.sDAP_Header_DL;
|
||||
|
||||
|
||||
@@ -480,7 +480,7 @@ typedef struct Type0_PDCCH_CSS_config_s {
|
||||
uint32_t search_space_frame_period; // in slots
|
||||
uint32_t ssb_length;
|
||||
uint32_t ssb_index;
|
||||
uint32_t cset_start_rb;
|
||||
int32_t cset_start_rb;
|
||||
NR_SubcarrierSpacing_t scs_pdcch;
|
||||
bool active;
|
||||
} NR_Type0_PDCCH_CSS_config_t;
|
||||
|
||||
@@ -4443,6 +4443,8 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD
|
||||
|
||||
type0_PDCCH_CSS_config->n_0 = ((uint32_t)(big_o*(1<<scs_pdcch)) + (uint32_t)(type0_PDCCH_CSS_config->ssb_index*big_m))%num_slot_per_frame;
|
||||
type0_PDCCH_CSS_config->cset_start_rb = ssb_offset_point_a - type0_PDCCH_CSS_config->rb_offset;
|
||||
AssertFatal(type0_PDCCH_CSS_config->cset_start_rb >= 0, "Invalid CSET0 start PRB %d SSB offset point A %d RB offset %d\n",
|
||||
type0_PDCCH_CSS_config->cset_start_rb, ssb_offset_point_a, type0_PDCCH_CSS_config->rb_offset);
|
||||
}
|
||||
|
||||
void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config)
|
||||
|
||||
@@ -348,11 +348,13 @@ typedef struct {
|
||||
int8_t delta_pucch;
|
||||
uint32_t R;
|
||||
uint32_t TBS;
|
||||
int last_ndi;
|
||||
} NR_UE_HARQ_STATUS_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t R;
|
||||
uint32_t TBS;
|
||||
int last_ndi;
|
||||
} NR_UL_HARQ_INFO_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -499,8 +501,6 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
/// measurements from CSI-RS
|
||||
fapi_nr_csirs_measurements_t csirs_measurements;
|
||||
|
||||
/// Last NDI of UL HARQ processes
|
||||
int UL_ndi[NR_MAX_HARQ_PROCESSES];
|
||||
//// FAPI-like interface message
|
||||
fapi_nr_ul_config_request_t *ul_config_request;
|
||||
fapi_nr_dl_config_request_t *dl_config_request;
|
||||
|
||||
@@ -74,6 +74,10 @@ void nr_ue_init_mac(module_id_t module_idP)
|
||||
memset(&mac->ssb_list[i], 0, sizeof(mac->ssb_list[i]));
|
||||
memset(&mac->prach_assoc_pattern[i], 0, sizeof(mac->prach_assoc_pattern[i]));
|
||||
}
|
||||
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) {
|
||||
mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
|
||||
mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
|
||||
@@ -100,8 +104,6 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
|
||||
mac->scheduling_info.lc_sched_info[i].LCGID = 0; // defaults to 0 irrespective of SRB or DRB
|
||||
mac->scheduling_info.lc_sched_info[i].LCID_status = LCID_EMPTY;
|
||||
mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0;
|
||||
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++)
|
||||
mac->UL_ndi[k] = -1; // initialize to invalid value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +144,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
|
||||
// MAC reset according to 38.321 Section 5.12
|
||||
|
||||
nr_ue_mac_default_configs(nr_mac);
|
||||
|
||||
// initialize Bj for each logical channel to zero
|
||||
// Done in default config but to -1 (is that correct?)
|
||||
|
||||
@@ -153,7 +156,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
|
||||
|
||||
// set the NDIs for all uplink HARQ processes to the value 0
|
||||
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++)
|
||||
nr_mac->UL_ndi[k] = -1; // initialize to invalid value
|
||||
nr_mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
|
||||
|
||||
// stop any ongoing RACH procedure
|
||||
if (nr_mac->ra.ra_state < RA_SUCCEEDED)
|
||||
@@ -179,7 +182,8 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
|
||||
memset(&nr_mac->dl_harq_info[k], 0, sizeof(NR_UE_HARQ_STATUS_t));
|
||||
|
||||
// for each DL HARQ process, consider the next received transmission for a TB as the very first transmission
|
||||
// TODO there is nothing in the MAC indicating first transmission
|
||||
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++)
|
||||
nr_mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value
|
||||
|
||||
// release, if any, Temporary C-RNTI
|
||||
nr_mac->ra.t_crnti = 0;
|
||||
|
||||
@@ -681,13 +681,30 @@ static int nr_ue_process_dci_dl_10(module_id_t module_id,
|
||||
/* MCS */
|
||||
dlsch_pdu->mcs = dci->mcs;
|
||||
|
||||
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid];
|
||||
/* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
|
||||
if (dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH ||
|
||||
dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH ||
|
||||
dci->ndi != current_harq->last_ndi) {
|
||||
// new data
|
||||
dlsch_pdu->new_data_indicator = true;
|
||||
current_harq->R = 0;
|
||||
current_harq->TBS = 0;
|
||||
}
|
||||
else
|
||||
dlsch_pdu->new_data_indicator = false;
|
||||
|
||||
if (dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH &&
|
||||
dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH) {
|
||||
current_harq->last_ndi = dci->ndi;
|
||||
}
|
||||
|
||||
dlsch_pdu->qamModOrder = nr_get_Qm_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table);
|
||||
if (dlsch_pdu->qamModOrder == 0) {
|
||||
LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid];
|
||||
int R = nr_get_code_rate_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table);
|
||||
if (R > 0) {
|
||||
dlsch_pdu->targetCodeRate = R;
|
||||
@@ -707,6 +724,11 @@ static int nr_ue_process_dci_dl_10(module_id_t module_id,
|
||||
1);
|
||||
// storing for possible retransmissions
|
||||
current_harq->R = dlsch_pdu->targetCodeRate;
|
||||
if (!dlsch_pdu->new_data_indicator && current_harq->TBS != dlsch_pdu->TBS) {
|
||||
LOG_W(NR_MAC, "NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n",
|
||||
dlsch_pdu->TBS, current_harq->TBS);
|
||||
dlsch_pdu->new_data_indicator = true; // treated as new data
|
||||
}
|
||||
current_harq->TBS = dlsch_pdu->TBS;
|
||||
}
|
||||
else {
|
||||
@@ -716,11 +738,14 @@ static int nr_ue_process_dci_dl_10(module_id_t module_id,
|
||||
|
||||
dlsch_pdu->ldpcBaseGraph = get_BG(dlsch_pdu->TBS, dlsch_pdu->targetCodeRate);
|
||||
|
||||
if (dlsch_pdu->TBS == 0) {
|
||||
LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int bw_tbslbrm = current_DL_BWP ? mac->sc_info.dl_bw_tbslbrm : dlsch_pdu->BWPSize;
|
||||
dlsch_pdu->tbslbrm = nr_compute_tbslbrm(dlsch_pdu->mcs_table, bw_tbslbrm, 1);
|
||||
|
||||
/* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
|
||||
dlsch_pdu->ndi = dci->ndi;
|
||||
/* RV (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
|
||||
dlsch_pdu->rv = dci->rv;
|
||||
/* HARQ_PROCESS_NUMBER (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
|
||||
@@ -801,7 +826,7 @@ static int nr_ue_process_dci_dl_10(module_id_t module_id,
|
||||
"scaling_factor_S=%f\n>>> tpc_pucch=%d\n>>> pucch_res_ind=%d\n>>> pdsch_to_harq_feedback_time_ind=%d\n",
|
||||
dlsch_pdu->vrb_to_prb_mapping,
|
||||
dlsch_pdu->mcs,
|
||||
dlsch_pdu->ndi,
|
||||
dlsch_pdu->new_data_indicator,
|
||||
dlsch_pdu->rv,
|
||||
dlsch_pdu->harq_process_nbr,
|
||||
dci->dai[0].val,
|
||||
@@ -961,13 +986,23 @@ static int nr_ue_process_dci_dl_11(module_id_t module_id,
|
||||
/* MCS (for transport block 1)*/
|
||||
dlsch_pdu->mcs = dci->mcs;
|
||||
/* NDI (for transport block 1)*/
|
||||
dlsch_pdu->ndi = dci->ndi;
|
||||
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid];
|
||||
if (dci->ndi != current_harq->last_ndi) {
|
||||
// new data
|
||||
dlsch_pdu->new_data_indicator = true;
|
||||
current_harq->R = 0;
|
||||
current_harq->TBS = 0;
|
||||
}
|
||||
else {
|
||||
dlsch_pdu->new_data_indicator = false;
|
||||
}
|
||||
current_harq->last_ndi = dci->ndi;
|
||||
/* RV (for transport block 1)*/
|
||||
dlsch_pdu->rv = dci->rv;
|
||||
/* MCS (for transport block 2)*/
|
||||
dlsch_pdu->tb2_mcs = dci->mcs2.val;
|
||||
/* NDI (for transport block 2)*/
|
||||
dlsch_pdu->tb2_ndi = dci->ndi2.val;
|
||||
dlsch_pdu->tb2_new_data_indicator = dci->ndi2.val;
|
||||
/* RV (for transport block 2)*/
|
||||
dlsch_pdu->tb2_rv = dci->rv2.val;
|
||||
/* HARQ_PROCESS_NUMBER */
|
||||
@@ -1124,7 +1159,6 @@ static int nr_ue_process_dci_dl_11(module_id_t module_id,
|
||||
nb_rb_oh = 0;
|
||||
int nb_re_dmrs = ((dmrs_type == NULL) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups;
|
||||
|
||||
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid];
|
||||
int R = nr_get_code_rate_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table);
|
||||
if (R > 0) {
|
||||
dlsch_pdu->targetCodeRate = R;
|
||||
@@ -1137,6 +1171,11 @@ static int nr_ue_process_dci_dl_11(module_id_t module_id,
|
||||
0,
|
||||
Nl);
|
||||
// storing for possible retransmissions
|
||||
if (!dlsch_pdu->new_data_indicator && current_harq->TBS != dlsch_pdu->TBS) {
|
||||
LOG_W(NR_MAC, "NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n",
|
||||
dlsch_pdu->TBS, current_harq->TBS);
|
||||
dlsch_pdu->new_data_indicator = true; // treated as new data
|
||||
}
|
||||
current_harq->R = dlsch_pdu->targetCodeRate;
|
||||
current_harq->TBS = dlsch_pdu->TBS;
|
||||
}
|
||||
@@ -1147,6 +1186,11 @@ static int nr_ue_process_dci_dl_11(module_id_t module_id,
|
||||
|
||||
dlsch_pdu->ldpcBaseGraph = get_BG(dlsch_pdu->TBS, dlsch_pdu->targetCodeRate);
|
||||
|
||||
if (dlsch_pdu->TBS == 0) {
|
||||
LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TBS_LBRM according to section 5.4.2.1 of 38.212
|
||||
AssertFatal(sc_info->maxMIMO_Layers_PDSCH != NULL, "Option with max MIMO layers not configured is not supported\n");
|
||||
int nl_tbslbrm = *sc_info->maxMIMO_Layers_PDSCH < 4 ? *sc_info->maxMIMO_Layers_PDSCH : 4;
|
||||
@@ -3733,11 +3777,8 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
// end of MAC PDU, can ignore the rest.
|
||||
break;
|
||||
// MAC SDU
|
||||
case DL_SCH_LCID_DCCH:
|
||||
// check if LCID is valid at current time.
|
||||
case DL_SCH_LCID_DCCH1:
|
||||
// check if LCID is valid at current time.
|
||||
case DL_SCH_LCID_DTCH ... (DL_SCH_LCID_DTCH + 28):
|
||||
// From values 1 to 32 it equals to the identity of the logical channel
|
||||
case 1 ... 32:
|
||||
if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
|
||||
return;
|
||||
LOG_D(NR_MAC, "%4d.%2d : DLSCH -> LCID %d %d bytes\n", frameP, slot, rx_lcid, mac_len);
|
||||
|
||||
@@ -656,8 +656,14 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
|
||||
}
|
||||
|
||||
/* NDI */
|
||||
pusch_config_pdu->pusch_data.new_data_indicator = dci->ndi != mac->UL_ndi[dci->harq_pid] ? 1 : 0;
|
||||
mac->UL_ndi[dci->harq_pid] = dci->ndi;
|
||||
NR_UL_HARQ_INFO_t *harq = &mac->ul_harq_info[dci->harq_pid];
|
||||
pusch_config_pdu->pusch_data.new_data_indicator = false;
|
||||
if (dci->ndi != harq->last_ndi) {
|
||||
pusch_config_pdu->pusch_data.new_data_indicator = true;
|
||||
// if new data reset harq structure
|
||||
memset(harq, 0, sizeof(*harq));
|
||||
}
|
||||
harq->last_ndi = dci->ndi;
|
||||
/* RV */
|
||||
pusch_config_pdu->pusch_data.rv_index = dci->rv;
|
||||
/* HARQ_PROCESS_NUMBER */
|
||||
@@ -768,7 +774,14 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
|
||||
pusch_config_pdu->target_code_rate = mac->ul_harq_info[pid].R;
|
||||
pusch_config_pdu->pusch_data.tb_size = mac->ul_harq_info[pid].TBS;
|
||||
}
|
||||
|
||||
pusch_config_pdu->ldpcBaseGraph = get_BG(pusch_config_pdu->pusch_data.tb_size << 3, pusch_config_pdu->target_code_rate);
|
||||
|
||||
if (pusch_config_pdu->pusch_data.tb_size == 0) {
|
||||
LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1454,13 +1467,6 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
|
||||
int *slot_tx,
|
||||
const long k2)
|
||||
{
|
||||
AssertFatal(k2 > DURATION_RX_TO_TX,
|
||||
"Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%d). Please set min_rxtxtime at least to %d in gNB config file or gNBs.[0].min_rxtxtime=%d via command line.\n",
|
||||
k2,
|
||||
DURATION_RX_TO_TX,
|
||||
DURATION_RX_TO_TX,
|
||||
DURATION_RX_TO_TX);
|
||||
|
||||
int delta = 0;
|
||||
const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
|
||||
|
||||
@@ -1505,6 +1511,13 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
|
||||
|
||||
} else {
|
||||
|
||||
AssertFatal(k2 > DURATION_RX_TO_TX,
|
||||
"Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%d). Please set min_rxtxtime at least to %d in gNB config file or gNBs.[0].min_rxtxtime=%d via command line.\n",
|
||||
k2,
|
||||
DURATION_RX_TO_TX,
|
||||
DURATION_RX_TO_TX,
|
||||
DURATION_RX_TO_TX);
|
||||
|
||||
if (k2 < 0) { // This can happen when a false DCI is received
|
||||
LOG_W(PHY, "%d.%d. Received k2 %ld\n", current_frame, current_slot, k2);
|
||||
return -1;
|
||||
|
||||
@@ -639,7 +639,8 @@ static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_Ant
|
||||
cfg->num_tlv++;
|
||||
cfg->ssb_table.ssb_subcarrier_offset.value =
|
||||
get_ssb_subcarrier_offset(*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB,
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA);
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
|
||||
*scc->ssbSubcarrierSpacing);
|
||||
|
||||
AssertFatal(cfg->ssb_table.ssb_subcarrier_offset.value < 16,
|
||||
"cannot handle ssb_subcarrier_offset %d resulting from Point A %ld SSB %ld: please increase dl_absoluteFrequencyPointA "
|
||||
|
||||
@@ -688,7 +688,7 @@ void nr_initiate_ra_proc(module_id_t module_idP,
|
||||
}
|
||||
|
||||
NR_SCHED_UNLOCK(&nr_mac->sched_lock);
|
||||
LOG_E(NR_MAC, "[gNB %d][RAPROC] FAILURE: CC_id %d Frame %d initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, preamble_index);
|
||||
LOG_E(NR_MAC, "[gNB %d][RAPROC] FAILURE: CC_id %d %4d.%2d initiating RA procedure for preamble index %d: no free RA process\n", module_idP, CC_id, frameP, slotP, preamble_index);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0);
|
||||
}
|
||||
@@ -768,8 +768,14 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_I(NR_MAC, "[gNB %d][RAPROC] Frame %d, Slot %d : CC_id %d Scheduling retransmission of Msg3 in (%d,%d)\n",
|
||||
module_idP, frame, slot, CC_id, sched_frame, sched_slot);
|
||||
LOG_I(NR_MAC,
|
||||
"%4d%2d: RA RNTI %04x CC_id %d Scheduling retransmission of Msg3 in (%d,%d)\n",
|
||||
frame,
|
||||
slot,
|
||||
ra->rnti,
|
||||
CC_id,
|
||||
sched_frame,
|
||||
sched_slot);
|
||||
|
||||
buffer_index = ul_buffer_index(sched_frame, sched_slot, mu, nr_mac->UL_tti_req_ahead_size);
|
||||
nfapi_nr_ul_tti_request_t *future_ul_tti_req = &nr_mac->UL_tti_req_ahead[CC_id][buffer_index];
|
||||
@@ -1253,7 +1259,8 @@ static void nr_generate_Msg2(module_id_t module_idP,
|
||||
true);
|
||||
|
||||
if (CCEIndex < 0) {
|
||||
LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, ra->rnti);
|
||||
LOG_E(NR_MAC, "cannot find free CCE for Msg2 of RA RNTI 0x%04x!\n", ra->rnti);
|
||||
nr_clear_ra_proc(module_idP, CC_id, frameP, ra);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1455,7 +1462,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
|
||||
}
|
||||
|
||||
ra->state = WAIT_Msg3;
|
||||
LOG_W(NR_MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: rnti %04x RA state %d\n", module_idP, frameP, slotP, ra->rnti, ra->state);
|
||||
LOG_D(NR_MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: rnti %04x RA state %d\n", module_idP, frameP, slotP, ra->rnti, ra->state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1698,7 +1705,6 @@ static void nr_generate_Msg4(module_id_t module_idP,
|
||||
// Need to wait until data for Msg4 is ready
|
||||
if (srb_status.bytes_in_buffer == 0)
|
||||
return;
|
||||
LOG_I(NR_MAC, "(%4d.%2d) SRB%d has %d bytes\n", frameP, slotP, lcid, srb_status.bytes_in_buffer);
|
||||
mac_sdu_length = srb_status.bytes_in_buffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -2376,8 +2376,7 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
|
||||
{
|
||||
NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon;
|
||||
NR_UEs_t *UE_info = &nr_mac->UE_info;
|
||||
LOG_I(NR_MAC, "Adding UE with rnti 0x%04x\n",
|
||||
rntiP);
|
||||
LOG_I(NR_MAC, "Adding new UE context with RNTI 0x%04x\n", rntiP);
|
||||
dump_nr_list(UE_info->list);
|
||||
|
||||
// We will attach at the end, to mitigate race conditions
|
||||
@@ -2851,11 +2850,11 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo
|
||||
|
||||
static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frame, sub_frame_t slot)
|
||||
{
|
||||
LOG_I(NR_MAC, "%4d.%2d RNTI %04x: RRC processing timer expired\n", frame, slot, UE->rnti);
|
||||
LOG_D(NR_MAC, "%4d.%2d RNTI %04x: RRC processing timer expired\n", frame, slot, UE->rnti);
|
||||
|
||||
/* check if there is a new CellGroupConfig to be applied */
|
||||
if (UE->apply_cellgroup && UE->reconfigCellGroup != NULL) {
|
||||
LOG_I(NR_MAC, "%4d.%2d RNTI %04x: Apply CellGroupConfig after RRC processing timer expiry\n", frame, slot, UE->rnti);
|
||||
LOG_D(NR_MAC, "%4d.%2d RNTI %04x: Apply CellGroupConfig after RRC processing timer expiry\n", frame, slot, UE->rnti);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
UE->CellGroup = UE->reconfigCellGroup;
|
||||
UE->reconfigCellGroup = NULL;
|
||||
@@ -2911,7 +2910,7 @@ int nr_mac_enable_ue_rrc_processing_timer(gNB_MAC_INST *mac, NR_UE_info_t *UE, b
|
||||
// frames, after RRC processing timer.
|
||||
UE->UE_sched_ctrl.ta_frame = (mac->frame - 1 + 1024) % 1024;
|
||||
|
||||
LOG_I(NR_MAC, "%4d.%2d UE %04x: Activate RRC processing timer (%d ms)\n", mac->frame, mac->slot, UE->rnti, delay);
|
||||
LOG_D(NR_MAC, "%4d.%2d UE %04x: Activate RRC processing timer (%d ms)\n", mac->frame, mac->slot, UE->rnti, delay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3092,7 +3091,7 @@ void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ct
|
||||
/* to trigger only once: trigger when ul_failure_timer == 1, but timer will
|
||||
* stop at 0 and we wait for a UE release command from upper layers */
|
||||
if (sched_ctrl->ul_failure_timer == 1) {
|
||||
LOG_W(MAC, "request release after UL failure timer expiry\n");
|
||||
LOG_W(MAC, "UE %04x: request release after UL failure timer expiry\n", rnti);
|
||||
f1_ue_data_t ue_data = du_get_f1_ue_data(rnti);
|
||||
f1ap_ue_context_release_req_t request = {
|
||||
.gNB_CU_ue_id = ue_data.secondary_ue,
|
||||
|
||||
@@ -96,6 +96,7 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac,
|
||||
}
|
||||
|
||||
#define MIN_RSRP_VALUE -141
|
||||
#define MAX_RSRP_VALUE -43
|
||||
#define MAX_NUM_SSB 128
|
||||
#define MAX_SSB_SCHED 8
|
||||
#define L1_RSRP_HYSTERIS 10 //considering 10 dBm as hysterisis for avoiding frequent SSB Beam Switching. !Fixme provide exact value if any
|
||||
@@ -109,7 +110,7 @@ int ssb_rsrp_sorted[MAX_NUM_SSB] = {0};
|
||||
//stored -1 for invalid values
|
||||
static const int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0 - 9
|
||||
-1, -1, -1, -1, -1, -1, INT_MIN, -140, -139, -138, // 10 - 19
|
||||
-1, -1, -1, -1, -1, -1, MIN_RSRP_VALUE, -140, -139, -138, // 10 - 19
|
||||
-137, -136, -135, -134, -133, -132, -131, -130, -129, -128, // 20 - 29
|
||||
-127, -126, -125, -124, -123, -122, -121, -120, -119, -118, // 30 - 39
|
||||
-117, -116, -115, -114, -113, -112, -111, -110, -109, -108, // 40 - 49
|
||||
@@ -119,7 +120,7 @@ static const int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = {
|
||||
-77, -76, -75, -74, -73, -72, -71, -70, -69, -68, // 80 - 89
|
||||
-67, -66, -65, -64, -63, -62, -61, -60, -59, -58, // 90 - 99
|
||||
-57, -56, -55, -54, -53, -52, -51, -50, -49, -48, // 100 - 109
|
||||
-47, -46, -45, -44, INT_MAX, -1, -1, -1, -1, -1, // 110 - 119
|
||||
-47, -46, -45, -44, MAX_RSRP_VALUE, -1, -1, -1, -1, -1, // 110 - 119
|
||||
-1, -1, -1, -1, -1, -1, -1, -1 // 120 - 127
|
||||
};
|
||||
|
||||
@@ -455,13 +456,16 @@ static int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, NR_UE_info_t *
|
||||
}
|
||||
|
||||
//returns the measured RSRP value (upper limit)
|
||||
static int get_measured_rsrp(uint8_t index)
|
||||
static bool get_measured_rsrp(uint8_t index, int *rsrp)
|
||||
{
|
||||
//if index is invalid returning minimum rsrp -140
|
||||
if(index <= 15 || index >= 114)
|
||||
return MIN_RSRP_VALUE;
|
||||
if (index <= 15)
|
||||
return false;
|
||||
if (index >= 114)
|
||||
return false;
|
||||
|
||||
return L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[index];
|
||||
*rsrp = L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
//returns the differential RSRP value (upper limit)
|
||||
@@ -477,7 +481,6 @@ static int get_diff_rsrp(uint8_t index, int strongest_rsrp) {
|
||||
//handles triggering of PDCCH and PDSCH MAC CEs
|
||||
static void tci_handling(NR_UE_info_t *UE, frame_t frame, slot_t slot)
|
||||
{
|
||||
int strongest_ssb_rsrp = 0;
|
||||
int cqi_idx = 0;
|
||||
int curr_ssb_beam_index = 0; //ToDo: yet to know how to identify the serving ssb beam index
|
||||
uint8_t target_ssb_beam_index = curr_ssb_beam_index;
|
||||
@@ -520,7 +523,13 @@ static void tci_handling(NR_UE_info_t *UE, frame_t frame, slot_t slot)
|
||||
}
|
||||
|
||||
//if strongest measured RSRP is configured
|
||||
strongest_ssb_rsrp = get_measured_rsrp(sched_ctrl->CSI_report.ssb_cri_report.RSRP);
|
||||
int strongest_ssb_rsrp;
|
||||
int rsrp_index = sched_ctrl->CSI_report.ssb_cri_report.RSRP;
|
||||
bool valid = get_measured_rsrp(rsrp_index, &strongest_ssb_rsrp);
|
||||
if (!valid) {
|
||||
LOG_E(NR_MAC, "UE %04x: reported RSRP index %d invalid\n", UE->rnti, rsrp_index);
|
||||
return;
|
||||
}
|
||||
ssb_rsrp[idx * nb_of_csi_ssb_report] = strongest_ssb_rsrp;
|
||||
LOG_D(NR_MAC,"ssb_rsrp = %d\n",strongest_ssb_rsrp);
|
||||
|
||||
@@ -717,7 +726,13 @@ static void evaluate_rsrp_report(NR_UE_info_t *UE,
|
||||
*cumul_bits += 4;
|
||||
}
|
||||
csi_report->nb_of_csi_ssb_report++;
|
||||
int strongest_ssb_rsrp = get_measured_rsrp(sched_ctrl->CSI_report.ssb_cri_report.RSRP);
|
||||
int strongest_ssb_rsrp;
|
||||
int rsrp_index = sched_ctrl->CSI_report.ssb_cri_report.RSRP;
|
||||
bool valid = get_measured_rsrp(rsrp_index, &strongest_ssb_rsrp);
|
||||
if (!valid) {
|
||||
LOG_E(NR_MAC, "UE %04x: reported RSRP index %d invalid\n", UE->rnti, rsrp_index);
|
||||
return;
|
||||
}
|
||||
NR_mac_stats_t *stats = &UE->mac_stats;
|
||||
// including ssb rsrp in mac stats
|
||||
stats->cumul_rsrp += strongest_ssb_rsrp;
|
||||
|
||||
@@ -377,7 +377,7 @@ static int nr_process_mac_pdu(instance_t module_idP,
|
||||
mac_len = 6;
|
||||
}
|
||||
|
||||
LOG_W(MAC, "[RAPROC] Received SDU for CCCH length %d for UE %04x\n", mac_len, UE->rnti);
|
||||
LOG_D(MAC, "[RAPROC] Received SDU for CCCH length %d for UE %04x\n", mac_len, UE->rnti);
|
||||
|
||||
prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE);
|
||||
mac_rlc_data_ind(module_idP,
|
||||
@@ -509,7 +509,7 @@ void handle_nr_ul_harq(const int CC_idP,
|
||||
bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(nrmac, CC_idP, frame, slot);
|
||||
|
||||
if (!UE || UE_waiting_CFRA_msg3 == true) {
|
||||
LOG_W(NR_MAC, "handle harq for rnti %04x, in RA process\n", crc_pdu->rnti);
|
||||
LOG_D(NR_MAC, "handle harq for rnti %04x, in RA process\n", crc_pdu->rnti);
|
||||
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
|
||||
NR_RA_t *ra = &nrmac->common_channels[CC_idP].ra[i];
|
||||
if (ra->state >= WAIT_Msg3 && ra->rnti == crc_pdu->rnti) {
|
||||
@@ -518,7 +518,7 @@ void handle_nr_ul_harq(const int CC_idP,
|
||||
}
|
||||
}
|
||||
NR_SCHED_UNLOCK(&nrmac->sched_lock);
|
||||
LOG_E(NR_MAC, "%s(): unknown RNTI 0x%04x in PUSCH\n", __func__, crc_pdu->rnti);
|
||||
LOG_E(NR_MAC, "no RA proc for RNTI 0x%04x in Msg3/PUSCH\n", crc_pdu->rnti);
|
||||
return;
|
||||
}
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
@@ -676,9 +676,11 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
}
|
||||
|
||||
if (!get_softmodem_params()->phy_test && UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt >= pusch_failure_thres) {
|
||||
LOG_W(NR_MAC,"Detected UL Failure on PUSCH after %d PUSCH DTX, stopping scheduling\n",
|
||||
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt);
|
||||
nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
|
||||
LOG_W(NR_MAC,
|
||||
"UE %04x: Detected UL Failure on PUSCH after %d PUSCH DTX, stopping scheduling\n",
|
||||
UE->rnti,
|
||||
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt);
|
||||
nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
|
||||
}
|
||||
}
|
||||
} else if(sduP) {
|
||||
@@ -792,7 +794,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
// Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better solution may be implemented
|
||||
mac_remove_nr_ue(gNB_mac, ra->rnti);
|
||||
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
|
||||
LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg.3 to have UE come back with new RA attempt\n", ra->rnti);
|
||||
LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", ra->rnti);
|
||||
return;
|
||||
} else {
|
||||
// Reset Msg4_ACKed to not schedule ULSCH and DLSCH before RRC Reconfiguration
|
||||
|
||||
@@ -260,7 +260,7 @@ static void set_QoSConfig(const f1ap_ue_context_modif_req_t *req, NR_UE_sched_ct
|
||||
f1ap_drb_to_be_setup_t *drb_p = &req->drbs_to_be_setup[i];
|
||||
uint8_t nb_qos_flows = drb_p->drb_info.flows_to_be_setup_length;
|
||||
long drb_id = drb_p->drb_id;
|
||||
LOG_I(NR_MAC, "In %s: number of QOS flows mapped to DRB_id %d: %ld \n", __func__, drb_count, drb_id);
|
||||
LOG_I(NR_MAC, "number of QOS flows mapped to DRB_id %ld: %d\n", drb_id, nb_qos_flows);
|
||||
|
||||
for (int q = 0; q < nb_qos_flows; q++) {
|
||||
f1ap_flows_mapped_to_drb_t *qos_flow = &drb_p->drb_info.flows_mapped_to_drb[q];
|
||||
@@ -338,9 +338,6 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
UE->capability = ue_cap;
|
||||
if (ue_cap != NULL) {
|
||||
// store the new UE capabilities, and update the cellGroupConfig
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability);
|
||||
UE->capability = ue_cap;
|
||||
LOG_I(NR_MAC, "UE %04x: received capabilities, updating CellGroupConfig\n", UE->rnti);
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,6 @@ static void f1_setup_request_direct(const f1ap_setup_req_t *req)
|
||||
static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp)
|
||||
{
|
||||
DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length);
|
||||
AssertFatal(req->drbs_to_be_setup_length == 0, "not implemented\n");
|
||||
|
||||
(void) req; /* we don't need the request -- it is to set up GTP in F1 case */
|
||||
MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP);
|
||||
@@ -85,6 +84,13 @@ static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req,
|
||||
for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i)
|
||||
f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i];
|
||||
}
|
||||
if (resp->drbs_to_be_setup_length > 0) {
|
||||
DevAssert(resp->drbs_to_be_setup != NULL);
|
||||
f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length;
|
||||
f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup));
|
||||
for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i)
|
||||
f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i];
|
||||
}
|
||||
|
||||
f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information));
|
||||
AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n");
|
||||
|
||||
@@ -103,7 +103,6 @@ static void f1_setup_request_f1ap(const f1ap_setup_req_t *req)
|
||||
static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp)
|
||||
{
|
||||
DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length);
|
||||
AssertFatal(req->drbs_to_be_setup_length == 0, "not implmented\n");
|
||||
|
||||
DevAssert(req->srbs_to_be_setup_length == resp->srbs_to_be_setup_length);
|
||||
MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP);
|
||||
@@ -118,6 +117,13 @@ static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, c
|
||||
for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i)
|
||||
f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i];
|
||||
}
|
||||
if (resp->drbs_to_be_setup_length > 0) {
|
||||
DevAssert(resp->drbs_to_be_setup != NULL);
|
||||
f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length;
|
||||
f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup));
|
||||
for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i)
|
||||
f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i];
|
||||
}
|
||||
|
||||
f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information));
|
||||
AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n");
|
||||
|
||||
@@ -85,7 +85,6 @@ void clear_mac_stats(gNB_MAC_INST *gNB) {
|
||||
|
||||
size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp)
|
||||
{
|
||||
int num = 1;
|
||||
const char *begin = output;
|
||||
const char *end = output + strlen;
|
||||
|
||||
@@ -99,11 +98,19 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
||||
NR_mac_stats_t *stats = &UE->mac_stats;
|
||||
const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0;
|
||||
|
||||
output += snprintf(output, end - output, "UE RNTI %04x CU-UE-ID ", UE->rnti);
|
||||
if (du_exists_f1_ue_data(UE->rnti)) {
|
||||
f1_ue_data_t ued = du_get_f1_ue_data(UE->rnti);
|
||||
output += snprintf(output, end - output, "%d", ued.secondary_ue);
|
||||
} else {
|
||||
output += snprintf(output, end-output, "(none)");
|
||||
}
|
||||
|
||||
bool in_sync = !sched_ctrl->ul_failure;
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE RNTI %04x (%d) PH %d dB PCMAX %d dBm, average RSRP %d (%d meas)\n",
|
||||
UE->rnti,
|
||||
num++,
|
||||
" %s PH %d dB PCMAX %d dBm, average RSRP %d (%d meas)\n",
|
||||
in_sync ? "in-sync" : "out-of-sync",
|
||||
sched_ctrl->ph,
|
||||
sched_ctrl->pcmax,
|
||||
avg_rsrp,
|
||||
@@ -132,19 +139,16 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS %d\n",
|
||||
", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS (%d) %d\n",
|
||||
stats->dl.errors,
|
||||
stats->pucch0_DTX,
|
||||
sched_ctrl->dl_bler_stats.bler,
|
||||
UE->current_DL_BWP.mcsTableIdx,
|
||||
sched_ctrl->dl_bler_stats.mcs);
|
||||
if (reset_rsrp) {
|
||||
stats->num_rsrp_meas = 0;
|
||||
stats->cumul_rsrp = 0;
|
||||
}
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: dlsch_total_bytes %"PRIu64"\n",
|
||||
UE->rnti, stats->dl.total_bytes);
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: ulsch_rounds ", UE->rnti);
|
||||
@@ -154,16 +158,17 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
", ulsch_DTX %d, ulsch_errors %"PRIu64", BLER %.5f MCS %d\n",
|
||||
stats->ulsch_DTX,
|
||||
", ulsch_errors %"PRIu64", ulsch_DTX %d, BLER %.5f MCS (%d) %d\n",
|
||||
stats->ul.errors,
|
||||
stats->ulsch_DTX,
|
||||
sched_ctrl->ul_bler_stats.bler,
|
||||
UE->current_UL_BWP.mcs_table,
|
||||
sched_ctrl->ul_bler_stats.mcs);
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
"UE %04x: ulsch_total_bytes_scheduled %"PRIu64", ulsch_total_bytes_received %"PRIu64"\n",
|
||||
UE->rnti,
|
||||
stats->ulsch_total_bytes_scheduled, stats->ul.total_bytes);
|
||||
"UE %04x: MAC: TX %14"PRIu64" RX %14"PRIu64" bytes\n",
|
||||
UE->rnti, stats->dl.total_bytes, stats->ul.total_bytes);
|
||||
|
||||
for (int i = 0; i < sched_ctrl->dl_lc_num; i++) {
|
||||
int lc_id = sched_ctrl->dl_lc_ids[i];
|
||||
|
||||
@@ -184,8 +184,8 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
|
||||
sdap_data_req,
|
||||
&resp_n3);
|
||||
AssertFatal(ret >= 0, "Unable to create GTP Tunnel for NG-U\n");
|
||||
AssertFatal(resp_n3.num_tunnels == req->numPDUSessions, "could not create all tunnels\n");
|
||||
resp_pdu->teId = resp_n3.gnb_NGu_teid[i];
|
||||
AssertFatal(resp_n3.num_tunnels == req_pdu->numDRB2Setup, "could not create all tunnels\n");
|
||||
resp_pdu->teId = resp_n3.gnb_NGu_teid[0];
|
||||
memcpy(&resp_pdu->tlAddress, &resp_n3.gnb_addr.buffer, 4);
|
||||
|
||||
// create PDCP bearers. This will also create SDAP bearers
|
||||
@@ -240,6 +240,7 @@ void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req)
|
||||
instance_t f1inst = get_f1_gtp_instance();
|
||||
|
||||
for (int i=0; i < req->numPDUSessionsMod; i++) {
|
||||
DevAssert(req->pduSessionMod[i].sessionId > 0);
|
||||
LOG_I(E1AP,
|
||||
"UE %d: updating PDU session ID %ld (%ld bearers)\n",
|
||||
req->gNB_cu_up_ue_id,
|
||||
@@ -278,6 +279,7 @@ void e1_bearer_release_cmd(const e1ap_bearer_release_cmd_t *cmd)
|
||||
if (f1inst >= 0) // is there F1-U?
|
||||
newGtpuDeleteAllTunnels(f1inst, cmd->gNB_cu_up_ue_id);
|
||||
nr_pdcp_remove_UE(cmd->gNB_cu_up_ue_id);
|
||||
nr_sdap_delete_ue_entities(cmd->gNB_cu_up_ue_id);
|
||||
if (need_ue_id_mgmt) {
|
||||
cu_remove_f1_ue_data(cmd->gNB_cu_up_ue_id);
|
||||
}
|
||||
|
||||
@@ -925,7 +925,7 @@ void add_drb(int is_gnb,
|
||||
has_integrity ? integrity_key : NULL);
|
||||
nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb);
|
||||
|
||||
LOG_D(PDCP, "added drb %d to UE ID %ld\n", drb_id, UEid);
|
||||
LOG_I(PDCP, "added drb %d to UE ID %ld\n", drb_id, UEid);
|
||||
|
||||
new_nr_sdap_entity(is_gnb, has_sdap_rx, has_sdap_tx, UEid, pdusession_id, is_sdap_DefaultDRB, drb_id, mappedQFIs2Add, mappedQFIs2AddCount);
|
||||
}
|
||||
@@ -1193,6 +1193,7 @@ void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id)
|
||||
drb->release_entity(drb);
|
||||
drb->delete_entity(drb);
|
||||
ue->drb[drb_id - 1] = NULL;
|
||||
LOG_I(PDCP, "release DRB %d of UE %ld\n", drb_id, ue_id);
|
||||
}
|
||||
else
|
||||
LOG_E(PDCP, "Attempting to release DRB%d but it is not configured\n", drb_id);
|
||||
|
||||
@@ -77,7 +77,7 @@ void handle_nr_rach(NR_UL_IND_t *UL_info)
|
||||
bool in_timewindow = frame_diff == 0 || (frame_diff == 1 && UL_info->slot < 7);
|
||||
|
||||
if (UL_info->rach_ind.number_of_pdus > 0 && in_timewindow) {
|
||||
LOG_A(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",
|
||||
LOG_D(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",
|
||||
UL_info->frame, UL_info->slot, UL_info->rach_ind.sfn, UL_info->rach_ind.slot);
|
||||
for (int i = 0; i < UL_info->rach_ind.number_of_pdus; i++) {
|
||||
UL_info->rach_ind.number_of_pdus--;
|
||||
|
||||
@@ -51,8 +51,20 @@ static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_c
|
||||
f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_REQ(msg);
|
||||
*f1ap_msg = *req;
|
||||
AssertFatal(req->cu_to_du_rrc_information == NULL, "cu_to_du_rrc_information not supported yet\n");
|
||||
AssertFatal(req->drbs_to_be_setup == NULL, "drbs_to_be_setup not supported yet\n");
|
||||
AssertFatal(req->srbs_to_be_setup == NULL, "drbs_to_be_setup not supported yet\n");
|
||||
if (req->drbs_to_be_setup_length > 0) {
|
||||
int n = req->drbs_to_be_setup_length;
|
||||
f1ap_msg->drbs_to_be_setup_length = n;
|
||||
f1ap_msg->drbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->drbs_to_be_setup));
|
||||
AssertFatal(f1ap_msg->drbs_to_be_setup != NULL, "out of memory\n");
|
||||
memcpy(f1ap_msg->drbs_to_be_setup, req->drbs_to_be_setup, n * sizeof(*f1ap_msg->drbs_to_be_setup));
|
||||
}
|
||||
if (req->srbs_to_be_setup_length > 0) {
|
||||
int n = req->srbs_to_be_setup_length;
|
||||
f1ap_msg->srbs_to_be_setup_length = n;
|
||||
f1ap_msg->srbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->srbs_to_be_setup));
|
||||
AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n");
|
||||
memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup));
|
||||
}
|
||||
if (req->rrc_container_length > 0) {
|
||||
f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container));
|
||||
AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n");
|
||||
|
||||
@@ -1768,7 +1768,8 @@ NR_BCCH_BCH_Message_t *get_new_MIB_NR(const NR_ServingCellConfigCommon_t *scc)
|
||||
int ssb_subcarrier_offset = 31; // default value for NSA
|
||||
if (get_softmodem_params()->sa) {
|
||||
ssb_subcarrier_offset = get_ssb_subcarrier_offset(*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB,
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA);
|
||||
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
|
||||
*scc->ssbSubcarrierSpacing);
|
||||
}
|
||||
mib->message.choice.mib->ssb_SubcarrierOffset = ssb_subcarrier_offset & 15;
|
||||
|
||||
|
||||
@@ -224,6 +224,7 @@ typedef struct drb_s {
|
||||
} drb_t;
|
||||
|
||||
typedef enum {
|
||||
RRC_ACTION_NONE, /* no transaction ongoing */
|
||||
RRC_SETUP,
|
||||
RRC_SETUP_FOR_REESTABLISHMENT,
|
||||
RRC_REESTABLISH,
|
||||
@@ -232,12 +233,12 @@ typedef enum {
|
||||
RRC_DEDICATED_RECONF,
|
||||
RRC_PDUSESSION_ESTABLISH,
|
||||
RRC_PDUSESSION_MODIFY,
|
||||
RRC_PDUSESSION_RELEASE
|
||||
RRC_PDUSESSION_RELEASE,
|
||||
RRC_UECAPABILITY_ENQUIRY,
|
||||
} rrc_action_t;
|
||||
|
||||
typedef struct gNB_RRC_UE_s {
|
||||
drb_t established_drbs[MAX_DRBS_PER_UE];
|
||||
uint8_t DRB_active[MAX_DRBS_PER_UE];
|
||||
NR_DRB_ToReleaseList_t *DRB_ReleaseList;
|
||||
|
||||
NR_SRB_INFO_TABLE_ENTRY Srb[maxSRBs]; // 3gpp max is 3 SRBs, number 1..3, we waste the entry 0 for code simplicity
|
||||
@@ -245,6 +246,8 @@ typedef struct gNB_RRC_UE_s {
|
||||
NR_HANDOVER_INFO *handover_info;
|
||||
NR_MeasResults_t *measResults;
|
||||
|
||||
bool as_security_active;
|
||||
|
||||
byte_array_t ue_cap_buffer;
|
||||
NR_UE_NR_Capability_t* UE_Capability_nr;
|
||||
int UE_Capability_size;
|
||||
@@ -275,12 +278,8 @@ typedef struct gNB_RRC_UE_s {
|
||||
/* Information from UE RRC Setup Request */
|
||||
NR_UE_S_TMSI Initialue_identity_5g_s_TMSI;
|
||||
uint64_t ng_5G_S_TMSI_Part1;
|
||||
uint16_t ng_5G_S_TMSI_Part2;
|
||||
NR_EstablishmentCause_t establishment_cause;
|
||||
|
||||
/* Information from UE RRCReestablishmentRequest */
|
||||
NR_ReestablishmentCause_t reestablishment_cause;
|
||||
|
||||
uint32_t rrc_ue_id;
|
||||
uint64_t amf_ue_ngap_id;
|
||||
nr_rrc_guami_t ue_guami;
|
||||
@@ -303,19 +302,15 @@ typedef struct gNB_RRC_UE_s {
|
||||
uint8_t e_rab_release_command_flag;
|
||||
uint32_t ue_rrc_inactivity_timer;
|
||||
uint32_t ue_reestablishment_counter;
|
||||
uint32_t ue_reconfiguration_after_reestablishment_counter;
|
||||
NR_CellGroupId_t cellGroupId;
|
||||
uint32_t ue_reconfiguration_counter;
|
||||
struct NR_SpCellConfig *spCellConfig;
|
||||
struct NR_CellGroupConfig__sCellToAddModList *sCellconfig;
|
||||
struct NR_CellGroupConfig__sCellToReleaseList *sCellconfigRelease;
|
||||
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_BearerBonfig;
|
||||
struct NR_CellGroupConfig__rlc_BearerToReleaseList *rlc_BearerRelease;
|
||||
struct NR_MAC_CellGroupConfig *mac_CellGroupConfig;
|
||||
struct NR_PhysicalCellGroupConfig *physicalCellGroupConfig;
|
||||
|
||||
/* Nas Pdu */
|
||||
ngap_pdu_t nas_pdu;
|
||||
|
||||
/* hack, see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() for more info */
|
||||
int max_delays_pdu_session;
|
||||
|
||||
} gNB_RRC_UE_t;
|
||||
|
||||
typedef struct rrc_gNB_ue_context_s {
|
||||
|
||||
@@ -81,7 +81,9 @@ int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2
|
||||
void
|
||||
rrc_gNB_generate_SecurityModeCommand(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rrc_gNB_ue_context_t *const ue_context_pP
|
||||
rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
int n_drbs,
|
||||
const f1ap_drb_to_be_setup_t *drbs
|
||||
);
|
||||
|
||||
unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP);
|
||||
@@ -125,6 +127,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
|
||||
|
||||
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP);
|
||||
|
||||
bool ue_associated_to_cuup(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue);
|
||||
sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue);
|
||||
sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue, int sst, int sd);
|
||||
int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req);
|
||||
|
||||
+450
-647
File diff suppressed because it is too large
Load Diff
+178
-151
@@ -145,11 +145,6 @@ nr_rrc_pdcp_config_security(
|
||||
nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc);
|
||||
nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint);
|
||||
|
||||
if (!IS_SOFTMODEM_IQPLAYER) {
|
||||
SET_LOG_DUMP(DEBUG_SECURITY) ;
|
||||
}
|
||||
|
||||
|
||||
if ( LOG_DUMPFLAG( DEBUG_SECURITY ) ) {
|
||||
if (print_keys == 1 ) {
|
||||
print_keys =0;
|
||||
@@ -201,10 +196,13 @@ rrc_gNB_send_NGAP_NAS_FIRST_REQ(
|
||||
|
||||
/* Fill UE identities with available information */
|
||||
req->ue_identity.presenceMask = NGAP_UE_IDENTITIES_NONE;
|
||||
/* Fill 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;
|
||||
if (UE->Initialue_identity_5g_s_TMSI.presence) {
|
||||
/* Fill 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;
|
||||
}
|
||||
|
||||
/* selected_plmn_identity: IE is 1-based, convert to 0-based (C array) */
|
||||
int selected_plmn_identity = rrcSetupComplete->selectedPLMN_Identity - 1;
|
||||
@@ -359,6 +357,109 @@ static int decodePDUSessionResourceSetup(pdusession_t *session)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession_t *sessions, uint64_t ueAggMaxBitRateDownlink)
|
||||
{
|
||||
e1ap_bearer_setup_req_t bearer_req = {0};
|
||||
|
||||
e1ap_nssai_t cuup_nssai = {0};
|
||||
for (int i = 0; i < n; i++) {
|
||||
rrc_pdu_session_param_t *pduSession = find_pduSession(UE, sessions[i].pdusession_id, true);
|
||||
pdusession_t *session = &pduSession->param;
|
||||
session->pdusession_id = sessions[i].pdusession_id;
|
||||
LOG_I(NR_RRC, "Adding pdusession %d, total nb of sessions %d\n", session->pdusession_id, UE->nb_of_pdusessions);
|
||||
session->pdu_session_type = sessions[i].pdu_session_type;
|
||||
session->nas_pdu = sessions[i].nas_pdu;
|
||||
session->pdusessionTransfer = sessions[i].pdusessionTransfer;
|
||||
session->nssai = sessions[i].nssai;
|
||||
decodePDUSessionResourceSetup(session);
|
||||
bearer_req.gNB_cu_cp_ue_id = UE->rrc_ue_id;
|
||||
bearer_req.cipheringAlgorithm = UE->ciphering_algorithm;
|
||||
bearer_req.integrityProtectionAlgorithm = UE->integrity_algorithm;
|
||||
nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, (uint8_t *)bearer_req.encryptionKey);
|
||||
nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, (uint8_t *)bearer_req.integrityProtectionKey);
|
||||
bearer_req.ueDlAggMaxBitRate = ueAggMaxBitRateDownlink;
|
||||
pdu_session_to_setup_t *pdu = bearer_req.pduSession + bearer_req.numPDUSessions;
|
||||
bearer_req.numPDUSessions++;
|
||||
pdu->sessionId = session->pdusession_id;
|
||||
pdu->nssai = sessions[i].nssai;
|
||||
if (cuup_nssai.sst == 0)
|
||||
cuup_nssai = pdu->nssai; /* for CU-UP selection below */
|
||||
|
||||
pdu->integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed;
|
||||
|
||||
pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed;
|
||||
pdu->teId = session->gtp_teid;
|
||||
memcpy(&pdu->tlAddress, session->upf_addr.buffer, 4); // Fixme: dirty IPv4 target
|
||||
|
||||
/* we assume for the moment one DRB per PDU session. Activate the bearer,
|
||||
* and configure in RRC. */
|
||||
int drb_id = get_next_available_drb_id(UE);
|
||||
drb_t *rrc_drb = generateDRB(UE,
|
||||
drb_id,
|
||||
pduSession,
|
||||
rrc->configuration.enable_sdap,
|
||||
rrc->security.do_drb_integrity,
|
||||
rrc->security.do_drb_ciphering);
|
||||
|
||||
pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding
|
||||
for (int j=0; j < pdu->numDRB2Setup; j++) {
|
||||
DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j;
|
||||
|
||||
drb->id = rrc_drb->drb_id;
|
||||
|
||||
struct sdap_config_s *sdap_config = &rrc_drb->cnAssociation.sdap_config;
|
||||
drb->defaultDRB = sdap_config->defaultDRB;
|
||||
drb->sDAP_Header_UL = sdap_config->sdap_HeaderUL;
|
||||
drb->sDAP_Header_DL = sdap_config->sdap_HeaderDL;
|
||||
|
||||
struct pdcp_config_s *pdcp_config = &rrc_drb->pdcp_config;
|
||||
drb->pDCP_SN_Size_UL = pdcp_config->pdcp_SN_SizeUL;
|
||||
drb->pDCP_SN_Size_DL = pdcp_config->pdcp_SN_SizeDL;
|
||||
drb->discardTimer = pdcp_config->discardTimer;
|
||||
drb->reorderingTimer = pdcp_config->t_Reordering;
|
||||
|
||||
drb->rLC_Mode = rrc->configuration.um_on_default_drb ? E1AP_RLC_Mode_rlc_um_bidirectional : E1AP_RLC_Mode_rlc_am;
|
||||
|
||||
drb->numCellGroups = 1; // assume one cell group associated with a DRB
|
||||
|
||||
for (int k=0; k < drb->numCellGroups; k++) {
|
||||
cell_group_t *cellGroup = drb->cellGroupList + k;
|
||||
cellGroup->id = 0; // MCG
|
||||
}
|
||||
|
||||
drb->numQosFlow2Setup = session->nb_qos;
|
||||
for (int k=0; k < drb->numQosFlow2Setup; k++) {
|
||||
qos_flow_to_setup_t *qos_flow = drb->qosFlows + k;
|
||||
pdusession_level_qos_parameter_t *qos_session = session->qos + k;
|
||||
|
||||
qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics;
|
||||
qos_flow->qfi = qos_session->qfi;
|
||||
qos_char->qos_type = qos_session->fiveQI_type;
|
||||
if (qos_char->qos_type == dynamic) {
|
||||
qos_char->dynamic.fiveqi = qos_session->fiveQI;
|
||||
qos_char->dynamic.qos_priority_level = qos_session->qos_priority;
|
||||
} else {
|
||||
qos_char->non_dynamic.fiveqi = qos_session->fiveQI;
|
||||
qos_char->non_dynamic.qos_priority_level = qos_session->qos_priority;
|
||||
}
|
||||
|
||||
ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority;
|
||||
ngap_allocation_retention_priority_t *rent_priority_in = &qos_session->allocation_retention_priority;
|
||||
rent_priority->priority_level = rent_priority_in->priority_level;
|
||||
rent_priority->preemption_capability = rent_priority_in->pre_emp_capability;
|
||||
rent_priority->preemption_vulnerability = rent_priority_in->pre_emp_vulnerability;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Limitation: we assume one fixed CU-UP per UE. We base the selection on
|
||||
* NSSAI, but the UE might have multiple PDU sessions with differing slices,
|
||||
* in which we might need to select different CU-UPs. In this case, we would
|
||||
* actually need to group the E1 bearer context setup for the different
|
||||
* CU-UPs, and send them to the different CU-UPs. */
|
||||
sctp_assoc_t assoc_id = get_new_cuup_for_ue(rrc, UE, cuup_nssai.sst, cuup_nssai.sd);
|
||||
rrc->cucp_cuup.bearer_context_setup(assoc_id, &bearer_req);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t instance)
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -381,40 +482,6 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
|
||||
}
|
||||
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, UE->rrc_ue_id, 0, 0);
|
||||
UE->amf_ue_ngap_id = req->amf_ue_ngap_id;
|
||||
uint8_t nb_pdusessions_tosetup = req->nb_of_pdusessions;
|
||||
if (nb_pdusessions_tosetup) {
|
||||
AssertFatal(false, "PDU sessions in Initial context setup request not handled by E1 yet\n");
|
||||
/* this code should pass by E1: commenting here for future reference, but
|
||||
* already handled in E1 for the "normal case" of a separate request for
|
||||
* PDU session setup.
|
||||
gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0};
|
||||
for (int i = 0; i < nb_pdusessions_tosetup; i++) {
|
||||
UE->nb_of_pdusessions++;
|
||||
if(UE->pduSession[i].status >= PDU_SESSION_STATUS_DONE)
|
||||
continue;
|
||||
UE->pduSession[i].status = PDU_SESSION_STATUS_NEW;
|
||||
UE->pduSession[i].param = req->pdusession_param[i];
|
||||
create_tunnel_req.num_tunnels++;
|
||||
create_tunnel_req.pdusession_id[i] = req->pdusession_param[i].pdusession_id;
|
||||
create_tunnel_req.outgoing_teid[i] = req->pdusession_param[i].gtp_teid;
|
||||
// To be developped: hardcoded first flow
|
||||
create_tunnel_req.outgoing_qfi[i] = req->pdusession_param[i].qos[0].qfi;
|
||||
create_tunnel_req.dst_addr[i].length = req->pdusession_param[i].upf_addr.length;
|
||||
memcpy(create_tunnel_req.dst_addr[i].buffer, req->pdusession_param[i].upf_addr.buffer, sizeof(create_tunnel_req.dst_addr[i].buffer));
|
||||
LOG_I(NR_RRC, "PDUSESSION SETUP: local index %d teid %u, pdusession id %d \n", i, create_tunnel_req.outgoing_teid[i], create_tunnel_req.pdusession_id[i]);
|
||||
}
|
||||
create_tunnel_req.ue_id = UE->rrc_ue_id;
|
||||
gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp = {0};
|
||||
int ret = gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, &create_tunnel_resp, nr_pdcp_data_req_drb, sdap_data_req);
|
||||
if (ret != 0) {
|
||||
LOG_E(NR_RRC, "rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE %x\n", UE->rnti);
|
||||
AssertFatal(false, "release timer not implemented\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(&ctxt, &create_tunnel_resp, 0);
|
||||
*/
|
||||
}
|
||||
|
||||
/* NAS PDU */
|
||||
// this is malloced pointers, we pass it for later free()
|
||||
@@ -427,12 +494,18 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
|
||||
/* configure only integrity, ciphering comes after receiving SecurityModeComplete */
|
||||
nr_rrc_pdcp_config_security(&ctxt, ue_context_p, 0);
|
||||
|
||||
rrc_gNB_generate_SecurityModeCommand(&ctxt, ue_context_p);
|
||||
|
||||
// in case, send the S1SP initial context response if it is not sent with the attach complete message
|
||||
if (UE->StatusRrc == NR_RRC_RECONFIGURED) {
|
||||
LOG_I(NR_RRC, "Sending rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP, cause %ld\n", UE->reestablishment_cause);
|
||||
rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(&ctxt, ue_context_p);
|
||||
uint8_t nb_pdusessions_tosetup = req->nb_of_pdusessions;
|
||||
/* if there are PDU sessions to setup, first send them to the CU-UP, then
|
||||
* send the UE Context setup with Security commend. Else go to the security
|
||||
* command directly. */
|
||||
if (nb_pdusessions_tosetup > 0) {
|
||||
trigger_bearer_setup(RC.nrrrc[instance],
|
||||
UE,
|
||||
req->nb_of_pdusessions,
|
||||
req->pdusession_param,
|
||||
/*req->ueAggMaxBitRateDownlink*/ 0);
|
||||
} else {
|
||||
rrc_gNB_generate_SecurityModeCommand(&ctxt, ue_context_p, 0, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -466,12 +539,13 @@ void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(const protocol_ctxt_t *const c
|
||||
resp->pdusessions[pdusession].associated_qos_flows[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi;
|
||||
resp->pdusessions[pdusession].associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL;
|
||||
}
|
||||
} else {
|
||||
} else if (session->status != PDU_SESSION_STATUS_ESTABLISHED) {
|
||||
session->status = PDU_SESSION_STATUS_FAILED;
|
||||
pdusession_failed_t *fail = &resp->pdusessions_failed[pdu_sessions_failed];
|
||||
fail->pdusession_id = session->param.pdusession_id;
|
||||
fail->cause = NGAP_CAUSE_RADIO_NETWORK;
|
||||
fail->cause_value = NGAP_CauseRadioNetwork_unknown_PDU_session_ID;
|
||||
pdu_sessions_failed++;
|
||||
resp->pdusessions_failed[pdusession].pdusession_id = session->param.pdusession_id;
|
||||
// TODO add cause when it will be integrated
|
||||
resp->pdusessions_failed[pdusession].cause = NGAP_CAUSE_RADIO_NETWORK;
|
||||
resp->pdusessions_failed[pdusession].cause_value = NGAP_CauseRadioNetwork_unknown_PDU_session_ID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,7 +585,7 @@ static NR_CipheringAlgorithm_t rrc_gNB_select_ciphering(
|
||||
}
|
||||
}
|
||||
|
||||
LOG_I(RRC, "selecting ciphering algorithm %d\n", ret);
|
||||
LOG_D(RRC, "selecting ciphering algorithm %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -547,7 +621,7 @@ static e_NR_IntegrityProtAlgorithm rrc_gNB_select_integrity(
|
||||
}
|
||||
}
|
||||
|
||||
LOG_I(RRC, "selecting integrity algorithm %d\n", ret);
|
||||
LOG_D(RRC, "selecting integrity algorithm %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -585,13 +659,13 @@ static int rrc_gNB_process_security(const protocol_ctxt_t *const ctxt_pP, rrc_gN
|
||||
}
|
||||
|
||||
LOG_I(NR_RRC,
|
||||
"[gNB %d][UE %x] Selected security algorithms (%p): %lx, %x, %s\n",
|
||||
"[gNB %d][UE %d] Selected security algorithms (%p): ciphering %lx, integrity %x (algorithms %s)\n",
|
||||
ctxt_pP->module_id,
|
||||
UE->rnti,
|
||||
UE->rrc_ue_id,
|
||||
security_capabilities_pP,
|
||||
(unsigned long)cipheringAlgorithm,
|
||||
cipheringAlgorithm,
|
||||
integrityProtAlgorithm,
|
||||
changed ? "changed" : "same");
|
||||
changed ? "changed" : "are the same");
|
||||
return changed;
|
||||
}
|
||||
|
||||
@@ -715,9 +789,11 @@ rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(
|
||||
pdu_sessions_done++;
|
||||
} else if (session->status != PDU_SESSION_STATUS_ESTABLISHED) {
|
||||
session->status = PDU_SESSION_STATUS_FAILED;
|
||||
resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = session->param.pdusession_id;
|
||||
pdusession_failed_t *fail = &resp->pdusessions_failed[pdu_sessions_failed];
|
||||
fail->pdusession_id = session->param.pdusession_id;
|
||||
fail->cause = NGAP_CAUSE_RADIO_NETWORK;
|
||||
fail->cause_value = NGAP_CauseRadioNetwork_unknown_PDU_session_ID;
|
||||
pdu_sessions_failed++;
|
||||
// TODO add cause when it will be integrated
|
||||
}
|
||||
resp->nb_of_pdusessions = pdu_sessions_done;
|
||||
resp->nb_of_pdusessions_failed = pdu_sessions_failed;
|
||||
@@ -739,6 +815,28 @@ rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(
|
||||
return;
|
||||
}
|
||||
|
||||
/* \brief checks if any transaction is ongoing for any xid of this UE */
|
||||
static bool transaction_ongoing(const gNB_RRC_UE_t *UE)
|
||||
{
|
||||
for (int xid = 0; xid < 4; ++xid)
|
||||
if (UE->xids[xid] != RRC_ACTION_NONE)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* \brief delays the ongoing transaction (in msg_p) by setting a timer to wait
|
||||
* 10ms; upon expiry, delivers to RRC, which sends the message to itself */
|
||||
static void delay_transaction(MessageDef *msg_p, int wait_us)
|
||||
{
|
||||
MessageDef *new = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_PDUSESSION_SETUP_REQ);
|
||||
ngap_pdusession_setup_req_t *n = &NGAP_PDUSESSION_SETUP_REQ(new);
|
||||
*n = NGAP_PDUSESSION_SETUP_REQ(msg_p);
|
||||
|
||||
int instance = msg_p->ittiMsgHeader.originInstance;
|
||||
long timer_id;
|
||||
timer_setup(0, wait_us, TASK_RRC_GNB, instance, TIMER_ONE_SHOT, new, &timer_id);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t instance)
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -762,98 +860,27 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
|
||||
return ;
|
||||
}
|
||||
|
||||
UE->rrc_ue_id = msg->gNB_ue_ngap_id;
|
||||
AssertFatal(UE->rrc_ue_id == msg->gNB_ue_ngap_id, "logic bug\n");
|
||||
UE->amf_ue_ngap_id = msg->amf_ue_ngap_id;
|
||||
e1ap_bearer_setup_req_t bearer_req = {0};
|
||||
|
||||
|
||||
e1ap_nssai_t cuup_nssai = {0};
|
||||
for (int i = 0; i < msg->nb_pdusessions_tosetup; i++) {
|
||||
rrc_pdu_session_param_t *pduSession = find_pduSession(UE, msg->pdusession_setup_params[i].pdusession_id, true);
|
||||
pdusession_t *session = &pduSession->param;
|
||||
session->pdusession_id = msg->pdusession_setup_params[i].pdusession_id;
|
||||
LOG_I(NR_RRC, "Adding pdusession %d, total nb of sessions %d\n", session->pdusession_id, UE->nb_of_pdusessions);
|
||||
session->pdu_session_type = msg->pdusession_setup_params[i].pdu_session_type;
|
||||
session->nas_pdu = msg->pdusession_setup_params[i].nas_pdu;
|
||||
session->pdusessionTransfer = msg->pdusession_setup_params[i].pdusessionTransfer;
|
||||
session->nssai = msg->pdusession_setup_params[i].nssai;
|
||||
decodePDUSessionResourceSetup(session);
|
||||
bearer_req.gNB_cu_cp_ue_id = msg->gNB_ue_ngap_id;
|
||||
bearer_req.cipheringAlgorithm = UE->ciphering_algorithm;
|
||||
bearer_req.integrityProtectionAlgorithm = UE->integrity_algorithm;
|
||||
nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, (uint8_t *)bearer_req.encryptionKey);
|
||||
nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, (uint8_t *)bearer_req.integrityProtectionKey);
|
||||
bearer_req.ueDlAggMaxBitRate = msg->ueAggMaxBitRateDownlink;
|
||||
pdu_session_to_setup_t *pdu = bearer_req.pduSession + bearer_req.numPDUSessions;
|
||||
bearer_req.numPDUSessions++;
|
||||
pdu->sessionId = session->pdusession_id;
|
||||
pdu->nssai = msg->pdusession_setup_params[i].nssai;
|
||||
if (cuup_nssai.sst == 0)
|
||||
cuup_nssai = pdu->nssai; /* for CU-UP selection below */
|
||||
pdu->integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed;
|
||||
|
||||
pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed;
|
||||
pdu->teId = session->gtp_teid;
|
||||
memcpy(&pdu->tlAddress, session->upf_addr.buffer, 4); // Fixme: dirty IPv4 target
|
||||
pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding
|
||||
for (int j=0; j < pdu->numDRB2Setup; j++) {
|
||||
DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j;
|
||||
|
||||
drb->id = i + j + UE->nb_of_pdusessions;
|
||||
|
||||
drb->defaultDRB = true;
|
||||
|
||||
drb->sDAP_Header_UL = !(rrc->configuration.enable_sdap);
|
||||
drb->sDAP_Header_DL = !(rrc->configuration.enable_sdap);
|
||||
|
||||
drb->pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_18;
|
||||
drb->pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_18;
|
||||
|
||||
drb->discardTimer = E1AP_DiscardTimer_infinity;
|
||||
drb->reorderingTimer = E1AP_T_Reordering_ms100;
|
||||
|
||||
drb->rLC_Mode = E1AP_RLC_Mode_rlc_am;
|
||||
|
||||
drb->numCellGroups = 1; // assume one cell group associated with a DRB
|
||||
|
||||
for (int k=0; k < drb->numCellGroups; k++) {
|
||||
cell_group_t *cellGroup = drb->cellGroupList + k;
|
||||
cellGroup->id = 0; // MCG
|
||||
}
|
||||
|
||||
drb->numQosFlow2Setup = session->nb_qos;
|
||||
for (int k=0; k < drb->numQosFlow2Setup; k++) {
|
||||
qos_flow_to_setup_t *qos_flow = drb->qosFlows + k;
|
||||
pdusession_level_qos_parameter_t *qos_session = session->qos + k;
|
||||
|
||||
qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics;
|
||||
qos_flow->qfi = qos_session->qfi;
|
||||
qos_char->qos_type = qos_session->fiveQI_type;
|
||||
if (qos_char->qos_type == dynamic) {
|
||||
qos_char->dynamic.fiveqi = qos_session->fiveQI;
|
||||
qos_char->dynamic.qos_priority_level = qos_session->qos_priority;
|
||||
} else {
|
||||
qos_char->non_dynamic.fiveqi = qos_session->fiveQI;
|
||||
qos_char->non_dynamic.qos_priority_level = qos_session->qos_priority;
|
||||
}
|
||||
|
||||
ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority;
|
||||
ngap_allocation_retention_priority_t *rent_priority_in = &qos_session->allocation_retention_priority;
|
||||
rent_priority->priority_level = rent_priority_in->priority_level;
|
||||
rent_priority->preemption_capability = rent_priority_in->pre_emp_capability;
|
||||
rent_priority->preemption_vulnerability = rent_priority_in->pre_emp_vulnerability;
|
||||
}
|
||||
}
|
||||
/* This is a hack. We observed that with some UEs, PDU session requests might
|
||||
* come in quick succession, faster than the RRC reconfiguration for the PDU
|
||||
* session requests can be carried out (UE is doing reconfig, and second PDU
|
||||
* session request arrives). We don't have currently the means to "queue up"
|
||||
* these transactions, which would probably involve some rework of the RRC.
|
||||
* To still allow these requests to come in and succeed, we below check and delay transactions
|
||||
* for 10ms. However, to not accidentally end up in infinite loops, the
|
||||
* maximum number is capped on a per-UE basis as indicated in variable
|
||||
* max_delays_pdu_session. */
|
||||
if (UE->max_delays_pdu_session > 0 && transaction_ongoing(UE)) {
|
||||
int wait_us = 10000;
|
||||
LOG_D(RRC, "UE %d: delay PDU session setup by %d us, pending %d retries\n", UE->rrc_ue_id, wait_us, UE->max_delays_pdu_session);
|
||||
delay_transaction(msg_p, wait_us);
|
||||
UE->max_delays_pdu_session--;
|
||||
return;
|
||||
}
|
||||
int xid = rrc_gNB_get_next_transaction_identifier(instance);
|
||||
UE->xids[xid] = RRC_PDUSESSION_ESTABLISH;
|
||||
/* Limitation: we assume one fixed CU-UP per UE. We base the selection on
|
||||
* NSSAI, but the UE might have multiple PDU sessions with differing slices,
|
||||
* in which we might need to select different CU-UPs. In this case, we would
|
||||
* actually need to group the E1 bearer context setup for the different
|
||||
* CU-UPs, and send them to the different CU-UPs. */
|
||||
sctp_assoc_t assoc_id = get_new_cuup_for_ue(rrc, UE, cuup_nssai.sst, cuup_nssai.sd);
|
||||
rrc->cucp_cuup.bearer_context_setup(assoc_id, &bearer_req);
|
||||
|
||||
trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, msg->pdusession_setup_params, msg->ueAggMaxBitRateDownlink);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ rrc_gNB_ue_context_t *rrc_gNB_allocate_new_ue_context(gNB_RRC_INST *rrc_instance
|
||||
for(int i = 0; i < NB_RB_MAX; i++)
|
||||
new_p->ue_context.pduSession[i].xid = -1;
|
||||
|
||||
LOG_I(NR_RRC, "Returning new RRC UE context RRC ue id: %d\n", new_p->ue_context.rrc_ue_id);
|
||||
LOG_D(NR_RRC, "Returning new RRC UE context RRC ue id: %d\n", new_p->ue_context.rrc_ue_id);
|
||||
return(new_p);
|
||||
}
|
||||
|
||||
@@ -188,6 +188,7 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id,
|
||||
"UE F1 Context for ID %d already exists, logic bug\n",
|
||||
ue->rrc_ue_id);
|
||||
cu_add_f1_ue_data(ue->rrc_ue_id, &ue_data);
|
||||
ue->max_delays_pdu_session = 20; /* see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() */
|
||||
|
||||
RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p);
|
||||
LOG_I(NR_RRC,
|
||||
|
||||
@@ -75,14 +75,16 @@ static const nr_rrc_cuup_container_t *select_cuup_round_robin(size_t n_t, const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ue_associated_to_cuup(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue)
|
||||
{
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id);
|
||||
return ue_data.e1_assoc_id != 0;
|
||||
}
|
||||
|
||||
sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue)
|
||||
{
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id);
|
||||
if (ue_data.e1_assoc_id == 0) {
|
||||
LOG_W(RRC, "UE %d should be associated to CU-UP, but is not\n", ue->rrc_ue_id);
|
||||
/* we could possibly check the SST/SD from the PDU session */
|
||||
return get_new_cuup_for_ue(rrc, ue, 0, 0);
|
||||
}
|
||||
AssertFatal(ue_data.e1_assoc_id != 0, "UE %d should be associated to CU-UP, but is not\n", ue->rrc_ue_id);
|
||||
LOG_D(RRC, "UE %d using CU-UP assoc_id %d\n", ue->rrc_ue_id, ue_data.e1_assoc_id);
|
||||
return ue_data.e1_assoc_id;
|
||||
}
|
||||
|
||||
@@ -37,62 +37,82 @@ rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create)
|
||||
return ue->pduSession + j;
|
||||
}
|
||||
|
||||
void generateDRB(gNB_RRC_UE_t *ue,
|
||||
uint8_t drb_id,
|
||||
rrc_pdu_session_param_t *pduSession,
|
||||
bool enable_sdap,
|
||||
int do_drb_integrity,
|
||||
int do_drb_ciphering)
|
||||
rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id)
|
||||
{
|
||||
int i;
|
||||
int qos_flow_index;
|
||||
drb_t *est_drb = &ue->established_drbs[drb_id - 1];
|
||||
if (est_drb->status == DRB_INACTIVE) {
|
||||
/* DRB Management */
|
||||
est_drb->drb_id = drb_id;
|
||||
est_drb->reestablishPDCP = -1;
|
||||
est_drb->recoverPDCP = -1;
|
||||
for (i = 0; i < MAX_DRBS_PER_UE; i++) {
|
||||
if ((est_drb->cnAssociation.sdap_config.pdusession_id == 0
|
||||
|| est_drb->cnAssociation.sdap_config.pdusession_id == pduSession->param.pdusession_id)
|
||||
&& est_drb->defaultDRBid == 0) {
|
||||
est_drb->cnAssociation.sdap_config.defaultDRB = true;
|
||||
est_drb->defaultDRBid = drb_id;
|
||||
}
|
||||
}
|
||||
/* SDAP Configuration */
|
||||
est_drb->cnAssociation.present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config;
|
||||
est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->param.pdusession_id;
|
||||
if (enable_sdap) {
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present;
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present;
|
||||
} else {
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent;
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent;
|
||||
}
|
||||
for (qos_flow_index = 0; qos_flow_index < pduSession->param.nb_qos; qos_flow_index++) {
|
||||
est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->param.qos[qos_flow_index].qfi;
|
||||
if (pduSession->param.qos[qos_flow_index].fiveQI > 5)
|
||||
est_drb->status = DRB_ACTIVE_NONGBR;
|
||||
else
|
||||
est_drb->status = DRB_ACTIVE;
|
||||
}
|
||||
/* PDCP Configuration */
|
||||
est_drb->pdcp_config.discardTimer = NR_PDCP_Config__drb__discardTimer_infinity;
|
||||
est_drb->pdcp_config.pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits;
|
||||
est_drb->pdcp_config.pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits;
|
||||
est_drb->pdcp_config.t_Reordering = NR_PDCP_Config__t_Reordering_ms100;
|
||||
est_drb->pdcp_config.headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
|
||||
est_drb->pdcp_config.headerCompression.NotUsed = 0;
|
||||
if (do_drb_integrity)
|
||||
est_drb->pdcp_config.integrityProtection = NR_PDCP_Config__drb__integrityProtection_enabled;
|
||||
else
|
||||
est_drb->pdcp_config.integrityProtection = 1;
|
||||
if (do_drb_ciphering)
|
||||
est_drb->pdcp_config.ext1.cipheringDisabled = 1;
|
||||
else
|
||||
est_drb->pdcp_config.ext1.cipheringDisabled = NR_PDCP_Config__ext1__cipheringDisabled_true;
|
||||
const drb_t *drb = &ue->established_drbs[drb_id - 1];
|
||||
if (drb->status == DRB_INACTIVE) {
|
||||
LOG_E(NR_RRC, "UE %d: DRB %d inactive\n", ue->rrc_ue_id, drb_id);
|
||||
return NULL;
|
||||
}
|
||||
int id = drb->cnAssociation.sdap_config.pdusession_id;
|
||||
return find_pduSession(ue, id, false);
|
||||
}
|
||||
|
||||
drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id)
|
||||
{
|
||||
DevAssert(drb_id > 0 && drb_id < 32);
|
||||
DevAssert(ue != NULL);
|
||||
|
||||
return &ue->established_drbs[drb_id - 1];
|
||||
}
|
||||
|
||||
drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
uint8_t drb_id,
|
||||
const rrc_pdu_session_param_t *pduSession,
|
||||
bool enable_sdap,
|
||||
int do_drb_integrity,
|
||||
int do_drb_ciphering)
|
||||
{
|
||||
DevAssert(ue != NULL);
|
||||
|
||||
LOG_I(NR_RRC, "UE %d: configure DRB ID %d for PDU session ID %d\n", ue->rrc_ue_id, drb_id, pduSession->param.pdusession_id);
|
||||
|
||||
drb_t *est_drb = &ue->established_drbs[drb_id - 1];
|
||||
DevAssert(est_drb->status == DRB_INACTIVE);
|
||||
|
||||
est_drb->status = DRB_ACTIVE;
|
||||
est_drb->drb_id = drb_id;
|
||||
est_drb->reestablishPDCP = -1;
|
||||
est_drb->recoverPDCP = -1;
|
||||
est_drb->cnAssociation.sdap_config.defaultDRB = true;
|
||||
est_drb->defaultDRBid = drb_id;
|
||||
|
||||
/* SDAP Configuration */
|
||||
est_drb->cnAssociation.present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config;
|
||||
est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->param.pdusession_id;
|
||||
if (enable_sdap) {
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present;
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present;
|
||||
} else {
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent;
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent;
|
||||
}
|
||||
for (int qos_flow_index = 0; qos_flow_index < pduSession->param.nb_qos; qos_flow_index++) {
|
||||
est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->param.qos[qos_flow_index].qfi;
|
||||
if (pduSession->param.qos[qos_flow_index].fiveQI > 5)
|
||||
est_drb->status = DRB_ACTIVE_NONGBR;
|
||||
else
|
||||
est_drb->status = DRB_ACTIVE;
|
||||
}
|
||||
/* PDCP Configuration */
|
||||
est_drb->pdcp_config.discardTimer = NR_PDCP_Config__drb__discardTimer_infinity;
|
||||
est_drb->pdcp_config.pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits;
|
||||
est_drb->pdcp_config.pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits;
|
||||
est_drb->pdcp_config.t_Reordering = NR_PDCP_Config__t_Reordering_ms100;
|
||||
est_drb->pdcp_config.headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
|
||||
est_drb->pdcp_config.headerCompression.NotUsed = 0;
|
||||
if (do_drb_integrity)
|
||||
est_drb->pdcp_config.integrityProtection = NR_PDCP_Config__drb__integrityProtection_enabled;
|
||||
else
|
||||
est_drb->pdcp_config.integrityProtection = 1;
|
||||
if (do_drb_ciphering)
|
||||
est_drb->pdcp_config.ext1.cipheringDisabled = 1;
|
||||
else
|
||||
est_drb->pdcp_config.ext1.cipheringDisabled = NR_PDCP_Config__ext1__cipheringDisabled_true;
|
||||
|
||||
drb_t *rrc_drb = get_drb(ue, drb_id);
|
||||
DevAssert(rrc_drb == est_drb); /* to double check that we create the same which we would retrieve */
|
||||
return rrc_drb;
|
||||
}
|
||||
|
||||
NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1)
|
||||
@@ -143,27 +163,20 @@ NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1)
|
||||
return DRB_config;
|
||||
}
|
||||
|
||||
uint8_t next_available_drb(gNB_RRC_UE_t *ue, rrc_pdu_session_param_t *pdusession, bool is_gbr)
|
||||
uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue)
|
||||
{
|
||||
uint8_t drb_id;
|
||||
|
||||
if (0 /*!is_gbr*/) { /* Find if Non-GBR DRB exists in the same PDU Session */
|
||||
for (drb_id = 0; drb_id < MAX_DRBS_PER_UE; drb_id++)
|
||||
if (pdusession->param.used_drbs[drb_id] == DRB_ACTIVE_NONGBR)
|
||||
return drb_id + 1;
|
||||
}
|
||||
/* GBR Flow or a Non-GBR DRB does not exist in the same PDU Session, find an available DRB */
|
||||
for (drb_id = 0; drb_id < MAX_DRBS_PER_UE; drb_id++)
|
||||
if (ue->DRB_active[drb_id] == DRB_INACTIVE)
|
||||
for (uint8_t drb_id = 0; drb_id < MAX_DRBS_PER_UE; drb_id++)
|
||||
if (ue->established_drbs[drb_id].status == DRB_INACTIVE)
|
||||
return drb_id + 1;
|
||||
/* From this point, we need to handle the case that all DRBs are already used by the UE. */
|
||||
LOG_E(RRC, "Error - All the DRBs are used - Handle this\n");
|
||||
return DRB_INACTIVE;
|
||||
}
|
||||
|
||||
bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id) {
|
||||
DevAssert(drb_id > 0);
|
||||
if(ue->DRB_active[drb_id-1] == DRB_ACTIVE)
|
||||
return true;
|
||||
return false;
|
||||
bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id)
|
||||
{
|
||||
drb_t *drb = get_drb(ue, drb_id);
|
||||
if (drb == NULL)
|
||||
return DRB_INACTIVE;
|
||||
return drb->status != DRB_INACTIVE;
|
||||
}
|
||||
|
||||
@@ -39,23 +39,36 @@
|
||||
/// @param drb_t drb_asn1
|
||||
/// @return Returns the ASN1 DRB-ToAddMod structs.
|
||||
NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1);
|
||||
/// @brief Creates and stores a DRB in the gNB_RRC_UE_t struct, it doesn't create the actual entity,
|
||||
/// to create the actual entity use the generateDRB_ASN1.
|
||||
|
||||
/// @brief retrieve the data structure representing DRB with ID drb_id of UE ue
|
||||
drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id);
|
||||
|
||||
/// @brief Creates and stores a DRB in the gNB_RRC_UE_t struct
|
||||
/// @param ue The gNB_RRC_UE_t struct that holds information for the UEs
|
||||
/// @param drb_id The Data Radio Bearer Identity to be created for the established DRB.
|
||||
/// @param pduSession The PDU Session that the DRB is created for.
|
||||
/// @param enable_sdap If true the SDAP header will be added to the packet, else it will not add or search for SDAP header.
|
||||
/// @param do_drb_integrity
|
||||
/// @param do_drb_ciphering
|
||||
void generateDRB(gNB_RRC_UE_t *ue,
|
||||
uint8_t drb_id,
|
||||
rrc_pdu_session_param_t *pduSession,
|
||||
bool enable_sdap,
|
||||
int do_drb_integrity,
|
||||
int do_drb_ciphering);
|
||||
uint8_t next_available_drb(gNB_RRC_UE_t *ue, rrc_pdu_session_param_t *pdusession, bool is_gbr);
|
||||
/// @return returns a pointer to the generated DRB structure
|
||||
drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
uint8_t drb_id,
|
||||
const rrc_pdu_session_param_t *pduSession,
|
||||
bool enable_sdap,
|
||||
int do_drb_integrity,
|
||||
int do_drb_ciphering);
|
||||
|
||||
/// @brief return the next available (inactive) DRB ID of UE ue
|
||||
uint8_t get_next_available_drb_id(gNB_RRC_UE_t *ue);
|
||||
|
||||
/// @brief check if DRB with ID drb_id of UE ue is active
|
||||
bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id);
|
||||
|
||||
/// @brief retrieve PDU session of UE ue with ID id, optionally creating it if
|
||||
/// create is true
|
||||
rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create);
|
||||
|
||||
/// @brief get PDU session of UE ue through the DRB drb_id
|
||||
rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -311,6 +311,7 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst)
|
||||
rrc->uecap_file = uecap_file;
|
||||
|
||||
memset(&rrc->timers_and_constants, 0, sizeof(rrc->timers_and_constants));
|
||||
set_default_timers_and_constants(&rrc->timers_and_constants);
|
||||
|
||||
for (int i = 0; i < NB_CNX_UE; i++) {
|
||||
rrcPerNB_t *ptr = &rrc->perNB[i];
|
||||
|
||||
@@ -120,11 +120,14 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc)
|
||||
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
|
||||
|
||||
bool t300_expired = nr_timer_tick(&timers->T300);
|
||||
if(t300_expired)
|
||||
if(t300_expired) {
|
||||
LOG_W(NR_RRC, "Timer T300 expired\n");
|
||||
handle_t300_expiry(rrc);
|
||||
}
|
||||
|
||||
bool t304_expired = nr_timer_tick(&timers->T304);
|
||||
if(t304_expired) {
|
||||
LOG_W(NR_RRC, "Timer T304 expired\n");
|
||||
// TODO
|
||||
// For T304 of MCG, in case of the handover from NR or intra-NR
|
||||
// handover, initiate the RRC re-establishment procedure;
|
||||
@@ -134,6 +137,7 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc)
|
||||
|
||||
bool t310_expired = nr_timer_tick(&timers->T310);
|
||||
if(t310_expired) {
|
||||
LOG_W(NR_RRC, "Timer T310 expired\n");
|
||||
// TODO
|
||||
// handle detection of radio link failure
|
||||
// as described in 5.3.10.3 of 38.331
|
||||
@@ -142,6 +146,7 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc)
|
||||
|
||||
bool t311_expired = nr_timer_tick(&timers->T311);
|
||||
if(t311_expired) {
|
||||
LOG_W(NR_RRC, "Timer T311 expired\n");
|
||||
// Upon T311 expiry, the UE shall perform the actions upon going to RRC_IDLE
|
||||
// with release cause 'RRC connection failure'
|
||||
nr_rrc_going_to_IDLE(rrc, RRC_CONNECTION_FAILURE, NULL);
|
||||
@@ -577,7 +582,7 @@ void set_default_timers_and_constants(NR_UE_Timers_Constants_t *tac)
|
||||
{
|
||||
// 38.331 9.2.3 Default values timers and constants
|
||||
nr_timer_setup(&tac->T310, 1000, 10); // 10ms step
|
||||
nr_timer_setup(&tac->T310, 30000, 10); // 10ms step
|
||||
nr_timer_setup(&tac->T311, 30000, 10); // 10ms step
|
||||
tac->N310_k = 1;
|
||||
tac->N311_k = 1;
|
||||
}
|
||||
|
||||
@@ -556,7 +556,7 @@ bool nr_sdap_delete_ue_entities(ue_id_t ue_id)
|
||||
entityPrev->next_entity = entityPtr->next_entity;
|
||||
free(entityPtr);
|
||||
entityPtr = entityPrev->next_entity;
|
||||
LOG_D(SDAP, "Successfully deleted Entity.\n");
|
||||
LOG_I(SDAP, "Successfully deleted SDAP entity for UE %ld\n", ue_id);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ extern int asn1_xer_print;
|
||||
# define NGAP_WARN(x, args...) LOG_W(NGAP, x, ##args)
|
||||
# define NGAP_TRAF(x, args...) LOG_I(NGAP, x, ##args)
|
||||
# define NGAP_INFO(x, args...) LOG_I(NGAP, x, ##args)
|
||||
# define NGAP_DEBUG(x, args...) LOG_I(NGAP, x, ##args)
|
||||
# define NGAP_DEBUG(x, args...) LOG_D(NGAP, x, ##args)
|
||||
|
||||
#define NGAP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \
|
||||
do { \
|
||||
@@ -118,7 +118,7 @@ extern int asn1_xer_print;
|
||||
if (mandatory) { \
|
||||
AssertFatal(NGAP, "NGAP_FIND_PROTOCOLIE_BY_ID ie is NULL (searching for ie: %ld)\n", IE_ID); \
|
||||
} else { \
|
||||
NGAP_INFO("NGAP_FIND_PROTOCOLIE_BY_ID ie is NULL (searching for ie: %ld)\n", IE_ID); \
|
||||
NGAP_DEBUG("NGAP_FIND_PROTOCOLIE_BY_ID ie is NULL (searching for ie: %ld)\n", IE_ID); \
|
||||
} \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
@@ -732,7 +732,7 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32
|
||||
asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateDL),
|
||||
&(msg->ue_ambr.br_dl));
|
||||
} else {
|
||||
NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate\n");
|
||||
NGAP_WARN("could not find NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -755,6 +755,16 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32
|
||||
NGAP_PDUSessionResourceSetupItemCxtReq_t *item_p = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i];
|
||||
msg->pdusession_param[i].pdusession_id = item_p->pDUSessionID;
|
||||
|
||||
OCTET_STRING_TO_INT8(&item_p->s_NSSAI.sST, msg->pdusession_param[i].nssai.sst);
|
||||
if (item_p->s_NSSAI.sD != NULL) {
|
||||
uint8_t *sd_p = (uint8_t *)&msg->pdusession_param[i].nssai.sd;
|
||||
sd_p[0] = item_p->s_NSSAI.sD->buf[0];
|
||||
sd_p[1] = item_p->s_NSSAI.sD->buf[1];
|
||||
sd_p[2] = item_p->s_NSSAI.sD->buf[2];
|
||||
} else {
|
||||
msg->pdusession_param[i].nssai.sd = 0xffffff;
|
||||
}
|
||||
|
||||
if (item_p->nAS_PDU) {
|
||||
allocCopy(&msg->pdusession_param[i].nas_pdu, *item_p->nAS_PDU);
|
||||
}
|
||||
@@ -775,7 +785,7 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32
|
||||
|
||||
AssertFatal(ie, "AllowedNSSAI not present, forging 2 NSSAI\n");
|
||||
|
||||
NGAP_INFO("AllowedNSSAI.list.count %d\n", ie->value.choice.AllowedNSSAI.list.count);
|
||||
NGAP_DEBUG("AllowedNSSAI.list.count %d\n", ie->value.choice.AllowedNSSAI.list.count);
|
||||
msg->nb_allowed_nssais = ie->value.choice.AllowedNSSAI.list.count;
|
||||
|
||||
for(i = 0; i < ie->value.choice.AllowedNSSAI.list.count; i++) {
|
||||
|
||||
@@ -95,8 +95,8 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
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("[gNB %ld] Chose AMF '%s' (assoc_id %d) through GUAMI MCC %d MNC %d AMFRI %d AMFSI %d AMFPT %d\n",
|
||||
instance,
|
||||
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,
|
||||
@@ -115,8 +115,8 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
|
||||
if (amf_desc_p) {
|
||||
NGAP_INFO(
|
||||
"[gNB %ld] Chose AMF '%s' (assoc_id %d) through S-TMSI AMFSI %d and selected PLMN Identity index %d MCC %d MNC %d\n",
|
||||
instance,
|
||||
"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,
|
||||
@@ -134,8 +134,8 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
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("[gNB %ld] Chose AMF '%s' (assoc_id %d) through selected PLMN Identity index %d MCC %d MNC %d\n",
|
||||
instance,
|
||||
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,
|
||||
@@ -153,7 +153,7 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
amf_desc_p = ngap_gNB_nnsf_select_amf(instance_p, UEfirstReq->establishment_cause);
|
||||
|
||||
if (amf_desc_p) {
|
||||
NGAP_INFO("[gNB %ld] Chose AMF '%s' (assoc_id %d) through highest relative capacity\n", instance, amf_desc_p->amf_name, amf_desc_p->assoc_id);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_FiveG_S_TMSI;
|
||||
AMF_SETID_TO_BIT_STRING(UEfirstReq->ue_identity.s_tmsi.amf_set_id, &ie->value.choice.FiveG_S_TMSI.aMFSetID);
|
||||
AMF_SETID_TO_BIT_STRING(UEfirstReq->ue_identity.s_tmsi.amf_pointer, &ie->value.choice.FiveG_S_TMSI.aMFPointer);
|
||||
AMF_POINTER_TO_BIT_STRING(UEfirstReq->ue_identity.s_tmsi.amf_pointer, &ie->value.choice.FiveG_S_TMSI.aMFPointer);
|
||||
M_TMSI_TO_OCTET_STRING(UEfirstReq->ue_identity.s_tmsi.m_tmsi, &ie->value.choice.FiveG_S_TMSI.fiveG_TMSI);
|
||||
}
|
||||
|
||||
@@ -631,7 +631,14 @@ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_r
|
||||
GTP_TEID_TO_ASN1(initial_ctxt_resp_p->pdusessions[i].gtp_teid, &tmp->gTP_TEID);
|
||||
allocAddrCopy(&tmp->transportLayerAddress, initial_ctxt_resp_p->pdusessions[i].gNB_addr);
|
||||
|
||||
NGAP_DEBUG("initial_ctxt_resp_p: pdusession ID %ld\n", item->pDUSessionID);
|
||||
NGAP_DEBUG("initial_ctxt_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld, TEID %u\n",
|
||||
item->pDUSessionID,
|
||||
tmp->transportLayerAddress.buf[0],
|
||||
tmp->transportLayerAddress.buf[1],
|
||||
tmp->transportLayerAddress.buf[2],
|
||||
tmp->transportLayerAddress.buf[3],
|
||||
tmp->transportLayerAddress.size,
|
||||
initial_ctxt_resp_p->pdusessions[i].gtp_teid);
|
||||
|
||||
/* associatedQosFlowList. number of 1? */
|
||||
for(int j=0; j < initial_ctxt_resp_p->pdusessions[i].nb_of_qos_flow; j++) {
|
||||
@@ -692,11 +699,11 @@ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_r
|
||||
|
||||
case NGAP_CAUSE_NOTHING:
|
||||
default:
|
||||
LOG_E(NR_RRC, "Unknown PDU session failure cause %d\n", initial_ctxt_resp_p->pdusessions_failed[i].cause);
|
||||
AssertFatal(false, "Unknown PDU session failure cause %d\n", initial_ctxt_resp_p->pdusessions_failed[i].cause);
|
||||
break;
|
||||
}
|
||||
|
||||
NGAP_DEBUG("initial context setup response: failed pdusession ID %ld\n", item->pDUSessionID);
|
||||
NGAP_INFO("initial context setup response: failed pdusession ID %ld\n", item->pDUSessionID);
|
||||
asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, &pdusessionUnTransfer);
|
||||
AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded);
|
||||
item->pDUSessionResourceSetupUnsuccessfulTransfer.buf = res.buffer;
|
||||
@@ -885,13 +892,14 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_re
|
||||
asn1cCalloc(pdusessionTransfer.dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel, tmp);
|
||||
GTP_TEID_TO_ASN1(pdusession->gtp_teid, &tmp->gTP_TEID);
|
||||
allocAddrCopy(&tmp->transportLayerAddress, pdusession->gNB_addr);
|
||||
NGAP_DEBUG("pdusession_setup_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld \n",
|
||||
NGAP_DEBUG("pdusession_setup_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld, TEID %u\n",
|
||||
item->pDUSessionID,
|
||||
tmp->transportLayerAddress.buf[0],
|
||||
tmp->transportLayerAddress.buf[1],
|
||||
tmp->transportLayerAddress.buf[2],
|
||||
tmp->transportLayerAddress.buf[3],
|
||||
tmp->transportLayerAddress.size);
|
||||
tmp->transportLayerAddress.size,
|
||||
pdusession->gtp_teid);
|
||||
/* associatedQosFlowList. number of 1? */
|
||||
for(int j=0; j < pdusession_setup_resp_p->pdusessions[i].nb_of_qos_flow; j++) {
|
||||
asn1cSequenceAdd(pdusessionTransfer.dLQosFlowPerTNLInformation.associatedQosFlowList.list, NGAP_AssociatedQosFlowItem_t, ass_qos_item_p);
|
||||
@@ -923,7 +931,6 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_re
|
||||
ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListSURes;
|
||||
|
||||
for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions_failed; i++) {
|
||||
LOG_W(NGAP,"add a failed session\n");
|
||||
pdusession_failed_t *pdusession_failed = pdusession_setup_resp_p->pdusessions_failed + i;
|
||||
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceFailedToSetupListSURes.list, NGAP_PDUSessionResourceFailedToSetupItemSURes_t, item);
|
||||
NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t pdusessionUnTransfer_p = {0};
|
||||
@@ -960,10 +967,10 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ngap_pdusession_setup_re
|
||||
|
||||
case NGAP_CAUSE_NOTHING:
|
||||
default:
|
||||
LOG_E(NR_RRC, "Unknown PDU session failure cause %d\n", pdusession_failed->cause);
|
||||
AssertFatal(false, "Unknown PDU session failure cause %d\n", pdusession_failed->cause);
|
||||
break;
|
||||
}
|
||||
NGAP_DEBUG("pdusession setup response: failed pdusession ID %ld\n", item->pDUSessionID);
|
||||
NGAP_INFO("pdusession setup response: failed pdusession ID %ld\n", item->pDUSessionID);
|
||||
|
||||
asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, &pdusessionUnTransfer_p);
|
||||
item->pDUSessionResourceSetupUnsuccessfulTransfer.buf = res.buffer;
|
||||
@@ -1124,7 +1131,7 @@ int ngap_gNB_pdusession_modify_resp(instance_t instance, ngap_pdusession_modify_
|
||||
|
||||
case NGAP_CAUSE_NOTHING:
|
||||
default:
|
||||
LOG_E(NR_RRC, "Unknown PDU session failure cause %d\n", pdusession_modify_resp_p->pdusessions_failed[i].cause);
|
||||
AssertFatal(false, "Unknown PDU session failure cause %d\n", pdusession_modify_resp_p->pdusessions_failed[i].cause);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1136,7 +1143,7 @@ int ngap_gNB_pdusession_modify_resp(instance_t instance, ngap_pdusession_modify_
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceModifyUnsuccessfulTransfer, pdusessionTransfer_p);
|
||||
|
||||
NGAP_DEBUG("pdusession_modify_resp: failed pdusession ID %ld\n", item->pDUSessionID);
|
||||
NGAP_INFO("pdusession_modify_resp: failed pdusession ID %ld\n", item->pDUSessionID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -735,10 +735,10 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp
|
||||
}
|
||||
|
||||
if ( t->lastWroteTS != 0 && fabs((double)t->lastWroteTS-timestamp) > (double)CirSize)
|
||||
LOG_E(HW, "Discontinuous TX gap too large Tx:%lu, %lu\n", t->lastWroteTS, timestamp);
|
||||
LOG_W(HW, "Discontinuous TX gap too large Tx:%lu, %lu\n", t->lastWroteTS, timestamp);
|
||||
|
||||
if (t->lastWroteTS > timestamp+nsamps)
|
||||
LOG_E(HW, "Not supported to send Tx out of order (same in USRP) %lu, %lu\n", t->lastWroteTS, timestamp);
|
||||
LOG_W(HW, "Not supported to send Tx out of order %lu, %lu\n", t->lastWroteTS, timestamp);
|
||||
|
||||
t->lastWroteTS=timestamp+nsamps;
|
||||
|
||||
@@ -872,14 +872,14 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
|
||||
} else if (b->lastReceivedTS == b->th.timestamp) {
|
||||
// normal case
|
||||
} else {
|
||||
LOG_E(HW, "Received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp);
|
||||
LOG_W(HW, "Received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp);
|
||||
b->trashingPacket=true;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&Sockmutex);
|
||||
|
||||
if (t->lastWroteTS != 0 && (fabs((double)t->lastWroteTS-b->lastReceivedTS) > (double)CirSize))
|
||||
LOG_E(HW, "UEsock(%d) Tx/Rx shift too large Tx:%lu, Rx:%lu\n", fd, t->lastWroteTS, b->lastReceivedTS);
|
||||
LOG_W(HW, "UEsock(%d) Tx/Rx shift too large Tx:%lu, Rx:%lu\n", fd, t->lastWroteTS, b->lastReceivedTS);
|
||||
|
||||
pthread_mutex_unlock(&Sockmutex);
|
||||
b->transferPtr=(char *)&b->circularBuf[(b->lastReceivedTS*b->th.nbAnt)%CirSize];
|
||||
|
||||
Reference in New Issue
Block a user