Add telnet trigger for N2 handover
* the command gets in input the neighbour PCI and the UE ID * the telnet ci function to retrieve the UE context was extended in the process * add function to trigger handover on the same gNB for testing purposes Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
This commit is contained in:
co-authored by
batuhan duyuler
parent
cb68d817f0
commit
5227becf89
@@ -38,6 +38,7 @@
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/RRC/NR/rrc_gNB_mobility.h"
|
||||
|
||||
#define TELNETSERVERCODE
|
||||
#include "telnetsrv.h"
|
||||
@@ -196,6 +197,53 @@ int rrc_gNB_trigger_f1_ho(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void nr_HO_N2_trigger_telnet(gNB_RRC_INST *rrc, uint32_t neighbour_pci, uint32_t rrc_ue_id);
|
||||
|
||||
/** @brief Trigger N2 handover for UE
|
||||
* @param buf: Neighbour PCI, SCell PCI, RRC UE ID
|
||||
* @param debug: Debug flag
|
||||
* @param prnt: Print function
|
||||
* @return 0 on success, -1 on failure */
|
||||
int rrc_gNB_trigger_n2_ho(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
if (!RC.nrrrc)
|
||||
ERROR_MSG_RET("no RRC present, cannot list counts\n");
|
||||
|
||||
if (!buf) {
|
||||
ERROR_MSG_RET("Please provide neighbour cell id and ue id\n");
|
||||
} else {
|
||||
// Parse neighbour cell PCI
|
||||
char *token = strtok(buf, ",");
|
||||
if (!token) {
|
||||
ERROR_MSG_RET("Invalid input. Expected format: Neighbour PCI, ueId\n");
|
||||
}
|
||||
uint32_t neighbour_pci = strtol(token, NULL, 10);
|
||||
|
||||
// Parse ueId
|
||||
token = strtok(NULL, ",");
|
||||
if (!token) {
|
||||
ERROR_MSG_RET("Missing UE ID\n");
|
||||
}
|
||||
uint32_t ueId = strtol(token, NULL, 10);
|
||||
|
||||
// Retrieve UE context
|
||||
rrc_gNB_ue_context_t *ue_p = rrc_gNB_get_ue_context(RC.nrrrc[0], ueId);
|
||||
if (!ue_p) {
|
||||
ERROR_MSG_RET("UE with id %u not found\n", ueId);
|
||||
}
|
||||
gNB_RRC_UE_t *UE = &ue_p->ue_context;
|
||||
|
||||
// Trigger N2 handover
|
||||
nr_HO_N2_trigger_telnet(RC.nrrrc[0], neighbour_pci, UE->rrc_ue_id);
|
||||
|
||||
// Print success message
|
||||
prnt("RRC N2 handover triggered for UE %u with neighbour cell id %u\n",
|
||||
ueId,
|
||||
neighbour_pci);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int force_ul_failure(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
if (!RC.nrmac)
|
||||
@@ -245,6 +293,7 @@ static telnetshell_cmddef_t cicmds[] = {
|
||||
{"trigger_f1_ho", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_f1_ho},
|
||||
{"fetch_du_by_ue_id", "[rrc_ue_id(int,opt)]", fetch_du_by_ue_id},
|
||||
{"get_current_bwp", "[rnti(hex,opt)]", get_current_bwp},
|
||||
{"trigger_n2_ho", "[neighbour_pci(uint32_t),ueId(uint32_t)]", rrc_gNB_trigger_n2_ho},
|
||||
{"", "", NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -549,3 +549,52 @@ void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc,
|
||||
rrc_gNB_send_NGAP_HANDOVER_REQUIRED(rrc, ue, neighbour_config, hoPrepInfo);
|
||||
free_byte_array(hoPrepInfo);
|
||||
}
|
||||
|
||||
extern const nr_neighbour_cell_t *get_neighbour_cell_by_pci(const neighbour_cell_configuration_t *cell, int pci);
|
||||
extern const neighbour_cell_configuration_t *get_neighbour_cell_config(const gNB_RRC_INST *rrc, int cell_id);
|
||||
|
||||
void nr_HO_N2_trigger_telnet(gNB_RRC_INST *rrc, uint32_t neighbour_pci, uint32_t rrc_ue_id)
|
||||
{
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, rrc_ue_id);
|
||||
if (ue_context_p == NULL) {
|
||||
LOG_E(NR_RRC, "N2 HO trigger failed for UE %d: cannot find UE context\n", rrc_ue_id);
|
||||
return;
|
||||
}
|
||||
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
|
||||
|
||||
struct nr_rrc_du_container_t *du = get_du_for_ue(rrc, rrc_ue_id);
|
||||
if (du == NULL) {
|
||||
LOG_E(NR_RRC, "N2 HO trigger failed for UE %d: Unknown DU\n", rrc_ue_id);
|
||||
return;
|
||||
}
|
||||
uint16_t scell_pci = du->setup_req->cell[0].info.nr_pci;
|
||||
|
||||
// Simulate handover on the same cell (testing purposes)
|
||||
if (neighbour_pci == scell_pci) {
|
||||
LOG_I(NR_RRC, "UE %d: trigger handover on the same cell PCI=%d\n", rrc_ue_id, neighbour_pci);
|
||||
nr_neighbour_cell_t neighbourConfig = {
|
||||
.isIntraFrequencyNeighbour = true,
|
||||
.gNB_ID = du->setup_req->gNB_DU_id,
|
||||
.nrcell_id = du->setup_req->cell[0].info.nr_cellid,
|
||||
.physicalCellId = du->setup_req->cell[0].info.nr_pci,
|
||||
.plmn = du->setup_req->cell[0].info.plmn,
|
||||
.subcarrierSpacing = du->setup_req->cell[0].info.tdd.tbw.scs,
|
||||
};
|
||||
nr_rrc_trigger_n2_ho(rrc, UE, neighbour_pci, &neighbourConfig);
|
||||
return;
|
||||
}
|
||||
|
||||
const f1ap_served_cell_info_t *scell_du = get_cell_information_by_phycellId(scell_pci);
|
||||
DevAssert(scell_du);
|
||||
LOG_I(NR_RRC, "UE %d: triggered N2 HO, source PCI=%d to target PCI=%d\n", rrc_ue_id, scell_pci, neighbour_pci);
|
||||
|
||||
const neighbour_cell_configuration_t *cell = get_neighbour_cell_config(rrc, scell_du->nr_cellid);
|
||||
const nr_neighbour_cell_t *neighbour = get_neighbour_cell_by_pci(cell, neighbour_pci);
|
||||
|
||||
if (neighbour == NULL) {
|
||||
LOG_E(NR_RRC, "N2 HO trigger failed for UE %d: could not find neighbour cell with PCI=%d\n", rrc_ue_id, neighbour_pci);
|
||||
return;
|
||||
}
|
||||
|
||||
nr_rrc_trigger_n2_ho(rrc, UE, scell_du->nr_pci, neighbour);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user