Merge remote-tracking branch 'origin/f1-ho-prep' into integration_2024_w36
This commit is contained in:
@@ -62,12 +62,12 @@ nr_measurement_configuration = {
|
||||
};
|
||||
|
||||
A3 = ({
|
||||
cell_id = -1; #Default
|
||||
physCellId = -1; #Default
|
||||
offset = 10;
|
||||
hysteresis = 0;
|
||||
timeToTrigger = 1
|
||||
}, {
|
||||
cell_id = 2;
|
||||
physCellId = 2;
|
||||
offset = 5;
|
||||
hysteresis = 1;
|
||||
timeToTrigger = 2
|
||||
|
||||
@@ -1161,9 +1161,9 @@ void nr_timer_stop(NR_timer_t *timer)
|
||||
timer->counter = 0;
|
||||
}
|
||||
|
||||
bool is_nr_timer_active(NR_timer_t timer)
|
||||
bool nr_timer_is_active(const NR_timer_t *timer)
|
||||
{
|
||||
return timer.active;
|
||||
return timer->active;
|
||||
}
|
||||
|
||||
bool nr_timer_tick(NR_timer_t *timer)
|
||||
@@ -1173,23 +1173,23 @@ bool nr_timer_tick(NR_timer_t *timer)
|
||||
timer->counter += timer->step;
|
||||
if (timer->target == UINT_MAX) // infinite target, never expires
|
||||
return false;
|
||||
expired = nr_timer_expired(*timer);
|
||||
expired = nr_timer_expired(timer);
|
||||
if (expired)
|
||||
timer->active = false;
|
||||
}
|
||||
return expired;
|
||||
}
|
||||
|
||||
bool nr_timer_expired(NR_timer_t timer)
|
||||
bool nr_timer_expired(const NR_timer_t *timer)
|
||||
{
|
||||
if (timer.target == UINT_MAX) // infinite target, never expires
|
||||
if (timer->target == UINT_MAX) // infinite target, never expires
|
||||
return false;
|
||||
return (timer.counter >= timer.target);
|
||||
return timer->counter >= timer->target;
|
||||
}
|
||||
|
||||
uint32_t nr_timer_elapsed_time(NR_timer_t timer)
|
||||
uint32_t nr_timer_elapsed_time(const NR_timer_t *timer)
|
||||
{
|
||||
return timer.counter;
|
||||
return timer->counter;
|
||||
}
|
||||
|
||||
void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t step)
|
||||
|
||||
@@ -163,19 +163,19 @@ void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t ste
|
||||
* @param timer Timer to be checked
|
||||
* @return Indication if the timer is expired or not
|
||||
*/
|
||||
bool nr_timer_expired(NR_timer_t timer);
|
||||
bool nr_timer_expired(const NR_timer_t *timer);
|
||||
/**
|
||||
* @brief To check if a timer is active
|
||||
* @param timer Timer to be checked
|
||||
* @return Indication if the timer is active or not
|
||||
*/
|
||||
bool is_nr_timer_active(NR_timer_t timer);
|
||||
bool nr_timer_is_active(const NR_timer_t *timer);
|
||||
/**
|
||||
* @brief To return how much time has passed since start of timer
|
||||
* @param timer Timer to be checked
|
||||
* @return Time passed since start of timer
|
||||
*/
|
||||
uint32_t nr_timer_elapsed_time(NR_timer_t timer);
|
||||
uint32_t nr_timer_elapsed_time(const NR_timer_t *timer);
|
||||
|
||||
|
||||
extern const nr_bandentry_t nr_bandtable[];
|
||||
|
||||
@@ -29,13 +29,13 @@ TEST(nr_common, nr_timer) {
|
||||
NR_timer_t timer;
|
||||
nr_timer_setup(&timer, 10, 1);
|
||||
nr_timer_start(&timer);
|
||||
EXPECT_TRUE(is_nr_timer_active(timer));
|
||||
EXPECT_FALSE(nr_timer_expired(timer));
|
||||
EXPECT_TRUE(nr_timer_is_active(&timer));
|
||||
EXPECT_FALSE(nr_timer_expired(&timer));
|
||||
for (auto i = 0; i < 10; i++) {
|
||||
nr_timer_tick(&timer);
|
||||
}
|
||||
EXPECT_FALSE(is_nr_timer_active(timer));
|
||||
EXPECT_TRUE(nr_timer_expired(timer));
|
||||
EXPECT_FALSE(nr_timer_is_active(&timer));
|
||||
EXPECT_TRUE(nr_timer_expired(&timer));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -320,7 +320,7 @@ typedef struct timer_elm_s {
|
||||
(char *)itti_get_task_name(task_id),
|
||||
-1,
|
||||
OAI_PRIORITY_RT);
|
||||
LOG_I(ITTI,"Created Posix thread %s\n", itti_get_task_name(task_id) );
|
||||
LOG_D(ITTI,"Created Posix thread %s\n", itti_get_task_name(task_id) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -278,8 +278,6 @@ typedef struct pdusession_s {
|
||||
transport_layer_addr_t upf_addr;
|
||||
/* Outgoing (UL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
|
||||
uint32_t gtp_teid;
|
||||
/* Stores the DRB ID of the DRBs used by this PDU Session */
|
||||
uint8_t used_drbs[MAX_DRBS_PER_UE];
|
||||
/* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
|
||||
uint32_t gNB_teid_N3;
|
||||
transport_layer_addr_t gNB_addr_N3;
|
||||
|
||||
@@ -64,27 +64,17 @@ static void cu_task_handle_sctp_association_ind(instance_t instance,
|
||||
static void cu_task_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
|
||||
DevAssert(sctp_new_association_resp != NULL);
|
||||
|
||||
if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN) {
|
||||
enum sctp_state_e state = sctp_new_association_resp->sctp_state;
|
||||
if (state != SCTP_STATE_ESTABLISHED) {
|
||||
f1ap_cudu_inst_t *f1ap_cu_data = getCxt(instance);
|
||||
AssertFatal(f1ap_cu_data != NULL, "illegal state: SCTP shutdown for non-existing F1AP endpoint\n");
|
||||
LOG_I(F1AP, "Received SCTP shutdown for assoc_id %d, removing endpoint\n", sctp_new_association_resp->assoc_id);
|
||||
LOG_I(F1AP, "Received SCTP state %d for assoc_id %d, removing endpoint\n", state, sctp_new_association_resp->assoc_id);
|
||||
/* inform RRC that the DU is gone */
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_LOST_CONNECTION);
|
||||
message_p->ittiMsgHeader.originInstance = sctp_new_association_resp->assoc_id;
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
||||
LOG_W(F1AP, "Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n",
|
||||
sctp_new_association_resp->sctp_state,
|
||||
instance,
|
||||
sctp_new_association_resp->ulp_cnx_id);
|
||||
//if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN)
|
||||
//proto_agent_stop(instance);
|
||||
//f1ap_handle_setup_message(instance, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
|
||||
return; // exit -1 for debugging
|
||||
}
|
||||
}
|
||||
|
||||
static void cu_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
|
||||
|
||||
@@ -281,12 +281,9 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i
|
||||
memcpy(f1ap_ue_context_setup_req->rrc_container,
|
||||
ieRRC->value.choice.RRCContainer.buf, ieRRC->value.choice.RRCContainer.size);
|
||||
f1ap_ue_context_setup_req->rrc_container_length = ieRRC->value.choice.RRCContainer.size;
|
||||
// AssertFatal(0, "check configuration, send to appropriate handler\n");
|
||||
} else {
|
||||
LOG_E(F1AP, " RRCContainer in UEContextSetupRequestIEs size id 0\n");
|
||||
}
|
||||
} else {
|
||||
LOG_W(F1AP, "can't find RRCContainer in UEContextSetupRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer);
|
||||
}
|
||||
|
||||
ue_context_setup_request(f1ap_ue_context_setup_req);
|
||||
@@ -596,6 +593,7 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
|
||||
F1AP_SRBs_Setup_Item_t *srbs_setup_item=&srbs_setup_item_ies->value.choice.SRBs_Setup_Item;
|
||||
/* sRBID */
|
||||
srbs_setup_item->sRBID = resp->srbs_to_be_setup[i].srb_id;
|
||||
srbs_setup_item->lCID = resp->srbs_to_be_setup[i].lcid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,13 +40,13 @@ int f1ap_encode_pdu(F1AP_F1AP_PDU_t *pdu, uint8_t **buffer, uint32_t *length) {
|
||||
LOG_E(F1AP, "----------------- ASN1 ENCODER PRINT END----------------- \n");
|
||||
}
|
||||
|
||||
char errbuf[128]; /* Buffer for error message */
|
||||
char errbuf[4096]; /* Buffer for error message */
|
||||
size_t errlen = sizeof(errbuf); /* Size of the buffer */
|
||||
int ret = asn_check_constraints(&asn_DEF_F1AP_F1AP_PDU, pdu, errbuf, &errlen);
|
||||
|
||||
/* assert(errlen < sizeof(errbuf)); // Guaranteed: you may rely on that */
|
||||
if(ret) {
|
||||
fprintf(stderr, "Constraint validation failed: %s\n", errbuf);
|
||||
xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, pdu);
|
||||
LOG_E(F1AP, "Constraint validation failed: %s\n", errbuf);
|
||||
}
|
||||
|
||||
encoded = aper_encode_to_new_buffer(&asn_DEF_F1AP_F1AP_PDU, 0, pdu, (void **)buffer);
|
||||
|
||||
@@ -1598,7 +1598,7 @@ static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc
|
||||
paramdef_t NeighbourCellParams[] = GNBNEIGHBOURCELLPARAMS_DESC;
|
||||
paramlist_def_t NeighbourCellParamList = {GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST, NULL, 0};
|
||||
config_getlist(config_get_if(), &NeighbourCellParamList, NeighbourCellParams, sizeofArray(NeighbourCellParams), neighbourpath);
|
||||
LOG_D(GNB_APP, "HO LOG: For the Cell: %d Neighbour Cell ELM NUM: %d\n", cell->nr_cell_id, NeighbourCellParamList.numelt);
|
||||
LOG_D(GNB_APP, "HO LOG: For the Cell: %ld Neighbour Cell ELM NUM: %d\n", cell->nr_cell_id, NeighbourCellParamList.numelt);
|
||||
if (NeighbourCellParamList.numelt < 1)
|
||||
continue;
|
||||
|
||||
@@ -1696,12 +1696,17 @@ static void fill_measurement_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
|
||||
for (int i = 0; i < A3_EventList.numelt; i++) {
|
||||
nr_a3_event_t *a3_event = (nr_a3_event_t *)calloc(1, sizeof(nr_a3_event_t));
|
||||
AssertFatal(a3_event != NULL, "out of memory\n");
|
||||
a3_event->cell_id = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_CELL_ID_IDX].i64ptr;
|
||||
a3_event->pci = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_PCI_ID_IDX].i64ptr;
|
||||
AssertFatal(a3_event->pci >= -1 && a3_event->pci < 1024,
|
||||
"entry %s.%s must be -1<=PCI<1024, but is %d\n",
|
||||
measurement_path,
|
||||
MEASUREMENT_EVENTS_PCI_ID,
|
||||
a3_event->pci);
|
||||
a3_event->timeToTrigger = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_TIMETOTRIGGER_IDX].i64ptr;
|
||||
a3_event->a3_offset = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_OFFSET_IDX].i64ptr;
|
||||
a3_event->hysteresis = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_HYSTERESIS_IDX].i64ptr;
|
||||
|
||||
if (a3_event->cell_id == -1)
|
||||
if (a3_event->pci == -1)
|
||||
measurementConfig->is_default_a3_configuration_exists = true;
|
||||
|
||||
seq_arr_push_back(measurementConfig->a3_event_list, a3_event, sizeof(nr_a3_event_t));
|
||||
|
||||
@@ -324,12 +324,12 @@ typedef enum {
|
||||
#define MEASUREMENT_EVENTS_THRESHOLD "threshold"
|
||||
#define MEASUREMENT_EVENTS_PERIODICAL_BEAM_MEASUREMENT "includeBeamMeasurements"
|
||||
#define MEASUREMENT_EVENTS_PERIODICAL_NR_OF_RS_INDEXES "maxNrofRS_IndexesToReport"
|
||||
#define MEASUREMENT_EVENTS_CELL_ID "cell_id"
|
||||
#define MEASUREMENT_EVENTS_PCI_ID "physCellId"
|
||||
#define MEASUREMENT_EVENT_ENABLE "enable"
|
||||
// clang-format off
|
||||
#define MEASUREMENT_A3_GLOBALPARAMS_DESC \
|
||||
{ \
|
||||
{MEASUREMENT_EVENTS_CELL_ID, "neighbour cellId for A3Report", 0, .i64ptr = NULL, .defint64val = -1, TYPE_INT64, 0}, \
|
||||
{MEASUREMENT_EVENTS_PCI_ID, "neighbour PCI for A3Report", 0, .i64ptr = NULL, .defint64val = -1, TYPE_INT64, 0}, \
|
||||
{MEASUREMENT_EVENTS_TIME_TO_TRIGGER, "a3 time to trigger", 0, .i64ptr = NULL, .defint64val = 1, TYPE_INT64, 0}, \
|
||||
{MEASUREMENT_EVENTS_OFFSET, "a3 offset", 0, .i64ptr = NULL, .defint64val = 60, TYPE_INT64, 0}, \
|
||||
{MEASUREMENT_EVENTS_HYSTERESIS, "a3 hysteresis", 0, .i64ptr = NULL, .defint64val = 0, TYPE_INT64, 0}, \
|
||||
@@ -350,7 +350,7 @@ typedef enum {
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
#define MEASUREMENT_EVENTS_CELL_ID_IDX 0
|
||||
#define MEASUREMENT_EVENTS_PCI_ID_IDX 0
|
||||
#define MEASUREMENT_EVENTS_ENABLE_IDX 0
|
||||
#define MEASUREMENT_EVENTS_TIMETOTRIGGER_IDX 1
|
||||
#define MEASUREMENT_EVENTS_A2_THRESHOLD_IDX 2
|
||||
|
||||
@@ -790,7 +790,7 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB
|
||||
}
|
||||
}
|
||||
|
||||
if (is_nr_timer_active(ra->contention_resolution_timer)) {
|
||||
if (nr_timer_is_active(&ra->contention_resolution_timer)) {
|
||||
nr_ue_contention_resolution(mac, CC_id, frame, nr_slot_tx, prach_resources);
|
||||
}
|
||||
}
|
||||
@@ -851,7 +851,7 @@ void nr_ue_contention_resolution(NR_UE_MAC_INST_t *mac, int cc_id, frame_t frame
|
||||
{
|
||||
RA_config_t *ra = &mac->ra;
|
||||
|
||||
if (nr_timer_expired(ra->contention_resolution_timer)) {
|
||||
if (nr_timer_expired(&ra->contention_resolution_timer)) {
|
||||
ra->t_crnti = 0;
|
||||
nr_timer_stop(&ra->contention_resolution_timer);
|
||||
// Signal PHY to quit RA procedure
|
||||
|
||||
@@ -2543,7 +2543,7 @@ int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_Schedu
|
||||
sr_id); // todo
|
||||
|
||||
// TODO check if the PUCCH resource for the SR transmission occasion does not overlap with a UL-SCH resource
|
||||
if (!sr_info->pending || is_nr_timer_active(sr_info->prohibitTimer))
|
||||
if (!sr_info->pending || nr_timer_is_active(&sr_info->prohibitTimer))
|
||||
return 0;
|
||||
|
||||
if (sr_info->counter < sr_info->maxTransmissions) {
|
||||
|
||||
@@ -1297,7 +1297,7 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac)
|
||||
|
||||
// if a Regular BSR has been triggered and logicalChannelSR-DelayTimer is not running
|
||||
if (((sched_info->BSR_reporting_active & NR_BSR_TRIGGER_REGULAR) == 0)
|
||||
|| is_nr_timer_active(sched_info->sr_DelayTimer))
|
||||
|| nr_timer_is_active(&sched_info->sr_DelayTimer))
|
||||
return;
|
||||
|
||||
nr_lcordered_info_t *lc_info = get_lc_info_from_lcid(mac, sched_info->regularBSR_trigger_lcid);
|
||||
@@ -1527,7 +1527,7 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
|
||||
NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
|
||||
int32_t bj = sched_info->Bj;
|
||||
if (lc_info->pbr < UINT_MAX) {
|
||||
uint32_t slots_elapsed = nr_timer_elapsed_time(sched_info->Bj_timer); // slots elapsed since Bj was last incremented
|
||||
uint32_t slots_elapsed = nr_timer_elapsed_time(&sched_info->Bj_timer); // slots elapsed since Bj was last incremented
|
||||
// it is safe to divide by 1k since pbr in lc_info is computed multiplying by 1000 the RRC value to convert kB/s to B/s
|
||||
uint32_t pbr_ms = lc_info->pbr / 1000;
|
||||
bj += ((pbr_ms * slots_elapsed) >> mac->current_UL_BWP->scs); // each slot length is 1/scs ms
|
||||
|
||||
@@ -560,7 +560,7 @@ static void start_ra_contention_resolution_timer(NR_RA_t *ra, const long ra_Cont
|
||||
// Value sf8 corresponds to 8 subframes, value sf16 corresponds to 16 subframes, and so on.
|
||||
// We add 2 * K2 because the timer runs from Msg2 transmission till Msg4 ACK reception
|
||||
ra->contention_resolution_timer = ((((int)ra_ContentionResolutionTimer + 1) * 8) << scs) + 2 * K2;
|
||||
LOG_I(NR_MAC,
|
||||
LOG_D(NR_MAC,
|
||||
"Starting RA Contention Resolution timer with %d ms + 2 * %d K2 (%d slots) duration\n",
|
||||
((int)ra_ContentionResolutionTimer + 1) * 8,
|
||||
K2,
|
||||
|
||||
@@ -860,12 +860,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
// re-initialize ta update variables after RA procedure completion
|
||||
UE->UE_sched_ctrl.ta_frame = frameP;
|
||||
|
||||
LOG_I(NR_MAC,
|
||||
"[gNB %d][RAPROC] PUSCH with TC_RNTI 0x%04x received correctly, "
|
||||
"adding UE MAC Context RNTI 0x%04x\n",
|
||||
gnb_mod_idP,
|
||||
current_rnti,
|
||||
ra->rnti);
|
||||
LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frameP, slotP, current_rnti);
|
||||
|
||||
NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl;
|
||||
if (ul_cqi != 0xff) {
|
||||
@@ -884,7 +879,6 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, ra->CellGroup->rlc_BearerToAddModList);
|
||||
nr_clear_ra_proc(ra);
|
||||
} else {
|
||||
LOG_A(NR_MAC, "[RAPROC] RA-Msg3 received (sdu_lenP %d)\n", sdu_lenP);
|
||||
LOG_D(NR_MAC, "[RAPROC] Received Msg3:\n");
|
||||
for (uint32_t k = 0; k < sdu_lenP; k++) {
|
||||
LOG_D(NR_MAC, "(%i): 0x%x\n", k, sduP[k]);
|
||||
|
||||
@@ -233,7 +233,8 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE,
|
||||
nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .priority = priority};
|
||||
nr_mac_add_lcid(&UE->UE_sched_ctrl, &c);
|
||||
|
||||
(*resp_srbs)[i] = *srb;
|
||||
(*resp_srbs)[i].srb_id = srb->srb_id;
|
||||
(*resp_srbs)[i].lcid = c.lcid;
|
||||
|
||||
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
|
||||
DevAssert(ret == 0);
|
||||
@@ -669,8 +670,12 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd)
|
||||
NR_SCHED_LOCK(&mac->sched_lock);
|
||||
NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, cmd->gNB_DU_ue_id);
|
||||
if (UE == NULL) {
|
||||
LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring UE Context Release Command\n", cmd->gNB_DU_ue_id);
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
f1ap_ue_context_release_complete_t complete = {
|
||||
.gNB_CU_ue_id = cmd->gNB_CU_ue_id,
|
||||
.gNB_DU_ue_id = cmd->gNB_DU_ue_id,
|
||||
};
|
||||
mac->mac_rrc.ue_context_release_complete(&complete);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -743,7 +748,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
|
||||
* the new UE context (with new C-RNTI), but set up everything to reuse the
|
||||
* old config. */
|
||||
NR_UE_info_t *oldUE = find_nr_UE(&mac->UE_info, *dl_rrc->old_gNB_DU_ue_id);
|
||||
DevAssert(oldUE);
|
||||
AssertFatal(oldUE, "CU claims we should know UE %04x, but we don't\n", *dl_rrc->old_gNB_DU_ue_id);
|
||||
pthread_mutex_lock(&mac->sched_lock);
|
||||
/* 38.331 5.3.7.2 says that the UE releases the spCellConfig, so we drop it
|
||||
* from the current configuration. Also, expect the reconfiguration from
|
||||
|
||||
@@ -1165,10 +1165,9 @@ static NR_ReportConfigToAddMod_t *prepare_a2_event_report(const nr_a2_event_t *a
|
||||
static NR_ReportConfigToAddMod_t *prepare_a3_event_report(const nr_a3_event_t *a3_event)
|
||||
{
|
||||
NR_ReportConfigToAddMod_t *rc_A3 = calloc(1, sizeof(*rc_A3));
|
||||
rc_A3->reportConfigId =
|
||||
a3_event->cell_id == -1
|
||||
? 3
|
||||
: a3_event->cell_id + 4; // 3 is default A3 Report Config ID. So cellId(0) specific Report Config ID starts from 4
|
||||
// 3 is default A3 Report Config ID. So cellId(0) specific Report Config ID
|
||||
// starts from 4
|
||||
rc_A3->reportConfigId = a3_event->pci == -1 ? 3 : a3_event->pci + 4;
|
||||
rc_A3->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR;
|
||||
NR_EventTriggerConfig_t *etrc_A3 = calloc(1, sizeof(*etrc_A3));
|
||||
etrc_A3->eventId.present = NR_EventTriggerConfig__eventId_PR_eventA3;
|
||||
@@ -1194,7 +1193,7 @@ static NR_ReportConfigToAddMod_t *prepare_a3_event_report(const nr_a3_event_t *a
|
||||
return rc_A3;
|
||||
}
|
||||
|
||||
const nr_a3_event_t *get_a3_configuration(int nr_cellid)
|
||||
const nr_a3_event_t *get_a3_configuration(int pci)
|
||||
{
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
nr_measurement_configuration_t *measurementConfiguration = &rrc->measurementConfiguration;
|
||||
@@ -1203,7 +1202,7 @@ const nr_a3_event_t *get_a3_configuration(int nr_cellid)
|
||||
|
||||
for (uint8_t i = 0; i < measurementConfiguration->a3_event_list->size; i++) {
|
||||
nr_a3_event_t *a3_event = (nr_a3_event_t *)seq_arr_at(measurementConfiguration->a3_event_list, i);
|
||||
if (a3_event->cell_id == nr_cellid)
|
||||
if (a3_event->pci == pci)
|
||||
return a3_event;
|
||||
}
|
||||
|
||||
@@ -1262,11 +1261,11 @@ NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt,
|
||||
if (!neighbourCell->isIntraFrequencyNeighbour)
|
||||
continue;
|
||||
|
||||
const nr_a3_event_t *a3Event = get_a3_configuration(neighbourCell->nrcell_id);
|
||||
const nr_a3_event_t *a3Event = get_a3_configuration(neighbourCell->physicalCellId);
|
||||
if (!a3Event || is_default_a3_added)
|
||||
continue;
|
||||
|
||||
if (a3Event->cell_id == -1)
|
||||
if (a3Event->pci == -1)
|
||||
is_default_a3_added = true;
|
||||
|
||||
NR_ReportConfigToAddMod_t *rc_A3 = prepare_a3_event_report(a3Event);
|
||||
@@ -1368,7 +1367,7 @@ int do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi)
|
||||
LOG_D(NR_RRC, "[gNB %d] do_Paging paging_record: PagingRecordList.count %d\n",
|
||||
Mod_id, c1->choice.paging->pagingRecordList->list.count);
|
||||
asn_enc_rval_t enc_rval = uper_encode_to_buffer(
|
||||
&asn_DEF_NR_PCCH_Message, NULL, (void *)&pcch_msg, buffer, RRC_BUF_SIZE);
|
||||
&asn_DEF_NR_PCCH_Message, NULL, (void *)&pcch_msg, buffer, NR_RRC_BUF_SIZE);
|
||||
|
||||
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
|
||||
xer_fprint(stdout, &asn_DEF_NR_PCCH_Message, (void *)&pcch_msg);
|
||||
|
||||
@@ -143,7 +143,7 @@ int do_RRCReestablishment(rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
|
||||
int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier);
|
||||
|
||||
const nr_a3_event_t *get_a3_configuration(int nr_cellid);
|
||||
const nr_a3_event_t *get_a3_configuration(int pci);
|
||||
NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt,
|
||||
int band,
|
||||
int scs,
|
||||
|
||||
@@ -26,17 +26,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define NR_RRC_HEADER_SIZE_MAX 64
|
||||
#define NR_RRC_BUFFER_SIZE_MAX 1024
|
||||
#define NR_NUM_SRB 4 /* Number of Signalling Radio Bearers according to clause 4.2.2 of 3GPP TS 38.331 */
|
||||
#define NR_K_KEY_SIZE 16 /* K keys have 128 bits length */
|
||||
|
||||
typedef struct {
|
||||
char Payload[NR_RRC_BUFFER_SIZE_MAX];
|
||||
char Header[NR_RRC_HEADER_SIZE_MAX];
|
||||
uint16_t payload_size;
|
||||
} NR_RRC_BUFFER;
|
||||
|
||||
typedef enum UE_STATE_NR_e {
|
||||
NR_RRC_INACTIVE=0,
|
||||
NR_RRC_IDLE,
|
||||
|
||||
@@ -2805,6 +2805,8 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
|
||||
&& servingcellconfigdedicated->downlinkBWP_ToAddModList->list.count > 0) {
|
||||
n_dl_bwp = servingcellconfigdedicated->downlinkBWP_ToAddModList->list.count;
|
||||
}
|
||||
int default_dl_bwp = 0;
|
||||
int first_active_dl_bwp = 0;
|
||||
if (n_dl_bwp > 0) {
|
||||
SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList =
|
||||
calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList));
|
||||
@@ -2813,15 +2815,13 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
|
||||
config_downlinkBWP(bwp, scc, servingcellconfigdedicated, NULL, 0, false, bwp_loop, true);
|
||||
asn1cSeqAdd(&SpCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list, bwp);
|
||||
}
|
||||
SpCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id =
|
||||
calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id));
|
||||
*SpCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id =
|
||||
servingcellconfigdedicated->firstActiveDownlinkBWP_Id ? *servingcellconfigdedicated->firstActiveDownlinkBWP_Id : 1;
|
||||
SpCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id =
|
||||
calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id));
|
||||
*SpCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id =
|
||||
servingcellconfigdedicated->defaultDownlinkBWP_Id ? *servingcellconfigdedicated->defaultDownlinkBWP_Id : 1;
|
||||
const NR_BWP_Id_t *firstActiveDownlinkBWP_Id = servingcellconfigdedicated->firstActiveDownlinkBWP_Id;
|
||||
first_active_dl_bwp = firstActiveDownlinkBWP_Id ? *firstActiveDownlinkBWP_Id : 1;
|
||||
const NR_BWP_Id_t *defaultDownlinkBWP_Id = servingcellconfigdedicated->defaultDownlinkBWP_Id;
|
||||
default_dl_bwp = defaultDownlinkBWP_Id ? *defaultDownlinkBWP_Id : 1;
|
||||
}
|
||||
asn1cCallocOne(SpCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id, first_active_dl_bwp);
|
||||
asn1cCallocOne(SpCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id, default_dl_bwp);
|
||||
|
||||
// Uplink BWPs
|
||||
int n_ul_bwp = 0;
|
||||
@@ -2830,6 +2830,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
|
||||
&& servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count > 0) {
|
||||
n_ul_bwp = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count;
|
||||
}
|
||||
int first_active_ul_bwp = 0;
|
||||
if (n_ul_bwp > 0) {
|
||||
uplinkConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList));
|
||||
for (int bwp_loop = 0; bwp_loop < n_ul_bwp; bwp_loop++) {
|
||||
@@ -2837,11 +2838,10 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
|
||||
config_uplinkBWP(ubwp, bwp_loop, true, uid, configuration, servingcellconfigdedicated, scc, NULL);
|
||||
asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ubwp);
|
||||
}
|
||||
uplinkConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*uplinkConfig->firstActiveUplinkBWP_Id));
|
||||
*uplinkConfig->firstActiveUplinkBWP_Id = servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id
|
||||
? *servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id
|
||||
: 1;
|
||||
const NR_BWP_Id_t *firstActiveUplinkBWP_Id = servingcellconfigdedicated->uplinkConfig->firstActiveUplinkBWP_Id;
|
||||
first_active_ul_bwp = firstActiveUplinkBWP_Id ? *firstActiveUplinkBWP_Id : 1;
|
||||
}
|
||||
asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_ul_bwp);
|
||||
|
||||
SpCellConfig->spCellConfigDedicated->csi_MeasConfig = calloc(1, sizeof(*SpCellConfig->spCellConfigDedicated->csi_MeasConfig));
|
||||
SpCellConfig->spCellConfigDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup;
|
||||
|
||||
@@ -88,15 +88,6 @@
|
||||
#define NR_RRC_RECONFIGURATION_DELAY_MS 10
|
||||
#define NR_RRC_BWP_SWITCHING_DELAY_MS 6
|
||||
|
||||
// 3GPP TS 38.133 - Section 8 - Table 8.2.1.2.7-2: Parameters which cause interruption other than SCS
|
||||
// This table was recently added to 3GPP. It shows that changing the parameters locationAndBandwidth, nrofSRS-Ports or
|
||||
// maxMIMO-Layers-r16 causes an interruption. This parameter is not yet being used in code, but has been placed here
|
||||
// for future reference.
|
||||
#define NR_OF_SRS_PORTS_SWITCHING_DELAY_MS 30
|
||||
|
||||
#define NR_UE_MODULE_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!!
|
||||
#define NR_UE_INDEX_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!! used to be -1
|
||||
|
||||
typedef enum {
|
||||
NR_RRC_OK=0,
|
||||
NR_RRC_ConnSetup_failed,
|
||||
@@ -105,17 +96,11 @@ typedef enum {
|
||||
NR_RRC_HO_STARTED
|
||||
} NR_RRC_status_t;
|
||||
|
||||
#define RRM_FREE(p) if ( (p) != NULL) { free(p) ; p=NULL ; }
|
||||
#define RRM_MALLOC(t,n) (t *) malloc16( sizeof(t) * n )
|
||||
#define RRM_CALLOC(t,n) (t *) malloc16( sizeof(t) * n)
|
||||
#define RRM_CALLOC2(t,s) (t *) malloc16( s )
|
||||
|
||||
#define MAX_MEAS_OBJ 7
|
||||
#define MAX_MEAS_CONFIG 7
|
||||
#define MAX_MEAS_ID 7
|
||||
|
||||
#define PAYLOAD_SIZE_MAX 1024
|
||||
#define RRC_BUF_SIZE 1024
|
||||
#define NR_RRC_BUF_SIZE 4096
|
||||
#define UNDEF_SECURITY_MODE 0xff
|
||||
#define NO_SECURITY_MODE 0x20
|
||||
|
||||
@@ -129,14 +114,6 @@ typedef struct UE_S_TMSI_NR_s {
|
||||
uint32_t fiveg_tmsi;
|
||||
} __attribute__ ((__packed__)) NR_UE_S_TMSI;
|
||||
|
||||
|
||||
typedef enum nr_e_rab_satus_e {
|
||||
NR_E_RAB_STATUS_NEW,
|
||||
NR_E_RAB_STATUS_DONE, // from the gNB perspective
|
||||
NR_E_RAB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE
|
||||
NR_E_RAB_STATUS_FAILED,
|
||||
} nr_e_rab_status_t;
|
||||
|
||||
typedef struct nr_e_rab_param_s {
|
||||
e_rab_t param;
|
||||
uint8_t status;
|
||||
@@ -156,12 +133,10 @@ typedef struct HANDOVER_INFO_NR_s {
|
||||
//AS_Config_t as_config; /* these two parameters are taken from 36.331 section 10.2.2: HandoverPreparationInformation-r8-IEs */
|
||||
//AS_Context_t as_context; /* They are mandatory for HO */
|
||||
|
||||
uint8_t buf[RRC_BUF_SIZE]; /* ASN.1 encoded handoverCommandMessage */
|
||||
uint8_t buf[NR_RRC_BUF_SIZE]; /* ASN.1 encoded handoverCommandMessage */
|
||||
int size; /* size of above message in bytes */
|
||||
} NR_HANDOVER_INFO;
|
||||
|
||||
#define NR_RRC_BUFFER_SIZE sizeof(RRC_BUFFER_NR)
|
||||
|
||||
typedef struct nr_rrc_guami_s {
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
@@ -194,19 +169,15 @@ typedef struct pdu_session_param_s {
|
||||
* @brief F1-U tunnel configuration
|
||||
*/
|
||||
typedef struct f1u_tunnel_s {
|
||||
/* Downlink F1-U Tunnel Endpoint Identifier (CU-UP/DU) */
|
||||
uint32_t cuup_teid_f1u;
|
||||
/* DL F1-U Transport Layer */
|
||||
transport_layer_addr_t cuup_addr_f1u;
|
||||
/* F1-U Tunnel Endpoint Identifier (on DU side) */
|
||||
uint32_t teid;
|
||||
/* Downlink F1-U Transport Layer (on DU side) */
|
||||
transport_layer_addr_t addr;
|
||||
} f1u_tunnel_t;
|
||||
|
||||
typedef struct drb_s {
|
||||
int status;
|
||||
int defaultDRBid;
|
||||
int drb_id;
|
||||
int reestablishPDCP;
|
||||
int recoverPDCP;
|
||||
int daps_Config_r16;
|
||||
struct cnAssociation_s {
|
||||
int present;
|
||||
int eps_BearerIdentity;
|
||||
@@ -232,8 +203,10 @@ typedef struct drb_s {
|
||||
int cipheringDisabled;
|
||||
} ext1;
|
||||
} pdcp_config;
|
||||
// F1-U
|
||||
f1u_tunnel_t f1u_tunnel_config;
|
||||
// F1-U Downlink Tunnel Config (on DU side)
|
||||
f1u_tunnel_t du_tunnel_config;
|
||||
// F1-U Uplink Tunnel Config (on CU-UP side)
|
||||
f1u_tunnel_t cuup_tunnel_config;
|
||||
} drb_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -284,7 +257,6 @@ typedef struct gNB_RRC_UE_s {
|
||||
NR_CipheringAlgorithm_t ciphering_algorithm;
|
||||
e_NR_IntegrityProtAlgorithm integrity_algorithm;
|
||||
|
||||
NR_UE_STATE_t StatusRrc;
|
||||
rnti_t rnti;
|
||||
uint64_t random_ue_identity;
|
||||
|
||||
@@ -317,6 +289,8 @@ typedef struct gNB_RRC_UE_s {
|
||||
uint32_t ue_reestablishment_counter;
|
||||
uint32_t ue_reconfiguration_counter;
|
||||
|
||||
bool an_release; // flag if core requested UE release
|
||||
|
||||
/* NGUEContextSetup might come with PDU sessions, but setup needs to be
|
||||
* delayed after security (and capability); PDU sessions are stored here */
|
||||
int n_initial_pdu;
|
||||
@@ -368,7 +342,7 @@ typedef struct {
|
||||
} nr_a2_event_t;
|
||||
|
||||
typedef struct {
|
||||
int cell_id;
|
||||
int pci;
|
||||
long a3_offset;
|
||||
long hysteresis;
|
||||
long timeToTrigger;
|
||||
@@ -393,7 +367,7 @@ typedef struct {
|
||||
} nr_neighbour_gnb_configuration_t;
|
||||
|
||||
typedef struct neighbour_cell_configuration_s {
|
||||
int nr_cell_id;
|
||||
uint64_t nr_cell_id;
|
||||
seq_arr_t *neighbour_cells;
|
||||
} neighbour_cell_configuration_t;
|
||||
|
||||
|
||||
+169
-125
@@ -113,9 +113,9 @@ mui_t rrc_gNB_mui = 0;
|
||||
|
||||
// the assoc_id might be 0 (if the DU goes offline). Below helper macro to
|
||||
// print an error and return from the function in that case
|
||||
#define RETURN_IF_INVALID_ASSOC_ID(ue_data) \
|
||||
#define RETURN_IF_INVALID_ASSOC_ID(assoc_id) \
|
||||
{ \
|
||||
if (ue_data.du_assoc_id == 0) { \
|
||||
if (assoc_id == 0) { \
|
||||
LOG_E(NR_RRC, "cannot send data: invalid assoc_id 0, DU offline\n"); \
|
||||
return; \
|
||||
} \
|
||||
@@ -197,7 +197,7 @@ void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc,
|
||||
{
|
||||
DevAssert(size > 0);
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
f1ap_dl_rrc_message_t dl_rrc = {.gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .srb_id = srb_id};
|
||||
deliver_dl_rrc_message_data_t data = {.rrc = rrc, .dl_rrc = &dl_rrc, .assoc_id = ue_data.du_assoc_id};
|
||||
nr_pdcp_data_req_srb(ue_p->rrc_ue_id,
|
||||
@@ -345,7 +345,6 @@ static NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish)
|
||||
if (ue->established_drbs[i].status != DRB_INACTIVE) {
|
||||
DRB_config = generateDRB_ASN1(&ue->established_drbs[i]);
|
||||
if (reestablish) {
|
||||
ue->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true;
|
||||
asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true);
|
||||
}
|
||||
asn1cSeqAdd(&DRB_configList->list, DRB_config);
|
||||
@@ -424,7 +423,7 @@ static void rrc_gNB_generate_RRCSetup(instance_t instance,
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buf, size, "[MSG] RRC Setup\n");
|
||||
freeSRBlist(SRBs);
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
f1ap_dl_rrc_message_t dl_rrc = {
|
||||
.gNB_CU_ue_id = ue_p->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
@@ -454,7 +453,7 @@ static void rrc_gNB_generate_RRCReject(module_id_t module_id, rrc_gNB_ue_context
|
||||
LOG_I(NR_RRC, " [RAPROC] ue %04x Logical Channel DL-CCCH, Generating NR_RRCReject (bytes %d)\n", ue_p->rnti, size);
|
||||
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
f1ap_dl_rrc_message_t dl_rrc = {
|
||||
.gNB_CU_ue_id = ue_p->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
@@ -477,7 +476,6 @@ static void rrc_gNB_process_RRCSetupComplete(const protocol_ctxt_t *const ctxt_p
|
||||
LOG_A(NR_RRC, "UE %d Processing NR_RRCSetupComplete from UE\n", ue_context_pP->ue_context.rrc_ue_id);
|
||||
ue_context_pP->ue_context.Srb[1].Active = 1;
|
||||
ue_context_pP->ue_context.Srb[2].Active = 0;
|
||||
ue_context_pP->ue_context.StatusRrc = NR_RRC_CONNECTED;
|
||||
AssertFatal(ctxt_pP->rntiMaybeUEid == ue_context_pP->ue_context.rrc_ue_id, "logic bug: inconsistent IDs, must use CU UE ID!\n");
|
||||
|
||||
rrc_gNB_send_NGAP_NAS_FIRST_REQ(ctxt_pP, ue_context_pP, rrcSetupComplete);
|
||||
@@ -549,13 +547,13 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c
|
||||
|
||||
ue_p->measConfig = measconfig;
|
||||
|
||||
uint8_t buffer[RRC_BUF_SIZE] = {0};
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE] = {0};
|
||||
NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false);
|
||||
NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false);
|
||||
|
||||
int size = do_RRCReconfiguration(ue_p,
|
||||
buffer,
|
||||
RRC_BUF_SIZE,
|
||||
NR_RRC_BUF_SIZE,
|
||||
xid,
|
||||
SRBs,
|
||||
DRBs,
|
||||
@@ -676,10 +674,10 @@ rrc_gNB_modify_dedicatedRRCReconfiguration(
|
||||
}
|
||||
|
||||
NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false);
|
||||
uint8_t buffer[RRC_BUF_SIZE];
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE];
|
||||
int size = do_RRCReconfiguration(ue_p,
|
||||
buffer,
|
||||
RRC_BUF_SIZE,
|
||||
NR_RRC_BUF_SIZE,
|
||||
xid,
|
||||
NULL,
|
||||
DRBs,
|
||||
@@ -742,10 +740,10 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
|
||||
LOG_W(NR_RRC,"dedlicated NAS list is empty\n");
|
||||
}
|
||||
|
||||
uint8_t buffer[RRC_BUF_SIZE] = {0};
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE] = {0};
|
||||
int size = do_RRCReconfiguration(ue_p,
|
||||
buffer,
|
||||
RRC_BUF_SIZE,
|
||||
NR_RRC_BUF_SIZE,
|
||||
xid,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -808,7 +806,8 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p)
|
||||
return;
|
||||
/* loop through active DRBs */
|
||||
for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) {
|
||||
if (ue_p->established_drbs[drb_id - 1].status == DRB_INACTIVE)
|
||||
drb_t *drb = get_drb(ue_p, drb_id);
|
||||
if (drb->status == DRB_INACTIVE)
|
||||
continue;
|
||||
/* fetch an existing PDU session for this DRB */
|
||||
rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue_p, drb_id);
|
||||
@@ -829,13 +828,11 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p)
|
||||
DRB_nGRAN_to_mod_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify];
|
||||
drb_e1->id = drb_id;
|
||||
drb_e1->numDlUpParam = 1;
|
||||
drb_t *drbs = &ue_p->established_drbs[drb_id];
|
||||
memcpy(&drb_e1->DlUpParamList[0].tlAddress, &drbs->f1u_tunnel_config.cuup_addr_f1u.buffer, sizeof(uint8_t) * 4);
|
||||
drb_e1->DlUpParamList[0].teId = drbs->f1u_tunnel_config.cuup_teid_f1u;
|
||||
memcpy(&drb_e1->DlUpParamList[0].tlAddress, &drb->du_tunnel_config.addr.buffer, sizeof(uint8_t) * 4);
|
||||
drb_e1->DlUpParamList[0].teId = drb->du_tunnel_config.teid;
|
||||
/* PDCP configuration */
|
||||
bearer_context_pdcp_config_t *pdcp_config = &drb_e1->pdcp_config;
|
||||
drb_t *rrc_drb = get_drb(ue_p, drb_id);
|
||||
set_bearer_context_pdcp_config(pdcp_config, rrc_drb, rrc->configuration.um_on_default_drb);
|
||||
set_bearer_context_pdcp_config(pdcp_config, drb, rrc->configuration.um_on_default_drb);
|
||||
pdcp_config->pDCP_Reestablishment = true;
|
||||
/* increase DRB to modify counter */
|
||||
pdu_e1->numDRB2Modify += 1;
|
||||
@@ -863,12 +860,12 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context
|
||||
module_id_t module_id = 0;
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[module_id];
|
||||
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
|
||||
uint8_t buffer[RRC_BUF_SIZE] = {0};
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE] = {0};
|
||||
uint8_t xid = rrc_gNB_get_next_transaction_identifier(module_id);
|
||||
ue_p->xids[xid] = RRC_REESTABLISH;
|
||||
const f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info;
|
||||
uint32_t ssb_arfcn = get_ssb_arfcn(du);
|
||||
int size = do_RRCReestablishment(ue_context_pP, buffer, RRC_BUF_SIZE, xid, cell_info->nr_pci, ssb_arfcn);
|
||||
int size = do_RRCReestablishment(ue_context_pP, buffer, NR_RRC_BUF_SIZE, xid, cell_info->nr_pci, ssb_arfcn);
|
||||
|
||||
LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", ue_p->rnti, size);
|
||||
|
||||
@@ -902,7 +899,7 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context
|
||||
&security_parameters);
|
||||
/* F1AP DL RRC Message Transfer */
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
uint32_t old_gNB_DU_ue_id = old_rnti;
|
||||
f1ap_dl_rrc_message_t dl_rrc = {.gNB_CU_ue_id = ue_p->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
@@ -935,7 +932,6 @@ static void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *co
|
||||
int i = 0;
|
||||
|
||||
ue_p->xids[xid] = RRC_ACTION_NONE;
|
||||
ue_p->StatusRrc = NR_RRC_CONNECTED;
|
||||
|
||||
ue_p->Srb[1].Active = 1;
|
||||
|
||||
@@ -987,10 +983,10 @@ static void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *co
|
||||
|
||||
uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id);
|
||||
ue_p->xids[new_xid] = RRC_REESTABLISH_COMPLETE;
|
||||
uint8_t buffer[RRC_BUF_SIZE] = {0};
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE] = {0};
|
||||
int size = do_RRCReconfiguration(ue_p,
|
||||
buffer,
|
||||
RRC_BUF_SIZE,
|
||||
NR_RRC_BUF_SIZE,
|
||||
new_xid,
|
||||
SRBs,
|
||||
DRBs,
|
||||
@@ -1031,8 +1027,8 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP,
|
||||
*masterCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = ul_bwp_id;
|
||||
}
|
||||
|
||||
uint8_t buffer[RRC_BUF_SIZE];
|
||||
int size = do_RRCReconfiguration(ue_p, buffer, RRC_BUF_SIZE, xid, NULL, NULL, NULL, NULL, NULL, NULL, masterCellGroup);
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE];
|
||||
int size = do_RRCReconfiguration(ue_p, buffer, NR_RRC_BUF_SIZE, xid, NULL, NULL, NULL, NULL, NULL, NULL, masterCellGroup);
|
||||
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DCCH, buffer, size);
|
||||
@@ -1120,7 +1116,9 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc,
|
||||
uint64_t random_value = 0;
|
||||
const char *scause = get_reestab_cause(req->reestablishmentCause);
|
||||
const long physCellId = req->ue_Identity.physCellId;
|
||||
LOG_D(NR_RRC, "UE %04x physCellId %ld NR_RRCReestablishmentRequest cause %s\n", msg->crnti, physCellId, scause);
|
||||
long ngap_cause = NGAP_CAUSE_RADIO_NETWORK_UNSPECIFIED; /* cause in case of NGAP release req */
|
||||
rrc_gNB_ue_context_t *ue_context_p = NULL;
|
||||
LOG_I(NR_RRC, "UE %04x physCellId %ld NR_RRCReestablishmentRequest cause %s\n", msg->crnti, physCellId, scause);
|
||||
|
||||
const nr_rrc_du_container_t *du = get_du_by_assoc_id(rrc, assoc_id);
|
||||
if (du == NULL) {
|
||||
@@ -1128,6 +1126,13 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc,
|
||||
return;
|
||||
}
|
||||
|
||||
// 3GPP TS 38.321 version 15.13.0 Section 7.1 Table 7.1-1: RNTI values
|
||||
if (req->ue_Identity.c_RNTI < 0x1 || req->ue_Identity.c_RNTI > 0xffef) {
|
||||
/* c_RNTI range error should not happen */
|
||||
LOG_E(NR_RRC, "NR_RRCReestablishmentRequest c_RNTI %04lx range error, fallback to RRC setup\n", req->ue_Identity.c_RNTI);
|
||||
goto fallback_rrc_setup;
|
||||
}
|
||||
|
||||
if (du->mib == NULL || du->sib1 == NULL) {
|
||||
/* we don't have MIB/SIB1 of the DU, and therefore cannot generate the
|
||||
* Reestablishment (as we would need the SSB's ARFCN, which we cannot
|
||||
@@ -1136,12 +1141,22 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc,
|
||||
goto fallback_rrc_setup;
|
||||
}
|
||||
|
||||
if (du->mtc == NULL) {
|
||||
// some UEs don't send MeasurementTimingConfiguration, so we don't know the
|
||||
// SSB ARFCN and can't do reestablishment. handle it gracefully by doing
|
||||
// RRC setup procedure instead
|
||||
LOG_E(NR_RRC, "no MeasurementTimingConfiguration for this cell, cannot perform reestablishment\n");
|
||||
ngap_cause = NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_NGRAN_GENERATED_REASON;
|
||||
goto fallback_rrc_setup;
|
||||
}
|
||||
|
||||
rnti_t old_rnti = req->ue_Identity.c_RNTI;
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, assoc_id, old_rnti);
|
||||
ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, assoc_id, old_rnti);
|
||||
if (ue_context_p == NULL) {
|
||||
LOG_E(NR_RRC, "NR_RRCReestablishmentRequest without UE context, fallback to RRC setup\n");
|
||||
goto fallback_rrc_setup;
|
||||
}
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
|
||||
const f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info;
|
||||
if (physCellId != cell_info->nr_pci) {
|
||||
@@ -1150,6 +1165,7 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc,
|
||||
"RRC Reestablishment Request from different physCellId (%ld) than current physCellId (%d), fallback to RRC setup\n",
|
||||
physCellId,
|
||||
cell_info->nr_pci);
|
||||
ngap_cause = NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_NGRAN_GENERATED_REASON;
|
||||
/* 38.401 8.7: "If the UE accessed from a gNB-DU other than the original
|
||||
* one, the gNB-CU should trigger the UE Context Setup procedure". Let's
|
||||
* assume that the old DU will trigger a release request, also freeing the
|
||||
@@ -1157,25 +1173,10 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc,
|
||||
goto fallback_rrc_setup;
|
||||
}
|
||||
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
// 3GPP TS 38.321 version 15.13.0 Section 7.1 Table 7.1-1: RNTI values
|
||||
if (req->ue_Identity.c_RNTI < 0x1 || req->ue_Identity.c_RNTI > 0xffef) {
|
||||
/* c_RNTI range error should not happen */
|
||||
LOG_E(NR_RRC, "NR_RRCReestablishmentRequest c_RNTI %04lx range error, fallback to RRC setup\n", req->ue_Identity.c_RNTI);
|
||||
goto fallback_rrc_setup;
|
||||
}
|
||||
|
||||
if (!UE->as_security_active) {
|
||||
/* no active security context, need to restart entire connection */
|
||||
LOG_E(NR_RRC, "UE requested Reestablishment without activated AS security\n");
|
||||
goto fallback_rrc_setup;
|
||||
}
|
||||
|
||||
if (du->mtc == NULL) {
|
||||
// some UEs don't send MeasurementTimingConfiguration, so we don't know the
|
||||
// SSB ARFCN and can't do reestablishment. handle it gracefully by doing
|
||||
// RRC setup procedure instead
|
||||
LOG_E(NR_RRC, "no MeasurementTimingConfiguration for this cell, cannot perform reestablishment\n");
|
||||
ngap_cause = NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_NGRAN_GENERATED_REASON;
|
||||
goto fallback_rrc_setup;
|
||||
}
|
||||
|
||||
@@ -1188,8 +1189,6 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc,
|
||||
cu_remove_f1_ue_data(UE->rrc_ue_id);
|
||||
cu_add_f1_ue_data(UE->rrc_ue_id, &ue_data);
|
||||
|
||||
LOG_I(NR_RRC, "Accept Reestablishment Request UE physCellId %ld cause %s\n", physCellId, scause);
|
||||
|
||||
rrc_gNB_generate_RRCReestablishment(ue_context_p, msg->du2cu_rrc_container, old_rnti, du);
|
||||
return;
|
||||
|
||||
@@ -1197,6 +1196,10 @@ fallback_rrc_setup:
|
||||
fill_random(&random_value, sizeof(random_value));
|
||||
random_value = random_value & 0x7fffffffff; /* random value is 39 bits */
|
||||
|
||||
/* request release of the "old" UE in case it exists */
|
||||
if (ue_context_p != NULL)
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(0, ue_context_p, NGAP_CAUSE_RADIO_NETWORK, ngap_cause);
|
||||
|
||||
rrc_gNB_ue_context_t *new = rrc_gNB_create_ue_context(assoc_id, msg->crnti, rrc, random_value, msg->gNB_DU_ue_id);
|
||||
activate_srb(&new->ue_context, 1);
|
||||
rrc_gNB_generate_RRCSetup(0, msg->crnti, new, msg->du2cu_rrc_container, msg->du2cu_rrc_container_length);
|
||||
@@ -1228,11 +1231,11 @@ static void process_Event_Based_Measurement_Report(NR_ReportConfigNR_t *report,
|
||||
|
||||
switch (event_triggered->eventId.present) {
|
||||
case NR_EventTriggerConfig__eventId_PR_eventA2:
|
||||
LOG_I(NR_RRC, "\nHO LOG: Event A2 (Serving becomes worse than threshold)\n");
|
||||
LOG_I(NR_RRC, "HO LOG: Event A2 (Serving becomes worse than threshold)\n");
|
||||
break;
|
||||
|
||||
case NR_EventTriggerConfig__eventId_PR_eventA3: {
|
||||
LOG_I(NR_RRC, "\nHO LOG: Event A3 Report - Neighbour Becomes Better than Serving!\n");
|
||||
LOG_I(NR_RRC, "HO LOG: Event A3 Report - Neighbour Becomes Better than Serving!\n");
|
||||
const NR_MeasResults_t *measResults = &measurementReport->criticalExtensions.choice.measurementReport->measResults;
|
||||
|
||||
for (int serving_cell_idx = 0; serving_cell_idx < measResults->measResultServingMOList.list.count; serving_cell_idx++) {
|
||||
@@ -1267,7 +1270,7 @@ static void process_Event_Based_Measurement_Report(NR_ReportConfigNR_t *report,
|
||||
}
|
||||
|
||||
LOG_I(NR_RRC,
|
||||
"HO LOG: Measurement Report has came for the neighbour: %d with RSRP: %d\n",
|
||||
"HO LOG: Measurement Report for the neighbour %d with RSRP: %d\n",
|
||||
neighbourCellId,
|
||||
neighbourCellRSRP);
|
||||
|
||||
@@ -1279,7 +1282,7 @@ static void process_Event_Based_Measurement_Report(NR_ReportConfigNR_t *report,
|
||||
// neighbour.
|
||||
if (!neighbour_cell_du_context && neighbour) {
|
||||
// No F1 connection but static neighbour configuration is available
|
||||
const nr_a3_event_t *a3_event_configuration = get_a3_configuration(neighbour->nrcell_id);
|
||||
const nr_a3_event_t *a3_event_configuration = get_a3_configuration(neighbour->physicalCellId);
|
||||
// Additional check - This part can be modified according to additional cell specific Handover Margin
|
||||
if (a3_event_configuration
|
||||
&& ((a3_event_configuration->a3_offset + a3_event_configuration->hysteresis)
|
||||
@@ -1864,15 +1867,39 @@ static void fill_e1_bearer_modif(DRB_nGRAN_to_setup_t *drb_e1, const f1ap_drb_to
|
||||
/**
|
||||
* @brief Store F1-U DL TL and TEID in RRC
|
||||
*/
|
||||
static void f1u_gtp_update(f1u_tunnel_t *f1u, const f1ap_drb_to_be_setup_t *drb_f1)
|
||||
static void f1u_dl_gtp_update(f1u_tunnel_t *f1u, const f1ap_up_tnl_t *p)
|
||||
{
|
||||
f1u->cuup_teid_f1u = drb_f1->up_dl_tnl[0].teid;
|
||||
memcpy(&f1u->cuup_addr_f1u.buffer, &drb_f1->up_dl_tnl[0].tl_address, sizeof(uint8_t) * 4);
|
||||
f1u->cuup_addr_f1u.length = sizeof(in_addr_t);
|
||||
f1u->teid = p->teid;
|
||||
memcpy(&f1u->addr.buffer, &p->tl_address, sizeof(uint8_t) * 4);
|
||||
f1u->addr.length = sizeof(in_addr_t);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update DRB TEID information in RRC storage from received DRB list
|
||||
*/
|
||||
static void store_du_f1u_tunnel(const f1ap_drb_to_be_setup_t *drbs, int n, gNB_RRC_UE_t *ue)
|
||||
{
|
||||
for (int i = 0; i < n; i++) {
|
||||
const f1ap_drb_to_be_setup_t *drb_f1 = &drbs[i];
|
||||
AssertFatal(drb_f1->up_dl_tnl_length == 1, "can handle only one UP param\n");
|
||||
AssertFatal(drb_f1->drb_id < MAX_DRBS_PER_UE, "illegal DRB ID %ld\n", drb_f1->drb_id);
|
||||
drb_t *drb = get_drb(ue, drb_f1->drb_id);
|
||||
f1u_dl_gtp_update(&drb->du_tunnel_config, &drb_f1->up_dl_tnl[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Store F1-U UL TEID and address in RRC
|
||||
*/
|
||||
static void f1u_ul_gtp_update(f1u_tunnel_t *f1u, const up_params_t *p)
|
||||
{
|
||||
f1u->teid = p->teId;
|
||||
memcpy(&f1u->addr.buffer, &p->tlAddress, sizeof(uint8_t) * 4);
|
||||
f1u->addr.length = sizeof(in_addr_t);
|
||||
}
|
||||
|
||||
/* \brief use list of DRBs and send the corresponding bearer update message via
|
||||
* E1 to the CU of this UE */
|
||||
* E1 to the CU of this UE. Also updates TEID info internally */
|
||||
static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_to_be_setup_t *drbs)
|
||||
{
|
||||
// we assume the same UE ID in CU-UP and CU-CP
|
||||
@@ -1892,7 +1919,6 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f
|
||||
DevAssert(pdu_e1 != NULL);
|
||||
pdu_e1->sessionId = pdu_ue->param.pdusession_id;
|
||||
DRB_nGRAN_to_setup_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify];
|
||||
f1u_gtp_update(&UE->established_drbs[drb_f1->drb_id].f1u_tunnel_config, drb_f1);
|
||||
/* Fill E1 bearer context modification */
|
||||
fill_e1_bearer_modif(drb_e1, drb_f1);
|
||||
pdu_e1->numDRB2Modify += 1;
|
||||
@@ -1942,6 +1968,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance
|
||||
/* Note: we would ideally check that SRB2 is acked, but at least LiteOn DU
|
||||
* seems buggy and does not ack, so simply check that locally we activated */
|
||||
AssertFatal(UE->Srb[1].Active && UE->Srb[2].Active, "SRBs 1 and 2 must be active during DRB Establishment");
|
||||
store_du_f1u_tunnel(resp->drbs_to_be_setup, resp->drbs_to_be_setup_length, UE);
|
||||
e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup);
|
||||
}
|
||||
|
||||
@@ -2003,7 +2030,13 @@ static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p)
|
||||
return;
|
||||
}
|
||||
|
||||
rrc_remove_ue(RC.nrrrc[0], ue_context_p);
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
if (UE->an_release) {
|
||||
/* only trigger release if it has been requested by core
|
||||
* otherwise, it might be CU that requested release on a DU during normal
|
||||
* operation (i.e, handover) */
|
||||
rrc_remove_ue(RC.nrrrc[0], ue_context_p);
|
||||
}
|
||||
}
|
||||
|
||||
static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, instance_t instance)
|
||||
@@ -2019,6 +2052,7 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
|
||||
if (resp->drbs_to_be_setup_length > 0) {
|
||||
store_du_f1u_tunnel(resp->drbs_to_be_setup, resp->drbs_to_be_setup_length, UE);
|
||||
e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup);
|
||||
}
|
||||
|
||||
@@ -2118,6 +2152,67 @@ static pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* \bref return F1AP QoS characteristics based on Qos flow parameters */
|
||||
static f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param)
|
||||
{
|
||||
f1ap_qos_characteristics_t qos_char = {0};
|
||||
if (qos_param->fiveQI_type == dynamic) {
|
||||
qos_char.qos_type = dynamic;
|
||||
qos_char.dynamic.fiveqi = qos_param->fiveQI;
|
||||
qos_char.dynamic.qos_priority_level = qos_param->qos_priority;
|
||||
} else {
|
||||
qos_char.qos_type = non_dynamic;
|
||||
qos_char.non_dynamic.fiveqi = qos_param->fiveQI;
|
||||
qos_char.non_dynamic.qos_priority_level = qos_param->qos_priority;
|
||||
}
|
||||
return qos_char;
|
||||
}
|
||||
|
||||
/* \brief fills a list of DRBs to be setup from a number of PDU sessions in E1
|
||||
* bearer setup response */
|
||||
static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc,
|
||||
gNB_RRC_UE_t *UE,
|
||||
const pdu_session_setup_t *pduSession,
|
||||
int numPduSession,
|
||||
f1ap_drb_to_be_setup_t drbs[32])
|
||||
{
|
||||
int nb_drb = 0;
|
||||
for (int p = 0; p < numPduSession; ++p) {
|
||||
rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, pduSession[p].id, false);
|
||||
DevAssert(RRC_pduSession);
|
||||
for (int i = 0; i < pduSession[p].numDRBSetup; i++) {
|
||||
const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i];
|
||||
f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb];
|
||||
drb->drb_id = pduSession[p].DRBnGRanList[i].id;
|
||||
drb->rlc_mode = rrc->configuration.um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM;
|
||||
drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tlAddress;
|
||||
drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
|
||||
drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].teId;
|
||||
drb->up_ul_tnl_length = 1;
|
||||
|
||||
/* pass QoS info to MAC */
|
||||
int nb_qos_flows = drb_config->numQosFlowSetup;
|
||||
AssertFatal(nb_qos_flows > 0, "must map at least one flow to a DRB\n");
|
||||
drb->drb_info.flows_to_be_setup_length = nb_qos_flows;
|
||||
drb->drb_info.flows_mapped_to_drb = calloc(nb_qos_flows, sizeof(f1ap_flows_mapped_to_drb_t));
|
||||
AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n");
|
||||
for (int j = 0; j < nb_qos_flows; j++) {
|
||||
drb->drb_info.flows_mapped_to_drb[j].qfi = drb_config->qosFlows[j].qfi;
|
||||
pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(drb_config->qosFlows[j].qfi, RRC_pduSession);
|
||||
drb->drb_info.flows_mapped_to_drb[j].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char);
|
||||
}
|
||||
/* the DRB QoS parameters: we just reuse the ones from the first flow */
|
||||
drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params;
|
||||
|
||||
/* pass NSSAI info to MAC */
|
||||
drb->nssai = RRC_pduSession->param.nssai;
|
||||
|
||||
nb_drb++;
|
||||
}
|
||||
}
|
||||
return nb_drb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief E1AP Bearer Context Setup Response processing on CU-CP
|
||||
*/
|
||||
@@ -2146,56 +2241,20 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
|
||||
rrc_pdu->param.gNB_teid_N3 = e1_pdu->teId;
|
||||
memcpy(&rrc_pdu->param.gNB_addr_N3.buffer, &e1_pdu->tlAddress, sizeof(uint8_t) * 4);
|
||||
rrc_pdu->param.gNB_addr_N3.length = sizeof(in_addr_t);
|
||||
|
||||
// save the tunnel address for the DRBs
|
||||
for (int i = 0; i < e1_pdu->numDRBSetup; i++) {
|
||||
DRB_nGRAN_setup_t *drb_config = &e1_pdu->DRBnGRanList[i];
|
||||
// numUpParam only relevant in F1, but not monolithic
|
||||
AssertFatal(drb_config->numUpParam <= 1, "can only up to one UP param\n");
|
||||
drb_t *drb = get_drb(UE, drb_config->id);
|
||||
f1u_ul_gtp_update(&drb->cuup_tunnel_config, &drb_config->UpParamList[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Instruction towards the DU for DRB configuration and tunnel creation */
|
||||
f1ap_drb_to_be_setup_t drbs[32]; // maximum DRB can be 32
|
||||
int nb_drb = 0;
|
||||
for (int p = 0; p < resp->numPDUSessions; ++p) {
|
||||
rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, resp->pduSession[p].id, false);
|
||||
DevAssert(RRC_pduSession);
|
||||
for (int i = 0; i < resp->pduSession[p].numDRBSetup; i++) {
|
||||
DRB_nGRAN_setup_t *drb_config = &resp->pduSession[p].DRBnGRanList[i];
|
||||
f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb];
|
||||
drb->drb_id = resp->pduSession[p].DRBnGRanList[i].id;
|
||||
drb->rlc_mode = rrc->configuration.um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM;
|
||||
drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tlAddress;
|
||||
drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
|
||||
drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].teId;
|
||||
drb->up_ul_tnl_length = 1;
|
||||
|
||||
drb->nssai = RRC_pduSession->param.nssai;
|
||||
|
||||
/* pass QoS info to MAC */
|
||||
int nb_qos_flows = drb_config->numQosFlowSetup;
|
||||
AssertFatal(nb_qos_flows > 0, "must map at least one flow to a DRB\n");
|
||||
drb->drb_info.flows_to_be_setup_length = nb_qos_flows;
|
||||
drb->drb_info.flows_mapped_to_drb = calloc(nb_qos_flows, sizeof(f1ap_flows_mapped_to_drb_t));
|
||||
AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n");
|
||||
for (int j = 0; j < nb_qos_flows; j++) {
|
||||
drb->drb_info.flows_mapped_to_drb[j].qfi = drb_config->qosFlows[j].qfi;
|
||||
|
||||
pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(drb_config->qosFlows[j].qfi, RRC_pduSession);
|
||||
f1ap_qos_characteristics_t *qos_char = &drb->drb_info.flows_mapped_to_drb[j].qos_params.qos_characteristics;
|
||||
if (in_qos_char->fiveQI_type == dynamic) {
|
||||
qos_char->qos_type = dynamic;
|
||||
qos_char->dynamic.fiveqi = in_qos_char->fiveQI;
|
||||
qos_char->dynamic.qos_priority_level = in_qos_char->qos_priority;
|
||||
} else {
|
||||
qos_char->qos_type = non_dynamic;
|
||||
qos_char->non_dynamic.fiveqi = in_qos_char->fiveQI;
|
||||
qos_char->non_dynamic.qos_priority_level = in_qos_char->qos_priority;
|
||||
}
|
||||
}
|
||||
/* the DRB QoS parameters: we just reuse the ones from the first flow */
|
||||
drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params;
|
||||
|
||||
/* pass NSSAI info to MAC */
|
||||
drb->nssai = RRC_pduSession->param.nssai;
|
||||
|
||||
nb_drb++;
|
||||
}
|
||||
}
|
||||
int nb_drb = fill_drb_to_be_setup_from_e1_resp(rrc, UE, resp->pduSession, resp->numPDUSessions, drbs);
|
||||
|
||||
if (!UE->f1_ue_context_active)
|
||||
rrc_gNB_generate_UeContextSetupRequest(rrc, ue_context_p, nb_drb, drbs);
|
||||
@@ -2255,20 +2314,6 @@ static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_rrc_connection_status_text(NR_UE_STATE_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case NR_RRC_INACTIVE: return "inactive";
|
||||
case NR_RRC_IDLE: return "idle";
|
||||
case NR_RRC_SI_RECEIVED: return "SI-received";
|
||||
case NR_RRC_CONNECTED: return "connected";
|
||||
case NR_RRC_RECONFIGURED: return "reconfigured";
|
||||
case NR_RRC_HO_EXECUTION: return "HO-execution";
|
||||
default: AssertFatal(false, "illegal RRC state %d\n", state); return "illegal";
|
||||
}
|
||||
return "illegal";
|
||||
}
|
||||
|
||||
static const char *get_pdusession_status_text(pdu_session_status_t status)
|
||||
{
|
||||
switch (status) {
|
||||
@@ -2316,7 +2361,6 @@ static void write_rrc_stats(const gNB_RRC_INST *rrc)
|
||||
|
||||
time_t last_seen = now - ue_ctxt->last_seen;
|
||||
fprintf(f, " last RRC activity: %ld seconds ago\n", last_seen);
|
||||
fprintf(f, " RRC status %s\n", get_rrc_connection_status_text(ue_ctxt->StatusRrc));
|
||||
|
||||
if (ue_ctxt->nb_of_pdusessions == 0)
|
||||
fprintf(f, " (no PDU sessions)\n");
|
||||
@@ -2606,8 +2650,8 @@ rrc_gNB_generate_RRCRelease(
|
||||
)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
uint8_t buffer[RRC_BUF_SIZE] = {0};
|
||||
int size = do_NR_RRCRelease(buffer, RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id));
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE] = {0};
|
||||
int size = do_NR_RRCRelease(buffer, NR_RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id));
|
||||
|
||||
LOG_I(NR_RRC,
|
||||
PROTOCOL_NR_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate RRCRelease (bytes %d)\n",
|
||||
@@ -2617,7 +2661,7 @@ rrc_gNB_generate_RRCRelease(
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
|
||||
const gNB_RRC_UE_t *UE = &ue_context_pP->ue_context;
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
f1ap_ue_context_release_cmd_t ue_context_release_cmd = {
|
||||
.gNB_CU_ue_id = UE->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
@@ -2639,7 +2683,7 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint
|
||||
uint32_t N; /* N: min(T,nB). total count of PF in one DRX cycle */
|
||||
uint32_t Ns = 0; /* Ns: max(1,nB/T) */
|
||||
uint32_t T; /* DRX cycle */
|
||||
uint8_t buffer[RRC_BUF_SIZE];
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE];
|
||||
|
||||
/* get default DRX cycle from configuration */
|
||||
Tc = sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.defaultPagingCycle;
|
||||
@@ -2743,7 +2787,7 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc,
|
||||
|
||||
/* the callback will fill the UE context setup request and forward it */
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
f1ap_ue_context_setup_t ue_context_setup_req = {
|
||||
.gNB_CU_ue_id = ue_p->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
@@ -2787,7 +2831,7 @@ void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc,
|
||||
}
|
||||
|
||||
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data);
|
||||
RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id);
|
||||
f1ap_ue_context_modif_req_t ue_context_modif_req = {
|
||||
.gNB_CU_ue_id = ue_p->rrc_ue_id,
|
||||
.gNB_DU_ue_id = ue_data.secondary_ue,
|
||||
|
||||
@@ -1180,6 +1180,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_
|
||||
}
|
||||
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
UE->an_release = true;
|
||||
#ifdef E2_AGENT
|
||||
signal_rrc_state_changed_to(UE, RC_SM_RRC_IDLE);
|
||||
#endif
|
||||
|
||||
@@ -40,12 +40,17 @@ int get_ssb_scs(const struct f1ap_served_cell_info_t *cell_info)
|
||||
return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.tbw.scs : cell_info->fdd.dl_tbw.scs;
|
||||
}
|
||||
|
||||
static int ssb_arfcn_mtc(const NR_MeasurementTimingConfiguration_t *mtc)
|
||||
{
|
||||
/* format has been verified when accepting MeasurementTimingConfiguration */
|
||||
NR_MeasTimingList_t *mtlist = mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming;
|
||||
return mtlist->list.array[0]->frequencyAndTiming->carrierFreq;
|
||||
}
|
||||
|
||||
int get_ssb_arfcn(const struct nr_rrc_du_container_t *du)
|
||||
{
|
||||
DevAssert(du != NULL && du->mtc != NULL);
|
||||
/* format has been verified when accepting MeasurementTimingConfiguration */
|
||||
NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming;
|
||||
return mtlist->list.array[0]->frequencyAndTiming->carrierFreq;
|
||||
return ssb_arfcn_mtc(du->mtc);
|
||||
}
|
||||
|
||||
static int du_compare(const nr_rrc_du_container_t *a, const nr_rrc_du_container_t *b)
|
||||
@@ -197,6 +202,58 @@ static void label_intra_frequency_neighbours(gNB_RRC_INST *rrc,
|
||||
for_each(cell_neighbour_list, (void *)&ssb_arfcn, is_intra_frequency_neighbour);
|
||||
}
|
||||
|
||||
static bool valid_du_in_neighbour_configs(const seq_arr_t *neighbour_cell_configuration, const f1ap_served_cell_info_t *cell, int ssb_arfcn)
|
||||
{
|
||||
for (int c = 0; c < neighbour_cell_configuration->size; c++) {
|
||||
const neighbour_cell_configuration_t *neighbour_config = seq_arr_at(neighbour_cell_configuration, c);
|
||||
for (int ni = 0; ni < neighbour_config->neighbour_cells->size; ni++) {
|
||||
const nr_neighbour_gnb_configuration_t *nc = seq_arr_at(neighbour_config->neighbour_cells, ni);
|
||||
if (nc->nrcell_id != cell->nr_cellid)
|
||||
continue;
|
||||
// current cell is in the nc config, check that config matches
|
||||
if (nc->physicalCellId != cell->nr_pci) {
|
||||
LOG_W(NR_RRC, "Cell %ld in neighbour config: PCI mismatch (%d vs %d)\n", cell->nr_cellid, cell->nr_pci, nc->physicalCellId);
|
||||
return false;
|
||||
}
|
||||
if (cell->tac && nc->tac != *cell->tac) {
|
||||
LOG_W(NR_RRC, "Cell %ld in neighbour config: TAC mismatch (%d vs %d)\n", cell->nr_cellid, *cell->tac, nc->tac);
|
||||
return false;
|
||||
}
|
||||
if (ssb_arfcn != nc->absoluteFrequencySSB) {
|
||||
LOG_W(NR_RRC,
|
||||
"Cell %ld in neighbour config: SSB ARFCN mismatch (%d vs %d)\n",
|
||||
cell->nr_cellid,
|
||||
ssb_arfcn,
|
||||
nc->absoluteFrequencySSB);
|
||||
return false;
|
||||
}
|
||||
if (get_ssb_scs(cell) != nc->subcarrierSpacing) {
|
||||
LOG_W(NR_RRC,
|
||||
"Cell %ld in neighbour config: SCS mismatch (%d vs %d)\n",
|
||||
cell->nr_cellid,
|
||||
get_ssb_scs(cell),
|
||||
nc->subcarrierSpacing);
|
||||
return false;
|
||||
}
|
||||
if (cell->plmn.mcc != nc->plmn.mcc || cell->plmn.mnc != nc->plmn.mnc
|
||||
|| cell->plmn.mnc_digit_length != nc->plmn.mnc_digit_length) {
|
||||
LOG_W(NR_RRC,
|
||||
"Cell %ld in neighbour config: PLMN mismatch (%03d.%0*d vs %03d.%0*d)\n",
|
||||
cell->nr_cellid,
|
||||
cell->plmn.mcc,
|
||||
cell->plmn.mnc_digit_length,
|
||||
cell->plmn.mnc,
|
||||
nc->plmn.mcc,
|
||||
nc->plmn.mnc_digit_length,
|
||||
nc->plmn.mnc);
|
||||
return false;
|
||||
}
|
||||
LOG_D(NR_RRC, "Cell %ld is neighbor of cell %ld\n", cell->nr_cellid, neighbour_config->nr_cell_id);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
{
|
||||
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
|
||||
@@ -219,10 +276,12 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
f1ap_served_cell_info_t *cell_info = &req->cell[0].info;
|
||||
if (!rrc_gNB_plmn_matches(rrc, cell_info)) {
|
||||
LOG_E(NR_RRC,
|
||||
"PLMN mismatch: CU %d%d, DU %d%d\n",
|
||||
"PLMN mismatch: CU %03d.%0*d, DU %03d%0*d\n",
|
||||
rrc->configuration.mcc[0],
|
||||
rrc->configuration.mnc_digit_length[0],
|
||||
rrc->configuration.mnc[0],
|
||||
cell_info->plmn.mcc,
|
||||
cell_info->plmn.mnc_digit_length,
|
||||
cell_info->plmn.mnc);
|
||||
f1ap_setup_failure_t fail = {.cause = F1AP_CauseRadioNetwork_plmn_not_served_by_the_gNB_CU};
|
||||
rrc->mac_rrc.f1_setup_failure(assoc_id, &fail);
|
||||
@@ -264,6 +323,15 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
NR_MeasurementTimingConfiguration_t *mtc =
|
||||
extract_mtc(cell_info->measurement_timing_config, cell_info->measurement_timing_config_len);
|
||||
|
||||
if (rrc->neighbour_cell_configuration
|
||||
&& !valid_du_in_neighbour_configs(rrc->neighbour_cell_configuration, cell_info, ssb_arfcn_mtc(mtc))) {
|
||||
LOG_E(NR_RRC, "problem with DU %ld in neighbor configuration, rejecting DU\n", req->gNB_DU_id);
|
||||
f1ap_setup_failure_t fail = {.cause = F1AP_CauseMisc_unspecified};
|
||||
rrc->mac_rrc.f1_setup_failure(assoc_id, &fail);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc);
|
||||
return;
|
||||
}
|
||||
|
||||
const f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info;
|
||||
NR_MIB_t *mib = NULL;
|
||||
NR_SIB1_t *sib1 = NULL;
|
||||
@@ -501,7 +569,7 @@ void dump_du_info(const gNB_RRC_INST *rrc, FILE *f)
|
||||
fprintf(f, "assoc_id %d", du->assoc_id);
|
||||
}
|
||||
const f1ap_served_cell_info_t *info = &sr->cell[0].info;
|
||||
fprintf(f, ": nrCellID %ld, PCI %d\n", info->nr_cellid, info->nr_pci);
|
||||
fprintf(f, ": nrCellID %ld, PCI %d, SSB ARFCN %d\n", info->nr_cellid, info->nr_pci, get_ssb_arfcn(du));
|
||||
|
||||
if (info->mode == F1AP_MODE_TDD) {
|
||||
const f1ap_nr_frequency_info_t *fi = &info->tdd.freqinfo;
|
||||
|
||||
@@ -51,7 +51,7 @@ rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id
|
||||
|
||||
drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id)
|
||||
{
|
||||
DevAssert(drb_id > 0 && drb_id < 32);
|
||||
DevAssert(drb_id > 0 && drb_id <= 32);
|
||||
DevAssert(ue != NULL);
|
||||
|
||||
return &ue->established_drbs[drb_id - 1];
|
||||
@@ -96,10 +96,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
|
||||
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;
|
||||
|
||||
@@ -479,7 +479,7 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
|
||||
// Actions following cell selection while T311 is running
|
||||
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
|
||||
if (is_nr_timer_active(timers->T311)) {
|
||||
if (nr_timer_is_active(&timers->T311)) {
|
||||
nr_timer_stop(&timers->T311);
|
||||
rrc->ra_trigger = RRC_CONNECTION_REESTABLISHMENT;
|
||||
|
||||
@@ -1695,7 +1695,7 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
|
||||
void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded)
|
||||
{
|
||||
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
|
||||
if (ra_succeeded && is_nr_timer_active(timers->T304)) {
|
||||
if (ra_succeeded && nr_timer_is_active(&timers->T304)) {
|
||||
// successful Random Access procedure triggered by reconfigurationWithSync
|
||||
nr_timer_stop(&timers->T304);
|
||||
// TODO handle the rest of procedures as described in 5.3.5.3 for when
|
||||
@@ -2130,7 +2130,7 @@ static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_l
|
||||
process_nsa_message(NR_UE_rrc_inst, nr_SecondaryCellGroupConfig_r15, nr_SecondaryCellGroup_buffer, nr_SecondaryCellGroup_size);
|
||||
process_nsa_message(NR_UE_rrc_inst, nr_RadioBearerConfigX_r15, nr_RadioBearer_buffer, nr_RadioBearer_size);
|
||||
LOG_I(NR_RRC, "Calling do_NR_RRCReconfigurationComplete. t_id %ld \n", t_id);
|
||||
uint8_t buffer[RRC_BUF_SIZE];
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE];
|
||||
size_t size = do_NR_RRCReconfigurationComplete_for_nsa(buffer, sizeof(buffer), t_id);
|
||||
nsa_sendmsg_to_lte_ue(buffer, size, NR_RRC_CONFIG_COMPLETE_REQ);
|
||||
break;
|
||||
@@ -2138,7 +2138,7 @@ static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_l
|
||||
|
||||
case OAI_TUN_IFACE_NSA: {
|
||||
LOG_I(NR_RRC, "We got an OAI_TUN_IFACE_NSA!!\n");
|
||||
char cmd_line[RRC_BUF_SIZE];
|
||||
char cmd_line[NR_RRC_BUF_SIZE];
|
||||
memcpy(cmd_line, msg_buffer, sizeof(cmd_line));
|
||||
LOG_D(NR_RRC, "Command line: %s\n", cmd_line);
|
||||
if (background_system(cmd_line) != 0)
|
||||
@@ -2218,14 +2218,14 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
|
||||
}
|
||||
}
|
||||
if (!waitTime) {
|
||||
if (is_nr_timer_active(tac->T302)) {
|
||||
if (nr_timer_is_active(&tac->T302)) {
|
||||
nr_timer_stop(&tac->T302);
|
||||
// TODO barring alleviation as in 5.3.14.4
|
||||
// not implemented
|
||||
LOG_E(NR_RRC,"Go to IDLE. Barring alleviation not implemented\n");
|
||||
}
|
||||
}
|
||||
if (is_nr_timer_active(tac->T390)) {
|
||||
if (nr_timer_is_active(&tac->T390)) {
|
||||
nr_timer_stop(&tac->T390);
|
||||
// TODO barring alleviation as in 5.3.14.4
|
||||
// not implemented
|
||||
|
||||
@@ -560,7 +560,7 @@ void handle_rlf_sync(NR_UE_Timers_Constants_t *tac,
|
||||
{
|
||||
if (sync_msg == IN_SYNC) {
|
||||
tac->N310_cnt = 0;
|
||||
if (is_nr_timer_active(tac->T310)) {
|
||||
if (nr_timer_is_active(&tac->T310)) {
|
||||
tac->N311_cnt++;
|
||||
// Upon receiving N311 consecutive "in-sync" indications
|
||||
if (tac->N311_cnt >= tac->N311_k) {
|
||||
@@ -573,12 +573,12 @@ void handle_rlf_sync(NR_UE_Timers_Constants_t *tac,
|
||||
else {
|
||||
// OUT_OF_SYNC
|
||||
tac->N311_cnt = 0;
|
||||
if(is_nr_timer_active(tac->T300) ||
|
||||
is_nr_timer_active(tac->T301) ||
|
||||
is_nr_timer_active(tac->T304) ||
|
||||
is_nr_timer_active(tac->T310) ||
|
||||
is_nr_timer_active(tac->T311) ||
|
||||
is_nr_timer_active(tac->T319))
|
||||
if(nr_timer_is_active(&tac->T300) ||
|
||||
nr_timer_is_active(&tac->T301) ||
|
||||
nr_timer_is_active(&tac->T304) ||
|
||||
nr_timer_is_active(&tac->T310) ||
|
||||
nr_timer_is_active(&tac->T311) ||
|
||||
nr_timer_is_active(&tac->T319))
|
||||
return;
|
||||
tac->N310_cnt++;
|
||||
// upon receiving N310 consecutive "out-of-sync" indications
|
||||
|
||||
@@ -787,7 +787,7 @@ sctp_eNB_read_from_socket(
|
||||
SCTP_ERROR("sctp_recvmsg (fd %d, len %d ): %s:%d\n", sctp_cnx->sd, n, strerror(errno), errno);
|
||||
|
||||
sctp_itti_send_association_resp(
|
||||
sctp_cnx->task_id, sctp_cnx->instance, -1,
|
||||
sctp_cnx->task_id, sctp_cnx->instance, sctp_cnx->assoc_id,
|
||||
sctp_cnx->cnx_id, SCTP_STATE_UNREACHABLE, 0, 0);
|
||||
|
||||
close(sctp_cnx->sd);
|
||||
|
||||
Reference in New Issue
Block a user