Merge remote-tracking branch 'origin/f1-handover-procedures' into integration_2024_w43 (!2786)
Add F1 Handover procedures - Clean up at RRC and MAC - Add DU handover procedures, completely handle CellGroupConfig at DU - Add CU handover procedures - Maintain reestablishment working between/after handover - Changes at UE to resync on different frequency DUs Instructions: see doc/handover-tutorial.md Things not implemented/open/missing: see #855
This commit is contained in:
@@ -59,8 +59,8 @@ This is the current status:
|
||||
* SA
|
||||
* Single cell per DU
|
||||
* Multiple DUs connected to one CU (both CP and UP)
|
||||
* Mobility between DUs connected to a single CU
|
||||
- Not supported:
|
||||
* Mobility
|
||||
* NSA
|
||||
|
||||
## F1-C
|
||||
|
||||
@@ -137,6 +137,7 @@ These modes of operation are supported:
|
||||
- evaluation of CQI report
|
||||
- MAC scheduling of SR reception
|
||||
- Support of up to 16 UEs (can be increased to 32)
|
||||
- Intra-frequency handover
|
||||
|
||||
## gNB RLC
|
||||
|
||||
@@ -221,6 +222,7 @@ These modes of operation are supported:
|
||||
- Interface with RRC
|
||||
- Interface with GTP-u (tunnel creation/handling for F1-U interface)
|
||||
- One CU(-CP) can handle multiple DUs
|
||||
- Support for intra-CU mobility (across DUs)
|
||||
|
||||
## gNB E1AP
|
||||
|
||||
|
||||
@@ -143,10 +143,13 @@ In the last lines:
|
||||
|
||||
# Configuration of the MAC
|
||||
|
||||
## Split-related options
|
||||
## Split-related options (running in a DU)
|
||||
|
||||
See [nFAPI documentation](../L2NFAPI.md) or [Aerial
|
||||
tutorial](../Aerial_FAPI_Split_Tutorial.md).
|
||||
tutorial](../Aerial_FAPI_Split_Tutorial.md) for information about the FAPI
|
||||
split.
|
||||
|
||||
See [F1 documentation](../F1-design.md) for information about the F1 split.
|
||||
|
||||
## MAC scheduler-related configuration options
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https://
|
||||
- [How to run with E2 agent](../openair2/E2AP/README.md)
|
||||
- [How to run the physical simulators](./physical-simulators.md)
|
||||
- [How to setup OAI with Nvidia Aerial and Foxconn](./Aerial_FAPI_Split_Tutorial.md)
|
||||
- [How to do a handover](./handover-tutorial.md)
|
||||
|
||||
Legacy unmaintained files:
|
||||
- [`L2NFAPI_NOS1.md`](./L2NFAPI_NOS1.md), [`L2NFAPI_S1.md`](./L2NFAPI_S1.md):
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
block-beta
|
||||
columns 5
|
||||
space space DU0 space UE
|
||||
CU space space space space
|
||||
space space DU1 space pos["new pos"]
|
||||
CU<-- "F1" -->DU0
|
||||
CU<-- "F1" -->DU1
|
||||
DU0-- "Uu" -->UE
|
||||
UE-- "move" -->pos
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
@@ -0,0 +1,318 @@
|
||||
This document contains documentation for the 5G RRC layer, destined towards
|
||||
developers. It explains the basic working of the RRC, and various UE procedure
|
||||
schemes (connection, reestablishment, handover) including their interworking
|
||||
with other layers.
|
||||
|
||||
User documentation, such as general configuration options, are described in [a
|
||||
separate page](./rrc-usage.md).
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
# General
|
||||
|
||||
5G RRC is basically an ITTI message queue with associated handlers. It
|
||||
sequentially reads received ITTI messages and handles them through the function
|
||||
`rrc_gnb_task()` (constituing the thread entry point function). In this
|
||||
function, one can see three main groups of messages in a big switch statement:
|
||||
|
||||
- NGAP (messages starting with `NGAP_`)
|
||||
- F1AP (messages starting with `F1AP_`)
|
||||
- E1AP (messages starting with `E1AP_`)
|
||||
|
||||
For each message, a corresponding handler is called. The messages are roughly
|
||||
named according to the 3GPP specification messages, so it should already be
|
||||
possible to find the message in the switch based on a message name in the spec.
|
||||
|
||||
Note that RRC is inherently single-threaded, and processes messages in a FIFO
|
||||
order.
|
||||
|
||||
# Sequence Diagrams of UE procedures
|
||||
|
||||
The following section presents a number of common UE procedures for connection
|
||||
establishment&control, bearer establishment, etc. The intention is to help
|
||||
developers find specific functions within RRC in the context of these
|
||||
procedures. For more information on message handlers at F1 and E1 layers,
|
||||
please refer to the respective [F1 documentation](../F1AP/F1-design.md) and [E1
|
||||
documentation](../E1AP/E1-design.md).
|
||||
|
||||
For more information on these procedures, please also refer to 3GPP TS 38.401
|
||||
(NG-RAN Architecture Description) and O-RAN.WG5.C.1-v11 (NR C-plane profile).
|
||||
|
||||
A lot of the following diagrams would show an exchange between CU-CP, DU, and
|
||||
UE, in which the CU-CP forwards an "RRC Message" to the UE via an F1AP DL RRC
|
||||
Message Transfer through the DU, and correspondingly receives the "RRC Message
|
||||
Answer", as follows:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant ue as UE
|
||||
participant du as DU
|
||||
participant cucp as CU-CP
|
||||
cucp->>du: F1AP DL RRC Msg Transfer (RRC Message)
|
||||
du->>ue: RRC Message
|
||||
ue->>du: RRC Message Answer
|
||||
du->>cucp: F1AP UL RRC Msg Transfer (RRC Message Answer)
|
||||
```
|
||||
|
||||
To better utilize horizontal space, these exchanges have been collapsed as
|
||||
follows, but should be read as the above exchange:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant ue as UE
|
||||
participant du as DU
|
||||
participant cucp as CU-CP
|
||||
cucp->>ue: F1AP DL RRC Msg Transfer (RRC Message)
|
||||
ue->>cucp: F1AP UL RRC Msg Transfer (RRC Message Answer)
|
||||
```
|
||||
|
||||
## Initial connection setup/Registration
|
||||
|
||||
This sequence diagram shows the principal steps for an initial UE connection.
|
||||
This can either happen through a _Registration Request_ (e.g., UE connects
|
||||
"from flight mode"), or a _Service Request_ (i.e., UE connects after leaving
|
||||
coverage). Both requests are handled similarly by the gNB, and basically
|
||||
distinguish themselves, from the point of view of the gNB, by having PDU
|
||||
sessions in the NGAP Initial Context Setup Request present (Service Request) or
|
||||
not (Registration Request, with following PDU Session Resource Setup Request
|
||||
procedure).
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant ue as UE
|
||||
participant du as DU
|
||||
participant cucp as CU-CP
|
||||
participant cuup as CU-UP
|
||||
participant amf as AMF
|
||||
|
||||
ue->>du: Msg1/Preamble
|
||||
du->>ue: Msg2/RAR
|
||||
ue->>cucp: F1AP Initial UL RRC Msg Tr (RRC Setup Req, in Msg3)
|
||||
Note over cucp: rrc_handle_RRCSetupRequest()
|
||||
cucp->>ue: F1AP DL RRC Msg Transfer (RRC Setup, in Msg4)
|
||||
ue->>cucp: F1AP UL RRC Msg Transfer (RRC Setup Complete)
|
||||
Note over cucp: rrc_handle_RRCSetupComplete()
|
||||
%% TODO: when is RRC connected?
|
||||
cucp->>amf: NGAP Initial UE Message (NAS Registration/Service Req)
|
||||
Note over amf,ue: NAS Authentication Procedure (see 24.501)
|
||||
Note over amf,ue: NAS Security Procedure (see 24.501)
|
||||
amf->>cucp: NGAP Initial Context Setup Req
|
||||
Note over cucp: rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ()
|
||||
Note over cucp: rrc_gNB_generate_SecurityModeCommand()
|
||||
cucp->>ue: F1AP DL RRC Msg Transfer (RRC Security Mode Command)
|
||||
ue->>cucp: F1AP UL RRC Msg Transfer (RRC Security Mode Complete)
|
||||
Note over cucp: rrc_gNB_decode_dcch() (inline)
|
||||
opt No UE Capabilities present
|
||||
Note over cucp: rrc_gNB_generate_UECapabilityEnquiry()
|
||||
cucp->>ue: F1AP DL RRC Msg Transfer (RRC UE Capability Enquiry)
|
||||
ue->>cucp: F1AP UL RRC Msg Transfer (RRC UE Capability Information)
|
||||
Note over cucp: handle_ueCapabilityInformation()
|
||||
end
|
||||
opt PDU Sessions in NGAP Initial Context Setup Req present
|
||||
Note over cucp: trigger_bearer_setup()
|
||||
cucp->>cuup: E1AP Bearer Context Setup Req
|
||||
cuup->>cucp: E1AP Bearer Context Setup Resp
|
||||
Note over cucp: rrc_gNB_process_e1_bearer_context_setup_resp()
|
||||
cucp->>du: F1AP UE Context Setup Req
|
||||
du->>cucp: F1AP UE Context Setup Resp
|
||||
Note over cucp: rrc_CU_process_ue_context_setup_response()
|
||||
Note over cucp: e1_send_bearer_updates()
|
||||
cucp->>cuup: E1AP Bearer Context Modification Req
|
||||
cucp->>ue: F1AP DL RRC Msg Transfer (RRC Reconfiguration)
|
||||
cuup->>cucp: E1AP Bearer Context Modification Resp
|
||||
ue->>cucp: F1AP UL RRC Msg Transfer (RRC Reconfiguration Complete)
|
||||
Note over cucp: handle_rrcReconfigurationComplete()
|
||||
end
|
||||
Note over cucp: rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP()
|
||||
cucp->>amf: NGAP Initial Context Setup Resp (NAS Registration/Service Complete)
|
||||
```
|
||||
|
||||
Note that if no PDU session is present in the NGAP Initial UE Context Setup
|
||||
Req, no F1AP UE Context Setup will be observed during this initial phase.
|
||||
|
||||
If there is no PDU session set up during NGAP Initial Context Setup Req, the UE
|
||||
typically requests a PDU session(s) through a NAS procedure, which is basically
|
||||
the same code paths as the above optional PDU Session setup during an NGAP
|
||||
Initial Context Setup procedure:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant ue as UE
|
||||
participant du as DU
|
||||
participant cucp as CU-CP
|
||||
participant cuup as CU-UP
|
||||
participant amf as AMF
|
||||
|
||||
ue->>cucp: F1AP UL RRC Msg Transfer (RRC UL Information Transfer)
|
||||
cucp->>amf: NGAP UL NAS Transport (NAS PDU Session Establishment Req)
|
||||
amf->>cucp: NGAP PDU Session Resource Setup Req (NAS PDU Session Establishment Accept)
|
||||
Note over cucp: rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ()
|
||||
Note over cucp: trigger_bearer_setup()
|
||||
cucp->>cuup: E1AP Bearer Context Setup Req
|
||||
cuup->>cucp: E1AP Bearer Context Setup Resp
|
||||
Note over cucp: rrc_gNB_process_e1_bearer_context_setup_resp()
|
||||
cucp->>du: F1AP UE Context Setup Req
|
||||
du->>cucp: F1AP UE Context Setup Resp
|
||||
Note over cucp: rrc_CU_process_ue_context_setup_response()
|
||||
Note over cucp: e1_send_bearer_updates()
|
||||
cucp->>cuup: E1AP Bearer Context Modification Req
|
||||
cucp->>ue: F1AP DL RRC Msg Transfer (RRC Reconfiguration + NAS PDU Session Establishment Accept)
|
||||
cuup->>cucp: E1AP Bearer Context Modification Resp
|
||||
ue->>cucp: F1AP UL RRC Msg Transfer (RRC Reconfiguration Complete)
|
||||
Note over cucp: handle_rrcReconfigurationComplete()
|
||||
Note over cucp: rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP()
|
||||
cucp->>amf: NGAP PDU Session Resource Setup Resp
|
||||
```
|
||||
|
||||
## Reestablishment
|
||||
|
||||
The following sequence diagram shows the principal steps during a
|
||||
reestablishment request. When handling the RRC Reestablishment Request at the
|
||||
CU-CP, it notably checks if this UE is already known, if the UE is still at the
|
||||
same DU as it used to be previously (might change because of, or despite
|
||||
handover), and other validation checks. If all checks pass, the CU-CP continues
|
||||
with the reestablishment procedure; if any check fails, the CU-CP tries to
|
||||
release the old UE at the AMF, and continues with the "normal" connection setup
|
||||
(registration/service request) described above.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant ue as UE
|
||||
participant du as DU
|
||||
participant cucp as CU-CP
|
||||
participant cuup as CU-UP
|
||||
participant amf as AMF
|
||||
|
||||
ue->>du: Msg1/Preamble
|
||||
du->>ue: Msg2/RAR
|
||||
ue->>du: Msg3 w/ RRC Reestabishment Request (old C-RNTI/PCI)
|
||||
Note over du: DU creates UE context for new RNTI
|
||||
du->>cucp: F1AP Initial UL RRC Msg Tr (RRC Reestab Req, in Msg3)
|
||||
Note over cucp: rrc_handle_RRCReestablishmentRequest()
|
||||
alt UE known and at the original DU
|
||||
Note over cucp: rrc_gNB_generate_RRCReestablishment()<br />SRB1 PDCP reestablishment
|
||||
cucp->>du: F1AP DL RRC Msg Tr (old gNB-DU-UE ID)
|
||||
Note over du: Reuse configuration of and delete old UE<br />(in dl_rrc_message_transfer())
|
||||
du->>ue: RRC Reestablishment
|
||||
ue->>du: RRC Reestablishment Complete
|
||||
du->>cucp: F1AP UL RRC Msg Tr (RRC Reestab Complete)
|
||||
Note over cucp: handle_rrcReestablishmentComplete()
|
||||
Note over cucp: cuup_notify_reestablishment()
|
||||
cucp->>cuup: E1AP Bearer Context Modification Req
|
||||
cucp->>ue: F1AP DL RRC Msg Transfer (RRC Reconfiguration)
|
||||
cuup->>cucp: E1AP Bearer Context Modification Resp
|
||||
ue->>cucp: F1AP UL RRC Msg Transfer (RRC Reconfiguration Complete)
|
||||
Note over cucp: handle_rrcReestablishmentComplete()
|
||||
else Fallback*
|
||||
cucp->>amf: NGAP UE Context Release Request
|
||||
Note over cucp: rrc_gNB_generate_RRCSetup()
|
||||
Note over ue,amf: Continue with connection setup (registration/service request)
|
||||
end
|
||||
```
|
||||
|
||||
## Handover
|
||||
|
||||
The basic handover (HO) structure is as follows. In order to support various
|
||||
handover "message passing implementation" (F1AP, NGAP, XnAP), RRC employs
|
||||
callbacks to signal HO Accept (`ho_req_ack()`), HO Success (`ho_success()`),
|
||||
and HO Cancel (`ho_cancel()`). These can be used to trigger the corresponding
|
||||
functionality based on mentioned "message passing implementation".
|
||||
|
||||
The following sequence diagram shows the basic functional execution of a
|
||||
successful handover in the case of an F1 handover. Note the callbacks as
|
||||
mentioned above:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant ue as UE
|
||||
participant sdu as source DU
|
||||
participant tdu as target DU
|
||||
participant cucp as CU-CP
|
||||
participant cuup as CU-UP
|
||||
|
||||
Note over ue,sdu: UE active on source DU
|
||||
alt HO triggered through A3 event
|
||||
ue->>sdu: RRC Measurement Report
|
||||
sdu->>cucp: F1AP UL RRC Msg Transfer (RRC Measurement Report)
|
||||
Note over cucp: Handover decision (A3 event trigger)
|
||||
else Manual Trigger
|
||||
Note over cucp: Handover decision (e.g., telnet)
|
||||
end
|
||||
Note over cucp: nr_rrc_trigger_f1_ho() ("on source CU")
|
||||
Note over cucp: nr_initiate_handover() ("on target CU")
|
||||
cucp->>tdu: F1AP UE Context Setup Req
|
||||
Note over tdu: Create UE context
|
||||
tdu->>cucp: F1AP UE Context Setup Resp (incl. CellGroupConfig)
|
||||
Note over cucp: rrc_CU_process_ue_context_setup_response() ("on target CU")
|
||||
Note over cucp: cuup_notify_reestablishment()
|
||||
cucp->>cuup: E1AP Bearer Context Modification Req
|
||||
cucp-->>cucp: callback: ho_req_ack()
|
||||
Note over cucp: nr_rrc_f1_ho_acknowledge() ("on source CU")
|
||||
cucp->>sdu: F1AP Context Modification Req (RRC Reconfiguration)
|
||||
cuup->>cucp: E1AP Bearer Context Modification Resp
|
||||
sdu->>ue: RRC Reconfiguration
|
||||
sdu->>cucp: F1AP Context Modification Resp
|
||||
Note over sdu: Stop scheduling UE
|
||||
Note over ue: Resync
|
||||
Note over ue,tdu: RA (Msg1 + Msg2)
|
||||
ue->>tdu: RRC Reconfiguration Complete
|
||||
tdu->>cucp: F1AP UL RRC Msg Transfer (RRC Reconfiguration Complete)
|
||||
Note over cucp: handle_rrcReconfigurationComplete() ("on target CU")
|
||||
cucp-->>cucp: callback: ho_success()
|
||||
Note over cucp: nr_rrc_f1_ho_complete() ("on source CU")
|
||||
cucp->>sdu: F1AP UE Context Release Command
|
||||
sdu->>cucp: F1AP UE Context Release Complete
|
||||
Note over ue,tdu: UE active on target DU
|
||||
```
|
||||
|
||||
# Structures
|
||||
|
||||
## Cells
|
||||
|
||||
OAI 5G RRC does not actually handle multiple cells as of now, but multiple DUs,
|
||||
each being limited to one cell.
|
||||
|
||||
Cell-related data is stored in `nr_rrc_du_container_t`, and kept in a tree
|
||||
indexed by the SCTP association ID.
|
||||
|
||||
## CU-UPs
|
||||
|
||||
CU-UP information is stored in `nr_rrc_cuup_container_t`, and kept in a tree
|
||||
indexed by the SCTP association ID.
|
||||
|
||||
## Transactions
|
||||
|
||||
The RRC keeps track of ongoing transaction (RRC procedures) through a per-UE
|
||||
array `xids`, which is indexed with a transaction ID `xid` in `[0,3]` to keep
|
||||
track of ongoing transactions. Upon RRC Reconfiguration Complete, these IDs are
|
||||
deleted.
|
||||
|
||||
Note that while 38.331 requires only one RRC transaction to happen at a time,
|
||||
the 5G RRC does not actually ensure this; it only tries to prevent it by
|
||||
chaining of transactions and some checks. For instance, the Security Mode
|
||||
procedure is followed by a UE capability procedure, and some procedures are not
|
||||
executed if others are ongoing (ex.: handover if there is reconfiguratio).
|
||||
However, it might be possible to trigger a procedure while another is ongoing.
|
||||
|
||||
As of now, no queueing mechanims exists to ensure only one operation is
|
||||
ongoing, which would likely also simplify the code.
|
||||
|
||||
## Handover
|
||||
|
||||
Handover-related data is stored in a per-UE structure of type
|
||||
`nr_handover_context_t`. It is a pointer and only set during handover
|
||||
operation. This data structure has in turn two pointers, one to the source CU
|
||||
(`nr_ho_source_cu_t`), and one to the target CU (`nr_ho_target_cu_t`). In F1,
|
||||
both are present. In N2 and Xn, only one pointer is supposed to be set a the
|
||||
corresponding CU.
|
||||
|
||||
`nr_ho_source_cu_t` contains notably a function pointer `ho_cancel` for
|
||||
handover cancel. `nr_ho_target_cu_t` contains function pointers `ho_req_ack`
|
||||
for handover request acknowledge and `ho_success` for handover success. As can
|
||||
be seen in the sequence diagram above, either the "target CU" or "source CU"
|
||||
needs to do an operation, and a "switch" from target to source CU is done using
|
||||
these function pointers. For instance, in F1, the handover request acknowledge
|
||||
function pointers merely calls another (RRC) function which triggers a
|
||||
reconfiguration. In the case of N2, the handover request acknowledge function
|
||||
pointer should trigger the NGAP Handover Request Acknowledge, and the handover
|
||||
success function pointer should trigger the NGAP Handover Success message.
|
||||
@@ -0,0 +1,99 @@
|
||||
This document describes the basic functioning of the 5G RRC layer, describes
|
||||
the periodic output, and explains the various configuration options that
|
||||
influence its behavior.
|
||||
|
||||
Developer documentation, such as UE connection control flow, reestablishment, or handover, are described in [a separate page](./rrc-dev.md).
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
# General
|
||||
|
||||
The RRC layer controls the basic connection setup of UEs as well as additional
|
||||
procedures. It is the fundamental building block of OAI's CU-CP, and interacts
|
||||
with lower layers (DU, basically MAC and RLC) through F1AP messages, and with
|
||||
the CU-UP through E1AP messages. More information can be found in the
|
||||
respective [F1AP page](../F1-design.md) and [E1AP page](../E1AP/E1-design.md).
|
||||
|
||||
# Periodic output and interpretation
|
||||
|
||||
Similarly to the scheduler, the RRC periodically prints information about
|
||||
connected UEs and DUs into file `nrRRC_stats.log` in the current working
|
||||
directory of the executable running the RRC (typically, `nr-softmodem`). The
|
||||
output lists first all UEs that are currently connected, and then all DUs, in
|
||||
order.
|
||||
|
||||
For each UE, it prints:
|
||||
|
||||
```
|
||||
UE 0 CU UE ID 1 DU UE ID 40352 RNTI 9da0 random identity c0f1ac9824000000:
|
||||
last RRC activity: 5 seconds ago
|
||||
PDU session 0 ID 10 status established
|
||||
associated DU: DU assoc ID 8
|
||||
```
|
||||
|
||||
where `UE 0` is the UE index, CU UE ID and DU UE IDs are the IDs used to
|
||||
exchange over F1 (cf. scheduler logs). Further, it shows RNTI, when the last
|
||||
RRC activity happened, the status of PDU sessions and which DU is associated
|
||||
(through the SCTP association ID).
|
||||
|
||||
|
||||
For each DU, it prints:
|
||||
|
||||
```
|
||||
1 connected DUs
|
||||
[1] DU ID 3584 (gNB-OAI-DU) assoc_id 8: nrCellID 12345678, PCI 0, SSB ARFCN 641280
|
||||
TDD: band 78 ARFCN 640008 SCS 30 (kHz) PRB 106
|
||||
```
|
||||
|
||||
i.e., an index (`[1]`), the DU ID and it's name, the SCTP association ID
|
||||
(`assoc_id 8`, cf. UE information), and DU specific information for the cell
|
||||
(cell ID, physical cell identity/PCI, the SSB frequency in ARFCN notation, the
|
||||
band and Point A ARFCN, subcarrier spacing/SCS, and the number of resource
|
||||
blocks/PRB). Only one cell per DU is supported.
|
||||
|
||||
As of now, it does not print information about connected CU-UPs or AMFs.
|
||||
|
||||
# Configuration of the RRC
|
||||
|
||||
## Split-related options (when running in a CU or CU-CP)
|
||||
|
||||
See [F1 documentation](../F1-design.md) for information about the F1 split.
|
||||
See [E1 documentation](../E1AP/E1-design.md) for information about the E1 split.
|
||||
|
||||
## RRC-specific configuration options
|
||||
|
||||
In the `gNBs` section of the gNB/CU/CU-CP configuration file is the
|
||||
RRC-specific configuration
|
||||
|
||||
### cell-specific options
|
||||
|
||||
- `gNB_ID` and `gNB_name`: ID and name of the gNB
|
||||
- `tracking_area_code`: the current tracking area code in the range `[0x0001,
|
||||
0xfffd]`
|
||||
- `plmn`: the PLMN, which is a list of entries consisting of:
|
||||
- `mcc`: mobile country code
|
||||
- `mnc`: mobile network code
|
||||
- `mnc_length`: length of mobile network code, allowed values: 2, 3
|
||||
- `snssaiList`: list of NSSAI (network selection slice assistence
|
||||
information, "slice ID"), which itself consists in
|
||||
- `sst`: slice service type, in `[1,255]`
|
||||
- `sd` (default `0xffffff`): slice differentiator, in `[0,0xffffff]`,
|
||||
`0xffffff` is a reserved value and means "no SD"
|
||||
Note that: SST=1, no SD is "eMBB"; SST=2, no SD is "URLLC"; SST=3, no SD
|
||||
is "mMTC"
|
||||
- `enable_sdap` (default: false): enable the use of the SDAP layer. If
|
||||
deactivated, a transparent SDAP header is prepended to packets, but no
|
||||
further processing is being done.
|
||||
|
||||
### UE-specific configuration
|
||||
|
||||
- `um_on_default_drb` (default: false): use RLC UM instead of RLC AM on default
|
||||
bearers
|
||||
- `drbs` (default: 0): the number of DRBs to allocate for a UE, only useful for
|
||||
do-ra or phy-test testing
|
||||
|
||||
### Neighbor-gNB configuration
|
||||
|
||||
TBD
|
||||
|
||||
Refer to the [handover tutorial](../handover-tutorial.md) for more information.
|
||||
@@ -0,0 +1,329 @@
|
||||
This tutorial explains how to perform handovers. For the moment, only F1
|
||||
handovers are supported.
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
# Considered setup for F1 handover
|
||||
|
||||
We consider one CU and two DUs, connected over F1. The UE is initially
|
||||
connected over the radio interface ("Uu") to DU0. Via movement to a new
|
||||
position ("new pos"), it will trigger an event such that the CU triggers a
|
||||
handover of the UE from DU0 to DU1. Alternatively, a manual trigger can do the
|
||||
same.
|
||||
|
||||

