Merge remote-tracking branch 'origin/telnet-o1' into integration_2024_w50 (!3125)
Add support for O1 in O-DU via telnet This change set adds a simple telnet interface to nr-softmodem. Together with oai/o1-adapter>, this implements a part of the O1 interface, for the DU only. Currently supported uses cases: - some stats are send to an SMO (such as bandwidth, PLMN, frequency, ...) - re-configuration of bandwidth, frequency - stop/start of the softmodem, while keeping the CU and L2 running - the o1-adapter implements two alarms, load overload and base station offline, using this interface. It is possible to use the telnet interface by itself (i.e., "o1" without the o1-adapter). To do this, compile with telnet support (./build_oai --build-lib telnetsrv) and start the nr-softmodem with O1 module (./nr-softmodem --telnetsrv --telnetsrv.shrmod o1). You can then do the following: - see some statistics as exposed to o1-adapter, in JSON: echo o1 stats | nc 127.0.0.1 9090 && echo - stop the L1: echo o1 stop_modem | nc 127.0.0.1 9090 && echo - reconfigure bandwidth: e.g., echo o1 bwconfig 20 | nc 127.0.0.1 9090 && echo (also supported: 40, 60, 100) - start the L1: echo o1 start_modem | nc 127.0.0.1 9090 && echo Note that the reconfiguration works with split-8 radios. Notably, it does not work yet out-of-the-box with 7.2 radios, because they have to be manually reconfigured on bandwith/frequency switch. The planned M-plane should allow such use case, though. To help with the above, this branch also includes fixes (for more information, refer to the corresponding commits): - fixes for stopping the L1, notably stop threads in right order, stop thread pool of RU - collect some general MAC metrics, fix some bugs in MAC - fix problems in F1AP gNB-DU configuration update message, update test - fix some problems in RRC
This commit is contained in:
@@ -920,10 +920,14 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc
|
||||
}
|
||||
|
||||
|
||||
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay){
|
||||
|
||||
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay)
|
||||
{
|
||||
//TODO change to accomodate for SRS
|
||||
|
||||
const NR_PUSCH_TimeDomainResourceAllocationList_t *tda =
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
|
||||
AssertFatal(tda->list.count == 0, "already have pusch_TimeDomainAllocationList members\n");
|
||||
|
||||
frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
|
||||
const int k2 = min_fb_delay;
|
||||
|
||||
|
||||
+28
-16
@@ -106,6 +106,21 @@ extern RAN_CONTEXT_t RC;
|
||||
|
||||
mui_t rrc_gNB_mui = 0;
|
||||
|
||||
typedef struct deliver_ue_ctxt_release_data_t {
|
||||
gNB_RRC_INST *rrc;
|
||||
f1ap_ue_context_release_cmd_t *release_cmd;
|
||||
sctp_assoc_t assoc_id;
|
||||
} deliver_ue_ctxt_release_data_t;
|
||||
|
||||
static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id)
|
||||
{
|
||||
DevAssert(deliver_pdu_data != NULL);
|
||||
deliver_ue_ctxt_release_data_t *data = deliver_pdu_data;
|
||||
data->release_cmd->rrc_container = (uint8_t*) buf;
|
||||
data->release_cmd->rrc_container_length = size;
|
||||
data->rrc->mac_rrc.ue_context_release_command(data->assoc_id, data->release_cmd);
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------------------------------------------------///
|
||||
///---------------------------------------------------------------------------------------------------------------///
|
||||
|
||||
@@ -1974,8 +1989,18 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, req->gNB_CU_ue_id);
|
||||
// TODO what happens if no AMF connected? should also handle, set an_release true
|
||||
if (!ue_context_p) {
|
||||
LOG_E(RRC, "could not find UE context for CU UE ID %u, aborting transaction\n", req->gNB_CU_ue_id);
|
||||
// TODO just request the DU to release to make it happy
|
||||
LOG_W(RRC, "could not find UE context for CU UE ID %u: auto-generate release command\n", req->gNB_CU_ue_id);
|
||||
uint8_t buffer[RRC_BUF_SIZE] = {0};
|
||||
int size = do_NR_RRCRelease(buffer, RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(0));
|
||||
f1ap_ue_context_release_cmd_t ue_context_release_cmd = {
|
||||
.gNB_CU_ue_id = req->gNB_CU_ue_id,
|
||||
.gNB_DU_ue_id = req->gNB_DU_ue_id,
|
||||
.cause = F1AP_CAUSE_RADIO_NETWORK,
|
||||
.cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release
|
||||
.srb_id = DCCH,
|
||||
};
|
||||
deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd};
|
||||
nr_pdcp_data_req_srb(req->gNB_CU_ue_id, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2473,6 +2498,7 @@ void *rrc_gnb_task(void *args_p) {
|
||||
switch (ITTI_MSG_ID(msg_p)) {
|
||||
case TERMINATE_MESSAGE:
|
||||
LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n");
|
||||
timer_remove(stats_timer_id);
|
||||
itti_exit_task();
|
||||
break;
|
||||
|
||||
@@ -2645,20 +2671,6 @@ void rrc_gNB_generate_SecurityModeCommand(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p)
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, buffer, size);
|
||||
}
|
||||
|
||||
typedef struct deliver_ue_ctxt_release_data_t {
|
||||
gNB_RRC_INST *rrc;
|
||||
f1ap_ue_context_release_cmd_t *release_cmd;
|
||||
sctp_assoc_t assoc_id;
|
||||
} deliver_ue_ctxt_release_data_t;
|
||||
static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id)
|
||||
{
|
||||
DevAssert(deliver_pdu_data != NULL);
|
||||
deliver_ue_ctxt_release_data_t *data = deliver_pdu_data;
|
||||
data->release_cmd->rrc_container = (uint8_t*) buf;
|
||||
data->release_cmd->rrc_container_length = size;
|
||||
data->rrc->mac_rrc.ue_context_release_command(data->assoc_id, data->release_cmd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
* Generate the RRC Connection Release to UE.
|
||||
|
||||
@@ -448,7 +448,7 @@ static void update_cell_info(nr_rrc_du_container_t *du, const f1ap_served_cell_i
|
||||
f1ap_served_cell_info_t *ci = &du->setup_req->cell[0].info;
|
||||
// make sure no memory is allocated
|
||||
free_f1ap_cell(ci, NULL);
|
||||
copy_f1ap_served_cell_info(ci, new_ci);
|
||||
*ci = copy_f1ap_served_cell_info(new_ci);
|
||||
|
||||
NR_MeasurementTimingConfiguration_t *new_mtc =
|
||||
extract_mtc(new_ci->measurement_timing_config, new_ci->measurement_timing_config_len);
|
||||
@@ -505,8 +505,10 @@ void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update
|
||||
// MIB is mandatory, so will be overwritten. SIB1 is optional, so will
|
||||
// only be overwritten if present in sys_info
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MIB, du->mib);
|
||||
if (sys_info->sib1 != NULL)
|
||||
if (sys_info->sib1 != NULL) {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SIB1, du->sib1);
|
||||
du->sib1 = NULL;
|
||||
}
|
||||
|
||||
NR_MIB_t *mib = NULL;
|
||||
if (!extract_sys_info(sys_info, &mib, &du->sib1)) {
|
||||
@@ -531,8 +533,6 @@ void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update
|
||||
/* Send DU Configuration Acknowledgement */
|
||||
f1ap_gnb_du_configuration_update_acknowledge_t ack = {.transaction_id = conf_up->transaction_id};
|
||||
rrc->mac_rrc.gnb_du_configuration_update_acknowledge(assoc_id, &ack);
|
||||
/* free F1AP message after use */
|
||||
free_f1ap_du_configuration_update(conf_up);
|
||||
}
|
||||
|
||||
void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id)
|
||||
|
||||
Reference in New Issue
Block a user