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:
Robert Schmidt
2024-12-16 19:42:28 +01:00
35 changed files with 944 additions and 168 deletions
@@ -1941,7 +1941,8 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP,
NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti);
if (!UE) {
LOG_E(NR_MAC, "want to generate %s, but rnti %04x not in the table\n", ra_type_str, ra->rnti);
LOG_E(NR_MAC, "want to generate %s, but rnti %04x not in the table. Abort RA\n", ra_type_str, ra->rnti);
nr_clear_ra_proc(ra);
return;
}
@@ -938,6 +938,9 @@ void nr_schedule_ue_spec(module_id_t module_id,
NR_UEs_t *UE_info = &gNB_mac->UE_info;
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE);
UE_iterator(UE_info->list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP;
@@ -1252,6 +1255,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti),
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock, TBS));
UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize;
gNB_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize;
} else { /* initial transmission */
LOG_D(NR_MAC, "Initial HARQ transmission in %d.%d\n", frame, slot);
uint8_t *buf = (uint8_t *) harq->transportBlock;
@@ -1369,6 +1373,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
UE->mac_stats.dl.num_mac_sdu += sdus;
UE->mac_stats.dl.current_rbs = sched_pdsch->rbSize;
UE->mac_stats.dl.total_sdu_bytes += dlsch_total_bytes;
gNB_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize;
/* save retransmission information */
harq->sched_pdsch = *sched_pdsch;
@@ -3319,7 +3319,7 @@ bool nr_mac_request_release_ue(const gNB_MAC_INST *nrmac, int rnti)
.gNB_CU_ue_id = ue_data.secondary_ue,
.gNB_DU_ue_id = rnti,
.cause = F1AP_CAUSE_RADIO_NETWORK,
.cause_value = F1AP_CauseRadioNetwork_rl_failure_others,
.cause_value = F1AP_CauseRadioNetwork_rl_failure_rlc,
};
nrmac->mac_rrc.ue_context_release_request(&request);
return true;
@@ -99,7 +99,8 @@ static bool check_plmn_identity(const f1ap_plmn_t *check_plmn, const f1ap_plmn_t
return plmn->mcc == check_plmn->mcc && plmn->mnc_digit_length == check_plmn->mnc_digit_length && plmn->mnc == check_plmn->mnc;
}
static void du_clear_all_ue_states()
/* not static, so we can call it from the outside (in telnet) */
void du_clear_all_ue_states()
{
gNB_MAC_INST *mac = RC.nrmac[0];
NR_SCHED_LOCK(&mac->sched_lock);
+1 -3
View File
@@ -82,10 +82,8 @@ static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_upd
f1ap_gnb_du_configuration_update_t cp = cp_f1ap_du_configuration_update(upd);
/* transfer to ITTI message */
F1AP_GNB_DU_CONFIGURATION_UPDATE(msg) = cp;
/* free after copy */
free_f1ap_du_configuration_update(upd);
/* send to RRC task */
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
itti_send_msg_to_task(TASK_DU_F1, 0, msg);
}
static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp)
+7
View File
@@ -807,6 +807,11 @@ typedef struct {
int8_t nvipc_poll_core;
} nvipc_params_t;
typedef struct {
uint64_t total_prb_aggregate;
uint64_t used_prb_aggregate;
} mac_stats_t;
/*! \brief top level eNB MAC structure */
typedef struct gNB_MAC_INST_s {
/// Ethernet parameters for northbound midhaul interface
@@ -930,6 +935,8 @@ typedef struct gNB_MAC_INST_s {
pthread_mutex_t sched_lock;
mac_stats_t mac_stats;
} gNB_MAC_INST;
#endif /*__LAYER2_NR_MAC_GNB_H__ */