|
||||
|
||||
# Steps to run F1 handover with OAI UE
|
||||
|
||||
Measurement reporting and processing of RRC Reconfiguration for Mobility are
|
||||
not completed at the UE. Nevertheless, it is possible to make simple handover
|
||||
tests without any radio setup, on a single PC, with the OAI UE, in RFsimulator.
|
||||
|
||||
## Build with telnet support
|
||||
|
||||
Since the UE does not support any measurement reporting, it cannot trigger a
|
||||
handover on its own; it has to be triggered manually through telnet. Thus,
|
||||
build both gNB and UE as well as activate the build of telnet to that purpose:
|
||||
|
||||
./build_oai --ninja --nrUE --gNB --build-lib telnetsrv
|
||||
|
||||
## Run the setup
|
||||
|
||||
This tutorial assumes you have a core network running; [refer to the
|
||||
corresponding tutorial](./NR_SA_Tutorial_OAI_CN5G.md) if this is not the case
|
||||
yet.
|
||||
|
||||
We will use the TDD configuration files in the repository for the
|
||||
[CU](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf) as well for
|
||||
[DU0](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf)
|
||||
and
|
||||
[DU1](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf).
|
||||
Note how the DUs differ in their DU ID (for identification at the CU), nr
|
||||
cellid (global identification), physical cell ID (identification through UE),
|
||||
frequency (limitation at OAI UE), and IP address.
|
||||
|
||||
Make sure that using RFsimulator and the CU and each DU, you can achieve a full
|
||||
connection of the UE (independently, i.e., running one DU a time). Once this is
|
||||
done, follow below steps to trigger a handover:
|
||||
|
||||
Start the CU including telnet support:
|
||||
|
||||
sudo ./nr-softmodem --sa -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-cu.sa.f1.conf --telnetsrv --telnetsrv.shrmod ci
|
||||
|
||||
Start DU0:
|
||||
|
||||
sudo ./nr-softmodem --sa --rfsim -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci0.conf --rfsimulator.serveraddr 127.0.0.1
|
||||
|
||||
Start the UE, and let it connect completely:
|
||||
|
||||
sudo ./nr-uesoftmodem --sa -C 3450720000 -r 106 --numerology 1 --ssb 516 -O <config> --rfsim --rfsimulator.serveraddr server
|
||||
|
||||
Note how the RFsimulator roles have been switched, and RFsim server is at the
|
||||
UE side; _this is important_. Replace `<config>` with the UE configuration
|
||||
matching your core. If you followed the CN and oaiUE tutorials, you can remove
|
||||
`-O <config>` and replace it with `--uicc0.imsi 001010000000001`.
|
||||
|
||||
Once the UE is connected, start DU1:
|
||||
|
||||
sudo ./nr-softmodem --sa --rfsim -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.rfsim.pci1.conf --rfsimulator.serveraddr 127.0.0.1
|
||||
|
||||
Once DU1 is online, you can trigger a handover by issuing this command
|
||||
|
||||
echo ci trigger_f1_ho | nc 127.0.0.1 9090 && echo
|
||||
|
||||
You should see how the UE switches from one DU to another. See additional
|
||||
information further below.
|
||||
|
||||
A number of remarks:
|
||||
|
||||
1. It is important that you start DU0, UE, DU1 in order, and having UE connect
|
||||
to DU0 before starting DU1. This is because we don't employ any channel
|
||||
emulation, and the UE could not decode the SIB1 of DU0 to connect.
|
||||
1. The RFsimulator roles are switched. Typically, the gNB RFsim acts as the
|
||||
server and the UE as a client. However, RFsim is limited to one server with
|
||||
multiple clients. Since the UE should be able to connect to both DUs, it has
|
||||
to act as the server, and both DUs are a client.
|
||||
1. If you see errors `could not open a socket` and/or `Could not start the RF
|
||||
device`, this means that RFsim could not be started. Handover will not work;
|
||||
please refer to the preceding point to fix this (i.e., run the UE as the
|
||||
RFsim server).
|
||||
1. In some cases, if the RFsim server is at the UE, the whole system can block;
|
||||
in this case, stop UE and all DUs and restart (the CU can keep running).
|
||||
|
||||
## Additional information to the manual HO trigger
|
||||
|
||||
You can trigger the handover manually by logging in through telnet:
|
||||
|
||||
telnet 127.0.0.1 9090
|
||||
|
||||
and then manually typing `ci trigger_f1_ho`.
|
||||
|
||||
The command using `nc` (`netcat`) above triggers handovers directly from bash.
|
||||
It does the same as logging in through telnet otherwise, and is a shorthand.
|
||||
|
||||
The full command is
|
||||
|
||||
ci trigger_f1_ho [cu-ue-id]
|
||||
|
||||
`cu-ue-id` is optional. If only one UE context is present in the RRC, it will
|
||||
trigger the handover for this UE in a round-robin fashion across all DUs. If
|
||||
there is only one DU, the handover request will be rejected. Similarly, if
|
||||
there are multiple UE contexts present at RRC, the handover will be rejected,
|
||||
and you have to manually type the CU UE ID. You can see a list of all UEs in
|
||||
the file `nrRRC_stats.log` that is printed periodically in the working
|
||||
directory of the CU.
|
||||
|
||||
# Steps to run F1 handover with COTS UE
|
||||
|
||||
You can do handover across DUs with a COTS UE. Note that these DUs should be
|
||||
separated by at least multiple meters to ensure that the UE will receive
|
||||
different signal strengths when moving between cells.
|
||||
|
||||
We only support intra-frequency handovers yet. We have verified with USRPs
|
||||
only, although other radios should work as well.
|
||||
|
||||
For UEs, we verified Quectel modules and iPhones. Note, though, that not all
|
||||
phones might work; for instance, we did not achieve handovers with a OnePlus
|
||||
Nord, yet.
|
||||
|
||||
## Steps
|
||||
|
||||
First, make sure that you can run both DUs with the CU independently. Use the
|
||||
same radio hardware for both radios to ensure that both cells can be received
|
||||
equally good by the UE.
|
||||
|
||||
In order to enable handovers (triggered by the UE), you have to configure the
|
||||
neighbour relation of the DUs at the CU. To do so, proceed as follows:
|
||||
|
||||
1. To simplify filling the right values in the neighbour configuration, you can
|
||||
rely on the information the CU has about both DUs. Start the CU and both
|
||||
DUs. Navigate to the directory from which you started the CU, and print RRC
|
||||
statistics:
|
||||
```
|
||||
cat nrRRC_stats.log
|
||||
```
|
||||
1. Fill in the `neighbour-config.conf` configuration file as shown below, and
|
||||
`@include` it in the CU file.
|
||||
1. Start the CU and both DUs.
|
||||
1. Bring the phone close to one cell, and leave flight mode. It should connect
|
||||
to the DU to which it is closer.
|
||||
1. Move the UE towards the other DU; it should trigger an "A3 event" (Neighbour
|
||||
Becomes Better than Serving), and the CU will trigger the handover to the
|
||||
other DU.
|
||||
|
||||
The output on the terminal should be the same as with RFsim. If no handover is
|
||||
triggered:
|
||||
|
||||
- Make sure that both DUs use the same hardware.
|
||||
- Make sure that the UE sees both cells. For instance, you can switch to flight
|
||||
mode, go closer to the other DU, and switch off flight mode -- the UE should
|
||||
connect to that second UE.
|
||||
- We did not manage handover with every phone yet -- make sure you use one of
|
||||
the list provided above.
|
||||
|
||||
You can also force a handover through telnet as described above. (In fact, the
|
||||
decision about a handover is always at the network-side, the UE only "assists"
|
||||
through measurements telling the CU that one DU is stronger than others.
|
||||
Hence, "forcing" a handover just means that you manually trigger the handover,
|
||||
instead of waiting for UE measurement report.)
|
||||
|
||||
## Example neighbour configuration
|
||||
|
||||
Below is an example neighbour configuration. It is based on this DU information
|
||||
gathered from `nrRRC_stats.log` at the CU:
|
||||
|
||||
```
|
||||
[1] DU ID 3585 (gNB-in-docker) assoc_id 4161: nrCellID 11111111, PCI 1, SSB ARFCN 643296
|
||||
TDD: band 78 ARFCN 642024 SCS 30 (kHz) PRB 106
|
||||
[2] DU ID 3584 (gNB-in-docker) assoc_id 4163: nrCellID 12345678, PCI 0, SSB ARFCN 643296
|
||||
TDD: band 78 ARFCN 642024 SCS 30 (kHz) PRB 106
|
||||
```
|
||||
|
||||
Note how both DUs have one cell on the same frequency and the same radio
|
||||
configuration. From this, fill the neighbour list as shown below.
|
||||
|
||||
Concretely, the first cell is `12345678` (on DU `[2]`), and it has `11111111`
|
||||
(on DU `[1]`) as its neighbour; hence in the first block, you fill
|
||||
`physical_cellId` and other values for DU `[1]`, and vice versa.
|
||||
|
||||
The below configuration further enables periodic measurements, A2 event
|
||||
("Serving becomes worse than threshold"), and A3 events ("Neighbour Becomes
|
||||
Better than Serving"). The A2 event can be disabled by setting `enable = 0`. A3
|
||||
events cannot be disabled as of now. Further, the A3 events can be made
|
||||
specific to cells; `cell_id = -1` means "any cell".
|
||||
|
||||
```
|
||||
neighbour_list = (
|
||||
{
|
||||
nr_cellid = 12345678;
|
||||
neighbour_cell_configuration = (
|
||||
{
|
||||
gNB_ID = 0xe01;
|
||||
nr_cellid = 11111111;
|
||||
physical_cellId = 1;
|
||||
absoluteFrequencySSB = 643296;
|
||||
subcarrierSpacing = 1; #30 KHz
|
||||
plmn = { mcc = 001; mnc = 01; mnc_length = 2};
|
||||
tracking_area_code = 1;
|
||||
}
|
||||
)
|
||||
},
|
||||
{
|
||||
nr_cellid = 11111111;
|
||||
neighbour_cell_configuration = (
|
||||
{
|
||||
gNB_ID = 0xe00;
|
||||
nr_cellid = 12345678;
|
||||
physical_cellId = 0;
|
||||
absoluteFrequencySSB = 643296;
|
||||
subcarrierSpacing = 1; #30 KHz
|
||||
plmn = { mcc = 001; mnc = 01; mnc_length = 2};
|
||||
tracking_area_code = 1;
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
nr_measurement_configuration = {
|
||||
Periodical = {
|
||||
enable = 1;
|
||||
includeBeamMeasurements = 1;
|
||||
maxNrofRS_IndexesToReport = 4;
|
||||
};
|
||||
|
||||
A2 = {
|
||||
enable = 1;
|
||||
threshold = 60;
|
||||
timeToTrigger = 1;
|
||||
};
|
||||
|
||||
A3 = ({
|
||||
cell_id = -1; #Default
|
||||
offset = 10;
|
||||
hysteresis = 0;
|
||||
timeToTrigger = 1
|
||||
})
|
||||
};
|
||||
```
|
||||
|
||||
# Handovers triggers and NTN
|
||||
|
||||
Typically, in terrestrial networks, channel measurements as well as criteria
|
||||
such as load in base stations, is used to determine when and where to handover
|
||||
a UE.
|
||||
|
||||
## NTN
|
||||
|
||||
Doppler spreading and time selectivity of the channel are already a challenge
|
||||
for conventional terrestrial networks. However, in the context of
|
||||
non-terrestrial networks (NTN), and low-earth orbit (LEO) systems, the
|
||||
satellites can have speeds up 7.56 km/s, which is much faster than 0.14 km/s of
|
||||
a high-speed train in terrestrial networks. Also, the delays in LEO are more varied
|
||||
and longer, and the path loss is larger, because the communication distances is up
|
||||
to 10 times longer than in terrestrial networks. Moreover, downlink in LEO
|
||||
presents a high interference from adjacent satellite beams, and all these
|
||||
features contribute to reduced received signal strength variation in these
|
||||
networks compared to terrestrial networks. Typically, the criteria used in
|
||||
algorithms presented in conventional terrestrial networks to trigger a handover
|
||||
from a gNB to another one is based on signal strength measurements (cf., A3
|
||||
event above). However, the reduced received signal strength variation in NTNs
|
||||
make these algorithms inefficient for LEO systems. Therefore, algorithms with
|
||||
criteria for handover triggering that address the specifics of LEO systems are
|
||||
crucial for an efficient handover processing that ensures a robust
|
||||
communication with low dropping probability. Some criteria for handovers in NTN
|
||||
are as follows:
|
||||
|
||||
- **Measurement-based triggering**: This method is based on signal strength
|
||||
measurement, and as stated above, it may not be efficient. The triggering
|
||||
thresholds and which measurement events to use as triggers, as reference
|
||||
signal received power (RSRP), reference signal received quality (RSRQ), or
|
||||
received signal strength indicator (RSSI), should be configured. This method
|
||||
relies on UE estimates and established channel estimation techniques, however
|
||||
it would require neighbouring cell lists which can be hard because the
|
||||
fast-moving of satellites leads to a fast cell coverage deviation.
|
||||
|
||||
- **Location-based triggering**: This method is based on UE and satellite
|
||||
location, which can be applied jointly (or not) with another trigger as the
|
||||
measurement-based trigger. For instance, for a deterministic satellite
|
||||
movement, it is possible to predict the configure triggering condition, and
|
||||
the initial association of the UE can be performed based on the distance with
|
||||
the nearest satellite, because we can know the location of the UE and NTN
|
||||
satellite to compute the distance.
|
||||
|
||||
- **Elevation angles of source and target cells based triggering**: This method
|
||||
is similar to the previous one, but it is based on the largest elevation
|
||||
angle.
|
||||
|
||||
- **Time/timer-based triggering**: This method uses triggering conditions based
|
||||
on UTC time or a timer-based solution, which can also be applied jointly (or
|
||||
not) with another trigger as the measurement-based trigger. The timer-based
|
||||
handover trigger considers the deterministic satellite movement to predict
|
||||
the time duration for which the satellite’s footprint covers a certain zone.
|
||||
|
||||
- **Timing advance value-based triggering**: This method uses the timing
|
||||
advance value (independently or jointly with another trigger) to trigger a
|
||||
handover to the target cell. It is appropriate to overcome the Random-Access
|
||||
preamble reception issue, where the UE needs to pre-compensate the instant
|
||||
which sends the preamble. However, UEs with GNSS support are required to
|
||||
perform this method.
|
||||
|
||||
## Simple location/time-based trigger
|
||||
|
||||
A location-based handover trigger, somewhat aligned with 3GPP Rel.17, taking
|
||||
advantage of deterministic satellite movement, can be implemented whereby it is
|
||||
assumed that the locations of the UE and the NTN satellite are known. From a
|
||||
practical point of view, this means that we know how long it takes to perform
|
||||
the handover, and therefore we only need to implement a timer.
|
||||
|
||||
It is possible to modify the source code to trigger a time-based handover, or
|
||||
combine with other methods. If all what is required is a trigger every 15
|
||||
seconds, you can also resort to the telnet-based handover trigger above, and
|
||||
run in a terminal:
|
||||
|
||||
```bash
|
||||
while true; do
|
||||
echo ci trigger_f1_ho | nc -N 127.0.0.1 9090 && echo
|
||||
sleep 15
|
||||
done
|
||||
```
|
||||
Reference in New Issue
Block a user