Merge remote-tracking branch 'origin/pdu-session-initial-setup' into integration_2024_w05
This commit is contained in:
+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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1698,7 +1698,7 @@ 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);
|
||||
LOG_D(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;
|
||||
}
|
||||
|
||||
|
||||
@@ -2851,11 +2851,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 +2911,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 +3092,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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
+448
-642
File diff suppressed because it is too large
Load Diff
+172
-140
@@ -201,10 +201,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 +362,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 +487,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 +499,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 +544,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,9 +794,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 +820,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 +865,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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