Merge remote-tracking branch 'origin/e1-reestablishment' into integration_2024_w09

This commit is contained in:
Robert Schmidt
2024-03-04 08:45:47 +01:00
23 changed files with 502 additions and 228 deletions
@@ -37,6 +37,10 @@
370001 370001
370000 370000
370002 370002
360001
100002
360002
350000
310011 310011
310002 310002
330201 330201
@@ -114,9 +118,9 @@
<testCase id="350000"> <testCase id="350000">
<class>Ping</class> <class>Ping</class>
<desc>Ping: 20pings in 20sec</desc> <desc>Ping: 50pings in 10sec</desc>
<id>idefix</id> <id>idefix</id>
<ping_args>-c 20 %cn_ip%</ping_args> <ping_args>-c 20 -i 0.2 %cn_ip%</ping_args>
<ping_packetloss_threshold>1</ping_packetloss_threshold> <ping_packetloss_threshold>1</ping_packetloss_threshold>
<ping_rttavg_threshold>25</ping_rttavg_threshold> <ping_rttavg_threshold>25</ping_rttavg_threshold>
</testCase> </testCase>
@@ -152,6 +156,27 @@
<iperf_profile>single-ue</iperf_profile> <iperf_profile>single-ue</iperf_profile>
</testCase> </testCase>
<testCase id="360001">
<class>Custom_Command</class>
<desc>Trigger Reestablishment (on DU)</desc>
<node>ofqot</node>
<command>echo ci force_reestab | nc -N 192.168.68.195 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment'</command>
<command_fail>yes</command_fail>
</testCase>
<testCase id="360002">
<class>Custom_Command</class>
<desc>Verify Reestablishment (on CU)</desc>
<node>ofqot</node>
<command>echo ci get_reestab_count | nc -N 192.168.68.194 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1'</command>
<command_fail>yes</command_fail>
</testCase>
<testCase id="100002">
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>10</idle_sleep_time_in_sec>
</testCase>
<testCase id="330201"> <testCase id="330201">
<class>Undeploy_Object</class> <class>Undeploy_Object</class>
<desc>Undeploy CU-DU</desc> <desc>Undeploy CU-DU</desc>
@@ -6,7 +6,7 @@ services:
privileged: true privileged: true
container_name: sa-cucp-gnb container_name: sa-cucp-gnb
environment: environment:
USE_ADDITIONAL_OPTIONS: --sa --log_config.global_log_options level,nocolor,time,line_num,function USE_ADDITIONAL_OPTIONS: --sa --telnetsrv --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,time,line_num,function
volumes: volumes:
- ../../conf_files/gnb-cucp.sa.f1.quectel.conf:/opt/oai-gnb/etc/gnb.conf - ../../conf_files/gnb-cucp.sa.f1.quectel.conf:/opt/oai-gnb/etc/gnb.conf
networks: networks:
@@ -43,7 +43,13 @@ services:
container_name: sa-du-b200-gnb container_name: sa-du-b200-gnb
environment: environment:
USE_B2XX: 'yes' USE_B2XX: 'yes'
USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 18 --RUs.[0].att_tx 18 USE_ADDITIONAL_OPTIONS: --sa
--RUs.[0].sdr_addrs serial=30C51D4
--continuous-tx -E
--telnetsrv --telnetsrv.shrmod ci
--gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1
--RUs.[0].att_rx 18 --RUs.[0].att_tx 18
--log_config.global_log_options level,nocolor,time,line_num,function
volumes: volumes:
- ../../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf - ../../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf
- /dev:/dev - /dev:/dev
-1
View File
@@ -56,5 +56,4 @@ typedef enum { CPtype = 0, UPtype } E1_t;
#define GTPV1_U_PORT_NUMBER (2152) #define GTPV1_U_PORT_NUMBER (2152)
typedef enum { non_dynamic, dynamic } fiveQI_type_t; typedef enum { non_dynamic, dynamic } fiveQI_type_t;
#define maxSRBs 4
#endif #endif
+2 -2
View File
@@ -75,11 +75,11 @@ sequenceDiagram
Note over u: E1AP_CUUP_task (SCTP Handler) Note over u: E1AP_CUUP_task (SCTP Handler)
Note over u: ASN1 decoder Note over u: ASN1 decoder
``` ```
More details about the E1AP procedures in OAI are available in this document: [E1 Procedures](./e1ap_procedures.md).
# 2. Running the E1 Split # 2. Running the E1 Split
The setup is assuming that all modules are running on the same machine. The user can refer to the [F1 design document](./F1-design.md) for local deployment of the DU. The setup is assuming that all modules are running on the same machine. The user can refer to the [F1 design document](./../F1-design.md) for local deployment of the DU.
## 2.1 Configuration File ## 2.1 Configuration File
+74
View File
@@ -0,0 +1,74 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="./images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">E1AP Procedures</font></b>
</td>
</tr>
</table>
[[_TOC_]]
# Introduction
The E1 interface is between the gNB-CU-CP (Central Unit - Control Plane) and gNB-CU-UP (Central Unit - User Plane) nodes. This interface is governed by the E1 Application Protocol (E1AP) outlined in the 3GPP release 16 specifications, specifically in the documents:
* 3GPP TS 38.463 - E1 Application Protocol (E1AP)
* 3GPP TS 38.460 - E1 general aspects and principles
* 3GPP TS 38.461 - E1 interface: layer 1
* 3GPP TS 38.462 - E1 interface: signaling transport
The E1AP protocol consists of the following sets of functions:
* E1 Interface Management functions
* E1 Bearer Context Management functions
* TEID allocation function
## E1 Bearer Context Management function
This function handles the establishment, modification, and release of E1 bearer contexts.
* E1 Bearer Context Establishment: initiation of E1 bearer context is by gNB-CU-CP and acceptance or rejection is determined by gNB-CU-UP based on admission control criteria (e.g., resource availability).
* E1 Bearer Context Modification: can be initiated by either gNB-CU-CP or gNB-CU-UP, with the receiving node having the authority to accept or reject the modification.
* Release of Bearer Context: can be triggered either directly by gNB-CU-CP or following a request from gNB-CU-UP.
* QoS-Flow to DRB Mapping Configuration: responsible for setting up and modifying the QoS-flow to DRB mapping configuration. gNB-CU-CP decides the flow-to-DRB mapping, generates SDAP and PDCP configurations, and provides them to gNB-CU-UP.
# OAI implementation
For the E1AP design in OAI, please refer to the [E1 Design](./E1-design.md) document.
## E1 re-establishment
The purpose of this procedure is to follow-up the re-establishment of RRC connection over the E1 interface. For all activated DRBs a Bearer Context Modification from CU-CP to CU-UP is necessary, according to clause 9.2.2.4 of 3GPP TS 38.463. If any modification to the bearer context is required, the CU-CP informs the CU-UP with the relevant IEs (e.g. in case of PDCP re-establishment, PDCP Configuration IE clause 9.3.1.38), Current implementation in OAI:
```mermaid
sequenceDiagram
participant e as UE
participant d as DU
participant c as CUCP
participant u as CUUP
Note over e,c: RRCReestablishment Procedure
e->>d: RRCReestablishmentRequest
Note over d: initial_ul_rrc_message_transfer_f1ap
d->>+c: Initial UL RRC Message Transfer (CCCH, new C-RNTI)
Note over c: rrc_gNB_process_initial_ul_rrc_message
Note over c: rrc_handle_RRCReestablishmentRequests
c-->>+d: DL RRC Message Transfer
note right of d: fallback to RRC establishment
d-->>-e: RRCSetup
e-->>d: RRCSetupComplete
Note over c: rrc_gNB_generate_RRCReestablishment
Note over c: cuup_notify_reestablishment
Note over c: e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST
c->>u: BEARER CONTEXT MODIFICATION REQUEST
Note over u: e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST
Note over u: e1_bearer_context_modif
Note over u: nr_pdcp_reestablishment
c->>-d: DL RRC Message Transfer (old gNB DU F1AP UE ID)
d->>e: RRCReestablishment
Note over d: Fetch UE Context with old gNB DU F1AP UE ID and update C-RNTI
e->>d: RRCReestablishmentComplete
u->>c: BEARER CONTEXT MODIFICATION RESPONSE
Note over c: e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE
```
+1 -1
View File
@@ -57,7 +57,7 @@ Legacy unmaintained files:
# Designs # Designs
- General software architecture notes: [SW_archi.md](./SW_archi.md) - General software architecture notes: [SW_archi.md](./SW_archi.md)
- [Information on E1](./E1-design.md) - [Information on E1](./E1AP/E1-design.md)
- [Information on F1](./F1-design.md) - [Information on F1](./F1-design.md)
- [Information on how NR nFAPI works](./NR_NFAPI_archi.md) - [Information on how NR nFAPI works](./NR_NFAPI_archi.md)
- [Flow graph of the L1 in gNB](SW-archi-graph.md) - [Flow graph of the L1 in gNB](SW-archi-graph.md)
+1 -1
View File
@@ -39,7 +39,7 @@ MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_s
/* E1AP Bearer Context Setup Response: gNB-CU-UP -> gNB-CU-CP */ /* E1AP Bearer Context Setup Response: gNB-CU-UP -> gNB-CU-CP */
MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_RESP , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_resp_t , e1ap_bearer_setup_resp) MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_RESP , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_resp_t , e1ap_bearer_setup_resp)
/* E1AP Bearer Context Modification Request: gNB-CU-CP -> gNB-CU-UP */ /* E1AP Bearer Context Modification Request: gNB-CU-CP -> gNB-CU-UP */
MESSAGE_DEF(E1AP_BEARER_CONTEXT_MODIFICATION_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_req_t , e1ap_bearer_mod_req) MESSAGE_DEF(E1AP_BEARER_CONTEXT_MODIFICATION_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_mod_req_t , e1ap_bearer_mod_req)
/* E1AP Bearer Context Modification Response: gNB-CU-UP -> gNB-CU-CP */ /* E1AP Bearer Context Modification Response: gNB-CU-UP -> gNB-CU-CP */
MESSAGE_DEF(E1AP_BEARER_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, e1ap_bearer_modif_resp_t, e1ap_bearer_modif_resp) MESSAGE_DEF(E1AP_BEARER_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, e1ap_bearer_modif_resp_t, e1ap_bearer_modif_resp)
/* E1AP Bearer Context Release Request: gNB-CU-CP -> gNB-CU-UP */ /* E1AP Bearer Context Release Request: gNB-CU-CP -> gNB-CU-UP */
+48 -16
View File
@@ -47,7 +47,7 @@
#define E1AP_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_fail #define E1AP_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_fail
#define E1AP_BEARER_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req #define E1AP_BEARER_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req
#define E1AP_BEARER_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_resp #define E1AP_BEARER_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_resp
#define E1AP_BEARER_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req #define E1AP_BEARER_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_mod_req
#define E1AP_BEARER_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_modif_resp #define E1AP_BEARER_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_modif_resp
#define E1AP_BEARER_CONTEXT_RELEASE_CMD(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_release_cmd #define E1AP_BEARER_CONTEXT_RELEASE_CMD(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_release_cmd
#define E1AP_BEARER_CONTEXT_RELEASE_CPLT(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_release_cplt #define E1AP_BEARER_CONTEXT_RELEASE_CPLT(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_release_cplt
@@ -111,11 +111,26 @@ typedef struct up_params_s {
int cell_group_id; int cell_group_id;
} up_params_t; } up_params_t;
typedef struct drb_to_setup_s { /* IE SDAP Configuration (clause 9.3.1.39 of 3GPP TS 38.463) */
long drbId; typedef struct bearer_context_sdap_config_s {
long defaultDRB;
long sDAP_Header_UL;
long sDAP_Header_DL;
} bearer_context_sdap_config_t;
/* IE PDCP Configuration (clause 9.3.1.38 of 3GPP TS 38.463) */
typedef struct bearer_context_pdcp_config_s {
long pDCP_SN_Size_UL; long pDCP_SN_Size_UL;
long pDCP_SN_Size_DL; long pDCP_SN_Size_DL;
long rLC_Mode; long rLC_Mode;
long reorderingTimer;
long discardTimer;
bool pDCP_Reestablishment;
} bearer_context_pdcp_config_t;
typedef struct drb_to_setup_s {
long drbId;
bearer_context_pdcp_config_t pdcp_config;
long qci; long qci;
long qosPriorityLevel; long qosPriorityLevel;
long pre_emptionCapability; long pre_emptionCapability;
@@ -161,26 +176,38 @@ typedef struct qos_flow_setup_e {
qos_flow_level_qos_parameters_t qos_params; qos_flow_level_qos_parameters_t qos_params;
} qos_flow_to_setup_t; } qos_flow_to_setup_t;
/* DRB To Setup List according to 3GPP TS 38.463 */
typedef struct DRB_nGRAN_to_setup_s { typedef struct DRB_nGRAN_to_setup_s {
/* DRB ID (clause 9.3.1.16) */
long id; long id;
long defaultDRB;
long sDAP_Header_UL; /* SDAP Configuration (clause 9.3.1.39) */
long sDAP_Header_DL; bearer_context_sdap_config_t sdap_config;
long pDCP_SN_Size_UL; /* PDCP Configuration (clause 9.3.1.38) */
long pDCP_SN_Size_DL; bearer_context_pdcp_config_t pdcp_config;
long discardTimer;
long reorderingTimer; /* DRB Data Forwarding Information (clause 9.3.2.6) */
long rLC_Mode; /* Transport Layer Address (clause 9.3.2.4) */
in_addr_t tlAddress; in_addr_t tlAddress;
/* GTP-TEID (clause 9.3.2.3) */
int teId; int teId;
/* DL UP Transport Layer Information (clause 9.3.2.1) */
int numDlUpParam; int numDlUpParam;
up_params_t DlUpParamList[E1AP_MAX_NUM_UP_PARAM]; up_params_t DlUpParamList[E1AP_MAX_NUM_UP_PARAM];
/* Cell Group Information (clause 9.3.1.11) */
int numCellGroups; int numCellGroups;
cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS];
/* DRB QoS Flows Parameters (clause 9.3.1.26) */
int numQosFlow2Setup; int numQosFlow2Setup;
qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS];
} DRB_nGRAN_to_setup_t; } DRB_nGRAN_to_setup_t, DRB_nGRAN_to_mod_t;
/**
* PDU Session Resource To Setup List (clause 9.3.3.10)
* PDU Session Resource To Modify List (clause 9.3.3.11)
*/
typedef struct pdu_session_to_setup_s { typedef struct pdu_session_to_setup_s {
long sessionId; long sessionId;
long sessionType; long sessionType;
@@ -196,9 +223,14 @@ typedef struct pdu_session_to_setup_s {
long numDRB2Setup; long numDRB2Setup;
DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB]; DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB];
long numDRB2Modify; long numDRB2Modify;
DRB_nGRAN_to_setup_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB]; DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB];
} pdu_session_to_setup_t; } pdu_session_to_setup_t, pdu_session_to_mod_t;
/**
* Bearer Context Setup Request message, clause 9.2.2.1 of 3GPP TS 38.463
* out of simplicity, this same struct is used for clause 9.2.2.4
* i.e. Bearer Context Modification Request message
*/
typedef struct e1ap_bearer_setup_req_s { typedef struct e1ap_bearer_setup_req_s {
uint32_t gNB_cu_cp_ue_id; uint32_t gNB_cu_cp_ue_id;
uint32_t gNB_cu_up_ue_id; uint32_t gNB_cu_up_ue_id;
@@ -212,8 +244,8 @@ typedef struct e1ap_bearer_setup_req_s {
int numPDUSessions; int numPDUSessions;
pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS];
int numPDUSessionsMod; int numPDUSessionsMod;
pdu_session_to_setup_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS]; pdu_session_to_mod_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS];
} e1ap_bearer_setup_req_t; } e1ap_bearer_setup_req_t, e1ap_bearer_mod_req_t;
typedef struct e1ap_bearer_release_cmd_s { typedef struct e1ap_bearer_release_cmd_s {
uint32_t gNB_cu_cp_ue_id; uint32_t gNB_cu_cp_ue_id;
+4 -2
View File
@@ -276,12 +276,14 @@ typedef struct pdusession_s {
/* The transport layer address for the IP packets */ /* The transport layer address for the IP packets */
pdu_session_type_t pdu_session_type; pdu_session_type_t pdu_session_type;
transport_layer_addr_t upf_addr; transport_layer_addr_t upf_addr;
/* S-GW Tunnel endpoint identifier */ /* Outgoing (UL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t gtp_teid; uint32_t gtp_teid;
/* Stores the DRB ID of the DRBs used by this PDU Session */ /* Stores the DRB ID of the DRBs used by this PDU Session */
uint8_t used_drbs[MAX_DRBS_PER_UE]; uint8_t used_drbs[MAX_DRBS_PER_UE];
/* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t gNB_teid_N3; uint32_t gNB_teid_N3;
transport_layer_addr_t gNB_addr_N3; transport_layer_addr_t gNB_addr_N3;
/* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t UPF_teid_N3; uint32_t UPF_teid_N3;
transport_layer_addr_t UPF_addr_N3; transport_layer_addr_t UPF_addr_N3;
nssai_t nssai; nssai_t nssai;
@@ -306,7 +308,7 @@ typedef struct pdusession_setup_s {
uint8_t pdu_session_type; uint8_t pdu_session_type;
transport_layer_addr_t gNB_addr; transport_layer_addr_t gNB_addr;
/* UPF Tunnel endpoint identifier */ /* Incoming NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t gtp_teid; uint32_t gtp_teid;
/* qos flow list number */ /* qos flow list number */
+86 -77
View File
@@ -163,7 +163,6 @@ int e1ap_send_ERROR_INDICATION(instance_t instance, E1AP_ErrorIndication_t *Erro
/* /*
E1 Setup: can be sent on both ways, to be refined E1 Setup: can be sent on both ways, to be refined
*/ */
static void fill_SETUP_REQUEST(e1ap_setup_req_t *setup, E1AP_E1AP_PDU_t *pdu) static void fill_SETUP_REQUEST(e1ap_setup_req_t *setup, E1AP_E1AP_PDU_t *pdu)
{ {
/* Create */ /* Create */
@@ -664,28 +663,28 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bear
for (DRB_nGRAN_to_setup_t *j = i->DRBnGRanList; j < i->DRBnGRanList + i->numDRB2Setup; j++) { for (DRB_nGRAN_to_setup_t *j = i->DRBnGRanList; j < i->DRBnGRanList + i->numDRB2Setup; j++) {
asn1cSequenceAdd(ieC6_1->dRB_To_Setup_List_NG_RAN.list, E1AP_DRB_To_Setup_Item_NG_RAN_t, ieC6_1_1); 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->dRB_ID = j->id;
/* SDAP config */
ieC6_1_1->sDAP_Configuration.defaultDRB = j->defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false; ieC6_1_1->sDAP_Configuration.defaultDRB = j->sdap_config.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_UL = j->sdap_config.sDAP_Header_UL;
ieC6_1_1->sDAP_Configuration.sDAP_Header_DL = j->sDAP_Header_DL; ieC6_1_1->sDAP_Configuration.sDAP_Header_DL = j->sdap_config.sDAP_Header_DL;
/* PDCP Config */
ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_UL = j->pDCP_SN_Size_UL; ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_UL = j->pdcp_config.pDCP_SN_Size_UL;
ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_DL = j->pDCP_SN_Size_DL; ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_DL = j->pdcp_config.pDCP_SN_Size_DL;
asn1cCallocOne(ieC6_1_1->pDCP_Configuration.discardTimer, j->discardTimer); asn1cCallocOne(ieC6_1_1->pDCP_Configuration.discardTimer, j->pdcp_config.discardTimer);
E1AP_T_ReorderingTimer_t *roTimer = calloc(1, sizeof(E1AP_T_ReorderingTimer_t)); E1AP_T_ReorderingTimer_t *roTimer = calloc(1, sizeof(E1AP_T_ReorderingTimer_t));
ieC6_1_1->pDCP_Configuration.t_ReorderingTimer = roTimer; ieC6_1_1->pDCP_Configuration.t_ReorderingTimer = roTimer;
roTimer->t_Reordering = j->reorderingTimer; roTimer->t_Reordering = j->pdcp_config.reorderingTimer;
ieC6_1_1->pDCP_Configuration.rLC_Mode = j->rLC_Mode; ieC6_1_1->pDCP_Configuration.rLC_Mode = j->pdcp_config.rLC_Mode;
/* Cell Group config */
for (cell_group_t *k = j->cellGroupList; k < j->cellGroupList + j->numCellGroups; k++) { for (cell_group_t *k = j->cellGroupList; k < j->cellGroupList + j->numCellGroups; k++) {
asn1cSequenceAdd(ieC6_1_1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ieC6_1_1_1); asn1cSequenceAdd(ieC6_1_1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ieC6_1_1_1);
ieC6_1_1_1->cell_Group_ID = k->id; ieC6_1_1_1->cell_Group_ID = k->id;
} }
/* QoS Flows */
for (qos_flow_to_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlow2Setup; k++) { for (qos_flow_to_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlow2Setup; k++) {
asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1); asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1);
ieC6_1_1_1->qoS_Flow_Identifier = k->qfi; ieC6_1_1_1->qoS_Flow_Identifier = k->qfi;
/* QoS Characteristics */
qos_characteristics_t *qos_char_in = &k->qos_params.qos_characteristics; qos_characteristics_t *qos_char_in = &k->qos_params.qos_characteristics;
if (qos_char_in->qos_type == non_dynamic) { // non Dynamic 5QI if (qos_char_in->qos_type == non_dynamic) { // non Dynamic 5QI
ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI; ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI;
@@ -699,7 +698,7 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bear
dynamic_5QI->packetErrorRate.pER_Scalar = qos_char_in->dynamic.packet_error_rate.per_scalar; dynamic_5QI->packetErrorRate.pER_Scalar = qos_char_in->dynamic.packet_error_rate.per_scalar;
dynamic_5QI->packetErrorRate.pER_Exponent = qos_char_in->dynamic.packet_error_rate.per_exponent; dynamic_5QI->packetErrorRate.pER_Exponent = qos_char_in->dynamic.packet_error_rate.per_exponent;
} }
/* QoS Retention Priority */
ngran_allocation_retention_priority_t *rent_priority_in = &k->qos_params.alloc_reten_priority; ngran_allocation_retention_priority_t *rent_priority_in = &k->qos_params.alloc_reten_priority;
ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = rent_priority_in->priority_level; ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = rent_priority_in->priority_level;
ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability =
@@ -871,7 +870,7 @@ int e1apCUUP_send_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance)
return -1; return -1;
} }
void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_setup_req_t *bearerCxt) static void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_setup_req_t *bearerCxt)
{ {
const E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest; const E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest;
E1AP_BearerContextSetupRequestIEs_t *ie; E1AP_BearerContextSetupRequestIEs_t *ie;
@@ -970,23 +969,20 @@ void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_beare
E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j]; E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j];
drb->id = drb2Setup->dRB_ID; drb->id = drb2Setup->dRB_ID;
/* SDAP */
drb->defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB == E1AP_DefaultDRB_true; drb->sdap_config.defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB == E1AP_DefaultDRB_true;
drb->sDAP_Header_UL = drb2Setup->sDAP_Configuration.sDAP_Header_UL; drb->sdap_config.sDAP_Header_UL = drb2Setup->sDAP_Configuration.sDAP_Header_UL;
drb->sDAP_Header_DL = drb2Setup->sDAP_Configuration.sDAP_Header_DL; drb->sdap_config.sDAP_Header_DL = drb2Setup->sDAP_Configuration.sDAP_Header_DL;
/* PDCP */
drb->pDCP_SN_Size_UL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_UL; drb->pdcp_config.pDCP_SN_Size_UL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_UL;
drb->pDCP_SN_Size_DL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_DL; drb->pdcp_config.pDCP_SN_Size_DL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_DL;
if (drb2Setup->pDCP_Configuration.discardTimer) { if (drb2Setup->pDCP_Configuration.discardTimer) {
drb->discardTimer = *drb2Setup->pDCP_Configuration.discardTimer; drb->pdcp_config.discardTimer = *drb2Setup->pDCP_Configuration.discardTimer;
} }
if (drb2Setup->pDCP_Configuration.t_ReorderingTimer) { if (drb2Setup->pDCP_Configuration.t_ReorderingTimer) {
drb->reorderingTimer = drb2Setup->pDCP_Configuration.t_ReorderingTimer->t_Reordering; drb->pdcp_config.reorderingTimer = drb2Setup->pDCP_Configuration.t_ReorderingTimer->t_Reordering;
} }
drb->pdcp_config.rLC_Mode = drb2Setup->pDCP_Configuration.rLC_Mode;
drb->rLC_Mode = drb2Setup->pDCP_Configuration.rLC_Mode;
E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information; E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information;
drb->numCellGroups = cellGroupList->list.count; drb->numCellGroups = cellGroupList->list.count;
@@ -1005,8 +1001,7 @@ void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_beare
qos_flow->qfi = qos2Setup->qoS_Flow_Identifier; qos_flow->qfi = qos2Setup->qoS_Flow_Identifier;
qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics;
if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
qos_char->qos_type = non_dynamic; qos_char->qos_type = non_dynamic;
qos_char->non_dynamic.fiveqi = qos_char->non_dynamic.fiveqi =
qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI; qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI;
@@ -1078,9 +1073,11 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bear
case E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse: case E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse:
DevAssert(ie->criticality == E1AP_Criticality_reject); DevAssert(ie->criticality == E1AP_Criticality_reject);
DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse); DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse);
DevAssert(ie->value.choice.System_BearerContextSetupResponse.present == DevAssert(ie->value.choice.System_BearerContextSetupResponse.present
E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse); == E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse);
E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P22_t *) ie->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse; E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list =
(E1AP_ProtocolIE_Container_4932P22_t *)
ie->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse;
DevAssert(msgNGRAN_list->list.count == 1); DevAssert(msgNGRAN_list->list.count == 1);
E1AP_NG_RAN_BearerContextSetupResponse_t *msgNGRAN = msgNGRAN_list->list.array[0]; E1AP_NG_RAN_BearerContextSetupResponse_t *msgNGRAN = msgNGRAN_list->list.array[0];
DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List); DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List);
@@ -1096,10 +1093,10 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bear
if (pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel) { if (pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel) {
DevAssert(pdu_session->nG_DL_UP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel); DevAssert(pdu_session->nG_DL_UP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel);
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress, BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(
pduSetup->tlAddress); &pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress,
OCTET_STRING_TO_INT32(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID, pduSetup->tlAddress);
pduSetup->teId); OCTET_STRING_TO_INT32(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID, pduSetup->teId);
} }
pduSetup->numDRBSetup = pdu_session->dRB_Setup_List_NG_RAN.list.count; pduSetup->numDRBSetup = pdu_session->dRB_Setup_List_NG_RAN.list.count;
@@ -1117,10 +1114,8 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bear
DevAssert(in_UL_UP_param->uP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel); DevAssert(in_UL_UP_param->uP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel);
E1AP_GTPTunnel_t *gTPTunnel = in_UL_UP_param->uP_TNL_Information.choice.gTPTunnel; E1AP_GTPTunnel_t *gTPTunnel = in_UL_UP_param->uP_TNL_Information.choice.gTPTunnel;
if (gTPTunnel) { if (gTPTunnel) {
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, UL_UP_param->tlAddress);
UL_UP_param->tlAddress); OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, UL_UP_param->teId);
OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID,
UL_UP_param->teId);
} else { } else {
AssertFatal(false, "gTPTunnel information in required\n"); AssertFatal(false, "gTPTunnel information in required\n");
} }
@@ -1210,15 +1205,17 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con
msgNGRAN->criticality = E1AP_Criticality_reject; msgNGRAN->criticality = E1AP_Criticality_reject;
msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List; msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List;
E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List; E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List;
for (pdu_session_to_setup_t *i = bearerCxt->pduSessionMod; i < bearerCxt->pduSessionMod + bearerCxt->numPDUSessionsMod; i++) { for (pdu_session_to_mod_t *i = bearerCxt->pduSessionMod; i < bearerCxt->pduSessionMod + bearerCxt->numPDUSessionsMod; i++) {
asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Modify_Item_t, ieC3_1); asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Modify_Item_t, ieC3_1);
ieC3_1->pDU_Session_ID = i->sessionId; ieC3_1->pDU_Session_ID = i->sessionId;
for (DRB_nGRAN_to_mod_t *j = i->DRBnGRanModList; j < i->DRBnGRanModList + i->numDRB2Modify; j++) {
for (DRB_nGRAN_to_setup_t *j = i->DRBnGRanModList; j < i->DRBnGRanModList + i->numDRB2Modify; j++) {
asn1cCalloc(ieC3_1->dRB_To_Modify_List_NG_RAN, drb2Mod_List); asn1cCalloc(ieC3_1->dRB_To_Modify_List_NG_RAN, drb2Mod_List);
asn1cSequenceAdd(drb2Mod_List->list, E1AP_DRB_To_Modify_Item_NG_RAN_t, drb2Mod); asn1cSequenceAdd(drb2Mod_List->list, E1AP_DRB_To_Modify_Item_NG_RAN_t, drb2Mod);
drb2Mod->dRB_ID = j->id; drb2Mod->dRB_ID = j->id;
asn1cCalloc(drb2Mod->pDCP_Configuration, pDCP_Configuration);
if (j->pdcp_config.pDCP_Reestablishment) {
asn1cCallocOne(pDCP_Configuration->pDCP_Reestablishment, E1AP_PDCP_Reestablishment_true);
}
if (j->numDlUpParam > 0) { if (j->numDlUpParam > 0) {
asn1cCalloc(drb2Mod->dL_UP_Parameters, DL_UP_Param_List); asn1cCalloc(drb2Mod->dL_UP_Parameters, DL_UP_Param_List);
for (up_params_t *k = j->DlUpParamList; k < j->DlUpParamList + j->numDlUpParam; k++) { for (up_params_t *k = j->DlUpParamList; k < j->DlUpParamList + j->numDlUpParam; k++) {
@@ -1236,7 +1233,7 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con
return 0; return 0;
} }
static void e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const bearerCxt) static void e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_bearer_mod_req_t *const bearerCxt)
{ {
E1AP_E1AP_PDU_t pdu = {0}; E1AP_E1AP_PDU_t pdu = {0};
fill_BEARER_CONTEXT_MODIFICATION_REQUEST(bearerCxt, &pdu); fill_BEARER_CONTEXT_MODIFICATION_REQUEST(bearerCxt, &pdu);
@@ -1314,7 +1311,10 @@ int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance)
return -1; return -1;
} }
void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_setup_req_t *bearerCxt) /**
* @brief Process E1AP PDU and extract Bearer Context Modification Request
*/
static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_mod_req_t *bearerCxt)
{ {
const E1AP_BearerContextModificationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest; const E1AP_BearerContextModificationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest;
E1AP_BearerContextModificationRequestIEs_t *ie; E1AP_BearerContextModificationRequestIEs_t *ie;
@@ -1348,38 +1348,43 @@ void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1a
DevAssert(msgNGRAN_list->list.count == 1); DevAssert(msgNGRAN_list->list.count == 1);
DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List); DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List);
DevAssert(msgNGRAN->value.present = DevAssert(msgNGRAN->value.present =
E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List); E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List);
/* PDU Session Resource To Modify List (see 9.3.3.11 of TS 38.463) */
E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2ModList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List; E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2ModList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List;
bearerCxt->numPDUSessionsMod = pdu2ModList->list.count; bearerCxt->numPDUSessionsMod = pdu2ModList->list.count;
for (int i = 0; i < pdu2ModList->list.count; i++) { for (int i = 0; i < pdu2ModList->list.count; i++) {
pdu_session_to_setup_t *pdu_session = bearerCxt->pduSessionMod + i; pdu_session_to_mod_t *pdu_session = bearerCxt->pduSessionMod + i;
E1AP_PDU_Session_Resource_To_Modify_Item_t *pdu2Mod = pdu2ModList->list.array[i]; E1AP_PDU_Session_Resource_To_Modify_Item_t *pdu2Mod = pdu2ModList->list.array[i];
pdu_session->sessionId = pdu2Mod->pDU_Session_ID; pdu_session->sessionId = pdu2Mod->pDU_Session_ID;
E1AP_DRB_To_Modify_List_NG_RAN_t *drb2ModList = pdu2Mod->dRB_To_Modify_List_NG_RAN; E1AP_DRB_To_Modify_List_NG_RAN_t *drb2ModList = pdu2Mod->dRB_To_Modify_List_NG_RAN;
pdu_session->numDRB2Modify = drb2ModList->list.count; pdu_session->numDRB2Modify = drb2ModList->list.count;
/* DRBs to modify */
for (int j = 0; j < drb2ModList->list.count; j++) { for (int j = 0; j < drb2ModList->list.count; j++) {
DRB_nGRAN_to_setup_t *drb = pdu_session->DRBnGRanModList + j; DRB_nGRAN_to_mod_t *drb = pdu_session->DRBnGRanModList + j;
E1AP_DRB_To_Modify_Item_NG_RAN_t *drb2Mod = drb2ModList->list.array[j]; E1AP_DRB_To_Modify_Item_NG_RAN_t *drb2Mod = drb2ModList->list.array[j];
drb->id = drb2Mod->dRB_ID; drb->id = drb2Mod->dRB_ID;
if (drb2Mod->pDCP_Configuration != NULL
E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters; && drb2Mod->pDCP_Configuration->pDCP_Reestablishment != NULL
drb->numDlUpParam = dl_up_paramList->list.count; && *drb2Mod->pDCP_Configuration->pDCP_Reestablishment == E1AP_PDCP_Reestablishment_true) {
for (int k = 0; k < dl_up_paramList->list.count; k++) { drb->pdcp_config.pDCP_Reestablishment = true;
up_params_t *dl_up_param = drb->DlUpParamList + k; }
E1AP_UP_Parameters_Item_t *dl_up_param_in = dl_up_paramList->list.array[k]; if (drb2Mod->dL_UP_Parameters) { /* Optional IE in the DRB To Modify Item */
if (dl_up_param_in->uP_TNL_Information.choice.gTPTunnel) { // Optional IE E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters;
DevAssert(dl_up_param_in->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel); drb->numDlUpParam = dl_up_paramList->list.count;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->transportLayerAddress, for (int k = 0; k < dl_up_paramList->list.count; k++) {
dl_up_param->tlAddress); up_params_t *dl_up_param = drb->DlUpParamList + k;
OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->teId); E1AP_UP_Parameters_Item_t *dl_up_param_in = dl_up_paramList->list.array[k];
} else { if (dl_up_param_in->uP_TNL_Information.choice.gTPTunnel) { // Optional IE
AssertFatal(false, "gTPTunnel IE is missing. It is mandatory at this point\n"); DevAssert(dl_up_param_in->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel);
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(
&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->transportLayerAddress,
dl_up_param->tlAddress);
OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->teId);
} else {
AssertFatal(false, "gTPTunnel IE is missing. It is mandatory at this point\n");
}
dl_up_param->cell_group_id = dl_up_param_in->cell_Group_ID;
} }
dl_up_param->cell_group_id = dl_up_param_in->cell_Group_ID;
} }
} }
} }
@@ -1392,6 +1397,10 @@ void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1a
} }
} }
/**
* @brief Extract Bearer Context Modification Request from E1AP PDU
* and prepare Bearer Context Modification Response
*/
int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id,
e1ap_upcp_inst_t *e1_inst, e1ap_upcp_inst_t *e1_inst,
const E1AP_E1AP_PDU_t *pdu) const E1AP_E1AP_PDU_t *pdu)
@@ -1401,10 +1410,8 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id,
DevAssert(pdu->choice.initiatingMessage->procedureCode == E1AP_ProcedureCode_id_bearerContextModification); DevAssert(pdu->choice.initiatingMessage->procedureCode == E1AP_ProcedureCode_id_bearerContextModification);
DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject); DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject);
DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest); DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest);
e1ap_bearer_mod_req_t bearerCxt = {0};
e1ap_bearer_setup_req_t bearerCxt = {0};
extract_BEARER_CONTEXT_MODIFICATION_REQUEST(pdu, &bearerCxt); extract_BEARER_CONTEXT_MODIFICATION_REQUEST(pdu, &bearerCxt);
e1_bearer_context_modif(&bearerCxt); e1_bearer_context_modif(&bearerCxt);
return 0; return 0;
} }
@@ -1412,7 +1419,8 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id,
static void extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_modif_resp_t *resp) static void extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_modif_resp_t *resp)
{ {
memset(resp, 0, sizeof(*resp)); memset(resp, 0, sizeof(*resp));
const E1AP_BearerContextModificationResponse_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextModificationResponse; const E1AP_BearerContextModificationResponse_t *in =
&pdu->choice.successfulOutcome->value.choice.BearerContextModificationResponse;
for (int i = 0; i < in->protocolIEs.list.count; ++i) { for (int i = 0; i < in->protocolIEs.list.count; ++i) {
E1AP_BearerContextModificationResponseIEs_t *ie = in->protocolIEs.list.array[i]; E1AP_BearerContextModificationResponseIEs_t *ie = in->protocolIEs.list.array[i];
@@ -1432,7 +1440,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(const E1AP_E1AP_PDU_t *
case E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse: case E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse:
DevAssert(ie->criticality == E1AP_Criticality_ignore); DevAssert(ie->criticality == E1AP_Criticality_ignore);
DevAssert(ie->value.present == E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse); DevAssert(ie->value.present
== E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse);
DevAssert(ie->value.choice.System_BearerContextModificationResponse.present DevAssert(ie->value.choice.System_BearerContextModificationResponse.present
== E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse); == E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse);
E1AP_ProtocolIE_Container_4932P29_t *msgNGRAN_list = E1AP_ProtocolIE_Container_4932P29_t *msgNGRAN_list =
@@ -1442,7 +1451,8 @@ static void extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(const E1AP_E1AP_PDU_t *
E1AP_NG_RAN_BearerContextModificationResponse_t *msgNGRAN = msgNGRAN_list->list.array[0]; E1AP_NG_RAN_BearerContextModificationResponse_t *msgNGRAN = msgNGRAN_list->list.array[0];
DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List); DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List);
DevAssert(msgNGRAN->criticality == E1AP_Criticality_reject); DevAssert(msgNGRAN->criticality == E1AP_Criticality_reject);
DevAssert(msgNGRAN->value.present == E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List); DevAssert(msgNGRAN->value.present
== E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List);
E1AP_PDU_Session_Resource_Modified_List_t *pduModifiedList = &msgNGRAN->value.choice.PDU_Session_Resource_Modified_List; E1AP_PDU_Session_Resource_Modified_List_t *pduModifiedList = &msgNGRAN->value.choice.PDU_Session_Resource_Modified_List;
resp->numPDUSessionsMod = pduModifiedList->list.count; resp->numPDUSessionsMod = pduModifiedList->list.count;
@@ -1485,7 +1495,6 @@ int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id,
DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_bearerContextModification); DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_bearerContextModification);
DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject); DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject);
DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse); DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse);
MessageDef *msg = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_RESP); MessageDef *msg = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_RESP);
e1ap_bearer_modif_resp_t *modif = &E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg); e1ap_bearer_modif_resp_t *modif = &E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg);
extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(pdu, modif); extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(pdu, modif);
@@ -1960,7 +1969,7 @@ void *E1AP_CUCP_task(void *arg)
break; break;
case E1AP_BEARER_CONTEXT_MODIFICATION_REQ: case E1AP_BEARER_CONTEXT_MODIFICATION_REQ:
e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg)); e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg));
break; break;
case E1AP_BEARER_CONTEXT_RELEASE_CMD: case E1AP_BEARER_CONTEXT_RELEASE_CMD:
+24 -19
View File
@@ -37,7 +37,7 @@
static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const pdu_session_to_setup_t *pdu) static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const pdu_session_to_setup_t *pdu)
{ {
for (int i=0; i < pdu->numDRB2Setup; i++) { for (int i = 0; i < pdu->numDRB2Setup; i++) {
const DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i; const DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i;
asn1cSequenceAdd(DRB_configList->list, struct NR_DRB_ToAddMod, ie); asn1cSequenceAdd(DRB_configList->list, struct NR_DRB_ToAddMod, ie);
ie->drb_Identity = drb->id; ie->drb_Identity = drb->id;
@@ -47,12 +47,12 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const
// sdap_Config // sdap_Config
asn1cCalloc(ie->cnAssociation->choice.sdap_Config, sdap_config); asn1cCalloc(ie->cnAssociation->choice.sdap_Config, sdap_config);
sdap_config->pdu_Session = pdu->sessionId; sdap_config->pdu_Session = pdu->sessionId;
sdap_config->sdap_HeaderDL = drb->sDAP_Header_DL; /* SDAP */
sdap_config->sdap_HeaderUL = drb->sDAP_Header_UL; sdap_config->sdap_HeaderDL = drb->sdap_config.sDAP_Header_DL;
sdap_config->defaultDRB = drb->defaultDRB; sdap_config->sdap_HeaderUL = drb->sdap_config.sDAP_Header_UL;
sdap_config->defaultDRB = drb->sdap_config.defaultDRB;
asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd); asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd);
for (int j=0; j < drb->numQosFlow2Setup; j++) { for (int j = 0; j < drb->numQosFlow2Setup; j++) {
asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, qfi); asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, qfi);
*qfi = drb->qosFlows[j].qfi; *qfi = drb->qosFlows[j].qfi;
} }
@@ -63,26 +63,22 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const
ie->recoverPDCP = NULL; ie->recoverPDCP = NULL;
asn1cCalloc(ie->pdcp_Config, pdcp_config); asn1cCalloc(ie->pdcp_Config, pdcp_config);
asn1cCalloc(pdcp_config->drb, drbCfg); asn1cCalloc(pdcp_config->drb, drbCfg);
asn1cCallocOne(drbCfg->discardTimer, drb->discardTimer); asn1cCallocOne(drbCfg->discardTimer, drb->pdcp_config.discardTimer);
asn1cCallocOne(drbCfg->pdcp_SN_SizeUL, drb->pDCP_SN_Size_UL); asn1cCallocOne(drbCfg->pdcp_SN_SizeUL, drb->pdcp_config.pDCP_SN_Size_UL);
asn1cCallocOne(drbCfg->pdcp_SN_SizeDL, drb->pDCP_SN_Size_DL); asn1cCallocOne(drbCfg->pdcp_SN_SizeDL, drb->pdcp_config.pDCP_SN_Size_DL);
drbCfg->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; drbCfg->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
drbCfg->headerCompression.choice.notUsed = 0; drbCfg->headerCompression.choice.notUsed = 0;
drbCfg->integrityProtection = NULL; drbCfg->integrityProtection = NULL;
drbCfg->statusReportRequired = NULL; drbCfg->statusReportRequired = NULL;
drbCfg->outOfOrderDelivery = NULL; drbCfg->outOfOrderDelivery = NULL;
pdcp_config->moreThanOneRLC = NULL; pdcp_config->moreThanOneRLC = NULL;
pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering)); pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering));
*pdcp_config->t_Reordering = drb->reorderingTimer; *pdcp_config->t_Reordering = drb->pdcp_config.reorderingTimer;
pdcp_config->ext1 = NULL; pdcp_config->ext1 = NULL;
if (pdu->integrityProtectionIndication == 0 || // Required if (pdu->integrityProtectionIndication == 0 || // Required
pdu->integrityProtectionIndication == 1) { // Preferred pdu->integrityProtectionIndication == 1) { // Preferred
asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled);
} }
if (pdu->confidentialityProtectionIndication == 2) { // Not Needed if (pdu->confidentialityProtectionIndication == 2) { // Not Needed
asn1cCalloc(pdcp_config->ext1, ext1); asn1cCalloc(pdcp_config->ext1, ext1);
asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true);
@@ -227,7 +223,10 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
get_e1_if()->bearer_setup_response(&resp); get_e1_if()->bearer_setup_response(&resp);
} }
void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) /**
* @brief Fill Bearer Context Modification Response and send to callback
*/
void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req)
{ {
AssertFatal(req->numPDUSessionsMod > 0, "need at least one PDU session to modify\n"); AssertFatal(req->numPDUSessionsMod > 0, "need at least one PDU session to modify\n");
@@ -239,7 +238,8 @@ void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req)
instance_t f1inst = get_f1_gtp_instance(); instance_t f1inst = get_f1_gtp_instance();
for (int i=0; i < req->numPDUSessionsMod; i++) { /* PDU Session Resource To Modify List (see 9.3.3.11 of TS 38.463) */
for (int i = 0; i < req->numPDUSessionsMod; i++) {
DevAssert(req->pduSessionMod[i].sessionId > 0); DevAssert(req->pduSessionMod[i].sessionId > 0);
LOG_I(E1AP, LOG_I(E1AP,
"UE %d: updating PDU session ID %ld (%ld bearers)\n", "UE %d: updating PDU session ID %ld (%ld bearers)\n",
@@ -248,11 +248,16 @@ void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req)
req->pduSessionMod[i].numDRB2Modify); req->pduSessionMod[i].numDRB2Modify);
modif.pduSessionMod[i].id = req->pduSessionMod[i].sessionId; modif.pduSessionMod[i].id = req->pduSessionMod[i].sessionId;
modif.pduSessionMod[i].numDRBModified = req->pduSessionMod[i].numDRB2Modify; modif.pduSessionMod[i].numDRBModified = req->pduSessionMod[i].numDRB2Modify;
for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) { /* DRBs to modify */
const DRB_nGRAN_to_setup_t *to_modif = &req->pduSessionMod[i].DRBnGRanModList[j]; for (int j = 0; j < req->pduSessionMod[i].numDRB2Modify; j++) {
const DRB_nGRAN_to_mod_t *to_modif = &req->pduSessionMod[i].DRBnGRanModList[j];
DRB_nGRAN_modified_t *modified = &modif.pduSessionMod[i].DRBnGRanModList[j]; DRB_nGRAN_modified_t *modified = &modif.pduSessionMod[i].DRBnGRanModList[j];
modified->id = to_modif->id; modified->id = to_modif->id;
if (to_modif->pdcp_config.pDCP_Reestablishment) {
nr_pdcp_reestablishment(req->gNB_cu_up_ue_id, to_modif->id, false);
}
if (f1inst < 0) // no F1-U? if (f1inst < 0) // no F1-U?
continue; // nothing to do continue; // nothing to do
+4
View File
@@ -416,6 +416,10 @@ static void free_rx_list(nr_pdcp_entity_t *entity)
entity->rx_size = 0; entity->rx_size = 0;
} }
/**
* @brief PDCP entity re-establishment according to 5.1.2 of 3GPP TS 38.323
* @todo deal with ciphering/integrity algos and keys for transmitting/receiving entity procedures
*/
static void nr_pdcp_entity_reestablish_drb_am(nr_pdcp_entity_t *entity) static void nr_pdcp_entity_reestablish_drb_am(nr_pdcp_entity_t *entity)
{ {
/* transmitting entity procedures */ /* transmitting entity procedures */
+2 -1
View File
@@ -1210,9 +1210,10 @@ void nr_pdcp_reestablishment(ue_id_t ue_id, int rb_id, bool srb_flag)
rb = nr_pdcp_get_rb(ue, rb_id, srb_flag); rb = nr_pdcp_get_rb(ue, rb_id, srb_flag);
if (rb != NULL) { if (rb != NULL) {
LOG_D(PDCP, "UE %4.4lx re-establishment of %sRB %d\n", ue_id, srb_flag ? "S" : "D", rb_id);
rb->reestablish_entity(rb); rb->reestablish_entity(rb);
} else { } else {
LOG_W(PDCP, "UE %4.4lx cannot re-establish RB %d (is_srb %d), RB not found\n", ue_id, rb_id, srb_flag); LOG_W(PDCP, "UE %4.4lx cannot re-establish %sRB %d, RB not found\n", ue_id, srb_flag ? "S" : "D", rb_id);
} }
nr_pdcp_manager_unlock(nr_pdcp_ue_manager); nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
+1 -1
View File
@@ -31,7 +31,7 @@ static void cucp_cuup_bearer_context_setup_direct(sctp_assoc_t assoc_id, const e
e1_bearer_context_setup(req); e1_bearer_context_setup(req);
} }
static void cucp_cuup_bearer_context_modif_direct(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req) static void cucp_cuup_bearer_context_modif_direct(sctp_assoc_t assoc_id, const e1ap_bearer_mod_req_t *req)
{ {
AssertFatal(assoc_id == -1, "illegal assoc_id %d, impossible for integrated CU\n", assoc_id); AssertFatal(assoc_id == -1, "illegal assoc_id %d, impossible for integrated CU\n", assoc_id);
e1_bearer_context_modif(req); e1_bearer_context_modif(req);
+2 -2
View File
@@ -37,12 +37,12 @@ static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, const e1a
itti_send_msg_to_task (TASK_CUCP_E1, 0, msg_p); itti_send_msg_to_task (TASK_CUCP_E1, 0, msg_p);
} }
static void cucp_cuup_bearer_context_mod_e1ap(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req) static void cucp_cuup_bearer_context_mod_e1ap(sctp_assoc_t assoc_id, const e1ap_bearer_mod_req_t *req)
{ {
AssertFatal(assoc_id > 0, "illegal assoc_id %d\n", assoc_id); AssertFatal(assoc_id > 0, "illegal assoc_id %d\n", assoc_id);
MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_REQ); MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_REQ);
msg->ittiMsgHeader.originInstance = assoc_id; msg->ittiMsgHeader.originInstance = assoc_id;
e1ap_bearer_setup_req_t *req_msg = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg); e1ap_bearer_mod_req_t *req_msg = &E1AP_BEARER_CONTEXT_MODIFICATION_REQ(msg);
memcpy(req_msg, req, sizeof(*req)); memcpy(req_msg, req, sizeof(*req));
itti_send_msg_to_task(TASK_CUCP_E1, 0, msg); itti_send_msg_to_task(TASK_CUCP_E1, 0, msg);
} }
+2 -1
View File
@@ -28,7 +28,8 @@
#define NR_RRC_HEADER_SIZE_MAX 64 #define NR_RRC_HEADER_SIZE_MAX 64
#define NR_RRC_BUFFER_SIZE_MAX 1024 #define NR_RRC_BUFFER_SIZE_MAX 1024
#define NR_NUM_SRB 4 #define NR_NUM_SRB 4 /* Number of Signalling Radio Bearers according to clause 4.2.2 of 3GPP TS 38.331 */
#define NR_K_KEY_SIZE 16 /* K keys have 128 bits length */
typedef struct { typedef struct {
char Payload[NR_RRC_BUFFER_SIZE_MAX]; char Payload[NR_RRC_BUFFER_SIZE_MAX];
+13 -1
View File
@@ -189,6 +189,16 @@ typedef struct pdu_session_param_s {
uint8_t cause_value; uint8_t cause_value;
} rrc_pdu_session_param_t; } rrc_pdu_session_param_t;
/**
* @brief F1-U tunnel configuration
*/
typedef struct f1u_tunnel_s {
/* Downlink F1-U Tunnel Endpoint Identifier (CU-UP/DU) */
uint32_t cuup_teid_f1u;
/* DL F1-U Transport Layer */
transport_layer_addr_t cuup_addr_f1u;
} f1u_tunnel_t;
typedef struct drb_s { typedef struct drb_s {
int status; int status;
int defaultDRBid; int defaultDRBid;
@@ -221,6 +231,8 @@ typedef struct drb_s {
int cipheringDisabled; int cipheringDisabled;
} ext1; } ext1;
} pdcp_config; } pdcp_config;
// F1-U
f1u_tunnel_t f1u_tunnel_config;
} drb_t; } drb_t;
typedef enum { typedef enum {
@@ -241,7 +253,7 @@ typedef struct gNB_RRC_UE_s {
drb_t established_drbs[MAX_DRBS_PER_UE]; drb_t established_drbs[MAX_DRBS_PER_UE];
NR_DRB_ToReleaseList_t *DRB_ReleaseList; 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 NR_SRB_INFO_TABLE_ENTRY Srb[NR_NUM_SRB];
NR_MeasConfig_t *measConfig; NR_MeasConfig_t *measConfig;
NR_HANDOVER_INFO *handover_info; NR_HANDOVER_INFO *handover_info;
NR_MeasResults_t *measResults; NR_MeasResults_t *measResults;
+158 -63
View File
@@ -97,6 +97,7 @@
#include "openair2/F1AP/f1ap_common.h" #include "openair2/F1AP/f1ap_common.h"
#include "openair2/F1AP/f1ap_ids.h" #include "openair2/F1AP/f1ap_ids.h"
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" #include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
#include "openair2/E1AP/e1ap.h"
#include "cucp_cuup_if.h" #include "cucp_cuup_if.h"
#include "BIT_STRING.h" #include "BIT_STRING.h"
@@ -154,15 +155,24 @@ static void rrc_deliver_dl_rrc_message(void *deliver_pdu_data, ue_id_t ue_id, in
data->rrc->mac_rrc.dl_rrc_message_transfer(data->assoc_id, data->dl_rrc); data->rrc->mac_rrc.dl_rrc_message_transfer(data->assoc_id, data->dl_rrc);
} }
void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc,
void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue_p, uint8_t srb_id, const uint8_t* buffer, int size) const gNB_RRC_UE_t *ue_p,
uint8_t srb_id,
const uint8_t *buffer,
int size)
{ {
DevAssert(size > 0); DevAssert(size > 0);
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
RETURN_IF_INVALID_ASSOC_ID(ue_data); RETURN_IF_INVALID_ASSOC_ID(ue_data);
f1ap_dl_rrc_message_t dl_rrc = {.gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .srb_id = srb_id}; f1ap_dl_rrc_message_t dl_rrc = {.gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .srb_id = srb_id};
deliver_dl_rrc_message_data_t data = {.rrc = rrc, .dl_rrc = &dl_rrc, .assoc_id = ue_data.du_assoc_id }; deliver_dl_rrc_message_data_t data = {.rrc = rrc, .dl_rrc = &dl_rrc, .assoc_id = ue_data.du_assoc_id};
nr_pdcp_data_req_srb(ue_p->rrc_ue_id, srb_id, rrc_gNB_mui++, size, (unsigned char *const)buffer, rrc_deliver_dl_rrc_message, &data); nr_pdcp_data_req_srb(ue_p->rrc_ue_id,
srb_id,
rrc_gNB_mui++,
size,
(unsigned char *const)buffer,
rrc_deliver_dl_rrc_message,
&data);
} }
static int get_dl_band(const f1ap_served_cell_info_t *cell_info) static int get_dl_band(const f1ap_served_cell_info_t *cell_info)
@@ -188,9 +198,13 @@ static int get_dl_bw(const f1ap_served_cell_info_t *cell_info)
static int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_t *mib, const NR_SIB1_t *sib1) static int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_t *mib, const NR_SIB1_t *sib1)
{ {
DevAssert(cell_info != NULL && sib1 != NULL && mib != NULL); DevAssert(cell_info != NULL && sib1 != NULL && mib != NULL);
const NR_FrequencyInfoDL_SIB_t* freq_info = &sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL; const NR_FrequencyInfoDL_SIB_t *freq_info = &sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL;
AssertFatal(freq_info->scs_SpecificCarrierList.list.count == 1, "cannot handle more than one carrier, but has %d\n", freq_info->scs_SpecificCarrierList.list.count); AssertFatal(freq_info->scs_SpecificCarrierList.list.count == 1,
AssertFatal(freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier == 0, "cannot handle offsetToCarrier != 0, but is %ld\n", freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier); "cannot handle more than one carrier, but has %d\n",
freq_info->scs_SpecificCarrierList.list.count);
AssertFatal(freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier == 0,
"cannot handle offsetToCarrier != 0, but is %ld\n",
freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier);
long offsetToPointA = freq_info->offsetToPointA; long offsetToPointA = freq_info->offsetToPointA;
long kssb = mib->ssb_SubcarrierOffset; long kssb = mib->ssb_SubcarrierOffset;
@@ -216,7 +230,17 @@ static int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_
int band_size_hz = get_supported_bw_mhz(band > 256 ? FR2 : FR1, bw_index) * 1000 * 1000; int band_size_hz = get_supported_bw_mhz(band > 256 ? FR2 : FR1, bw_index) * 1000 * 1000;
uint32_t ssb_arfcn = to_nrarfcn(band, freqssb, scs, band_size_hz); uint32_t ssb_arfcn = to_nrarfcn(band, freqssb, scs, band_size_hz);
LOG_D(RRC, "freqpointa %ld Hz/%d offsetToPointA %ld kssb %ld scs %d band %d band_size_hz %d freqssb %ld Hz/%d\n", freqpointa, dl_arfcn, offsetToPointA, kssb, scs, band, band_size_hz, freqssb, ssb_arfcn); LOG_D(NR_RRC,
"freqpointa %ld Hz/%d offsetToPointA %ld kssb %ld scs %d band %d band_size_hz %d freqssb %ld Hz/%d\n",
freqpointa,
dl_arfcn,
offsetToPointA,
kssb,
scs,
band,
band_size_hz,
freqssb,
ssb_arfcn);
if (RC.nrmac) { if (RC.nrmac) {
// debugging: let's test this is the correct ARFCN // debugging: let's test this is the correct ARFCN
@@ -227,7 +251,11 @@ static int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_
// taken out (but the reestablishment will likely not work). // taken out (but the reestablishment will likely not work).
const NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon; const NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
uint32_t scc_ssb_arfcn = *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB; uint32_t scc_ssb_arfcn = *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB;
AssertFatal(ssb_arfcn == scc_ssb_arfcn, "mismatch of SCC SSB ARFCN original %d vs. computed %d! Note: you can remove this Assert, the gNB might run but UE connection instable\n", scc_ssb_arfcn, ssb_arfcn); AssertFatal(ssb_arfcn == scc_ssb_arfcn,
"mismatch of SCC SSB ARFCN original %d vs. computed %d! Note: you can remove this Assert, the gNB might run but UE "
"connection instable\n",
scc_ssb_arfcn,
ssb_arfcn);
} }
return ssb_arfcn; return ssb_arfcn;
@@ -348,7 +376,7 @@ static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish)
return NULL; return NULL;
} }
NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1); NR_SRB_ToAddModList_t *list = CALLOC(sizeof(*list), 1);
for (int i = 0; i < maxSRBs; i++) for (int i = 0; i < NR_NUM_SRB; i++)
if (ue->Srb[i].Active) { if (ue->Srb[i].Active) {
asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb);
srb->srb_Identity = i; srb->srb_Identity = i;
@@ -408,8 +436,8 @@ static void activate_srb(gNB_RRC_UE_t *UE, int srb_id)
if (srb_id == 1) { if (srb_id == 1) {
nr_pdcp_add_srbs(true, UE->rrc_ue_id, list, 0, NULL, NULL); nr_pdcp_add_srbs(true, UE->rrc_ue_id, list, 0, NULL, NULL);
} else { } else {
uint8_t kRRCenc[16] = {0}; uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
uint8_t kRRCint[16] = {0}; uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc); nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint); nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint);
@@ -883,18 +911,87 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DCCH, buffer, size); nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DCCH, buffer, size);
} }
//----------------------------------------------------------------------------- /* \brief find existing PDU session inside E1AP Bearer Modif message, or
* point to new one.
* \param bearer_modif E1AP Bearer Modification Message
* \param pdu_id PDU session ID
* \return pointer to existing PDU session, or to new/unused one. */
static pdu_session_to_mod_t *find_or_next_pdu_session(e1ap_bearer_mod_req_t *bearer_modif, int pdu_id)
{
for (int i = 0; i < bearer_modif->numPDUSessionsMod; ++i) {
if (bearer_modif->pduSessionMod[i].sessionId == pdu_id)
return &bearer_modif->pduSessionMod[i];
}
/* E1AP Bearer Modification has no PDU session to modify with that ID, create
* new entry */
DevAssert(bearer_modif->numPDUSessionsMod < E1AP_MAX_NUM_PDU_SESSIONS - 1);
bearer_modif->numPDUSessionsMod += 1;
return &bearer_modif->pduSessionMod[bearer_modif->numPDUSessionsMod - 1];
}
/**
* @brief Notify E1 re-establishment to CU-UP
*/
static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p)
{
e1ap_bearer_mod_req_t req = {
.gNB_cu_cp_ue_id = ue_p->rrc_ue_id,
.gNB_cu_up_ue_id = ue_p->rrc_ue_id,
};
if (!ue_associated_to_cuup(rrc, ue_p))
return;
/* loop through active DRBs */
for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) {
if (ue_p->established_drbs[drb_id - 1].status == DRB_INACTIVE)
continue;
/* fetch an existing PDU session for this DRB */
rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue_p, drb_id);
if (pdu == NULL) {
LOG_E(RRC, "UE %d: E1 Bearer Context Modification: no PDU session for DRB ID %d\n", ue_p->rrc_ue_id, drb_id);
continue;
}
/* Get pointer to existing (or new one) PDU session to modify in E1 */
pdu_session_to_mod_t *pdu_e1 = find_or_next_pdu_session(&req, pdu->param.pdusession_id);
AssertError(pdu != NULL,
continue,
"UE %d: E1 Bearer Context Modification: PDU session %d to setup is null\n",
ue_p->rrc_ue_id,
pdu->param.pdusession_id);
/* Prepare PDU for E1 Bearear Context Modification Request */
pdu_e1->sessionId = pdu->param.pdusession_id;
/* Fill DRB to setup with ID, DL TL and DL TEID */
DRB_nGRAN_to_mod_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify];
drb_e1->id = drb_id;
drb_e1->numDlUpParam = 1;
drb_t *drbs = &ue_p->established_drbs[drb_id];
memcpy(&drb_e1->DlUpParamList[0].tlAddress, &drbs->f1u_tunnel_config.cuup_addr_f1u.buffer, sizeof(uint8_t) * 4);
drb_e1->DlUpParamList[0].teId = drbs->f1u_tunnel_config.cuup_teid_f1u;
/* PDCP configuration */
bearer_context_pdcp_config_t *pdcp_config = &drb_e1->pdcp_config;
drb_t *rrc_drb = get_drb(ue_p, drb_id);
set_bearer_context_pdcp_config(pdcp_config, rrc_drb, rrc->configuration.um_on_default_drb);
pdcp_config->pDCP_Reestablishment = true;
/* increase DRB to modify counter */
pdu_e1->numDRB2Modify += 1;
}
/* Send E1 Bearer Context Modification Request (3GPP TS 38.463) */
sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue_p);
rrc->cucp_cuup.bearer_context_mod(assoc_id, &req);
}
/**
* @brief RRCReestablishment message
* Direction: Network to UE
*/
static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context_pP, static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context_pP,
const uint8_t *masterCellGroup_from_DU, const uint8_t *masterCellGroup_from_DU,
const rnti_t old_rnti, const rnti_t old_rnti,
const nr_rrc_du_container_t *du) const nr_rrc_du_container_t *du)
//-----------------------------------------------------------------------------
{ {
module_id_t module_id = 0; module_id_t module_id = 0;
gNB_RRC_INST *rrc = RC.nrrrc[module_id]; gNB_RRC_INST *rrc = RC.nrrrc[module_id];
int enable_ciphering = 0; int enable_ciphering = 0;
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
uint8_t buffer[RRC_BUF_SIZE] = {0}; uint8_t buffer[RRC_BUF_SIZE] = {0};
uint8_t xid = rrc_gNB_get_next_transaction_identifier(module_id); uint8_t xid = rrc_gNB_get_next_transaction_identifier(module_id);
ue_p->xids[xid] = RRC_REESTABLISH; ue_p->xids[xid] = RRC_REESTABLISH;
@@ -904,34 +1001,34 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context
LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", ue_p->rnti, size); LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", ue_p->rnti, size);
uint8_t kRRCenc[16] = {0}; /* Ciphering and Integrity according to TS 33.501 */
uint8_t kRRCint[16] = {0}; uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
uint8_t kUPenc[16] = {0}; uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
uint8_t kUPenc[NR_K_KEY_SIZE] = {0};
/* Derive the keys from kgnb */ /* Derive the keys from kgnb */
if (ue_p->Srb[1].Active) if (ue_p->Srb[1].Active)
nr_derive_key(UP_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kUPenc); nr_derive_key(UP_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kUPenc);
nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kRRCenc); nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kRRCint); nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kRRCint);
LOG_I(NR_RRC,
LOG_I(NR_RRC, "Set PDCP security UE %d RNTI %04x nca %ld nia %d in RRCReestablishment\n", ue_p->rrc_ue_id, ue_p->rnti, ue_p->ciphering_algorithm, ue_p->integrity_algorithm); "Set PDCP security UE %d RNTI %04x nca %ld nia %d in RRCReestablishment\n",
ue_p->rrc_ue_id,
ue_p->rnti,
ue_p->ciphering_algorithm,
ue_p->integrity_algorithm);
uint8_t security_mode = uint8_t security_mode =
enable_ciphering ? ue_p->ciphering_algorithm | (ue_p->integrity_algorithm << 4) : 0 | (ue_p->integrity_algorithm << 4); enable_ciphering ? ue_p->ciphering_algorithm | (ue_p->integrity_algorithm << 4) : 0 | (ue_p->integrity_algorithm << 4);
for (int srb_id = 1; srb_id < maxSRBs; srb_id++) { /* SRBs */
for (int srb_id = 1; srb_id < NR_NUM_SRB; srb_id++) {
if (ue_p->Srb[srb_id].Active) { if (ue_p->Srb[srb_id].Active) {
nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc); nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc);
// TODO: should send E1 UE Bearer Modification with PDCP Reestablishment flag
nr_pdcp_reestablishment(ue_p->rrc_ue_id, srb_id, true); nr_pdcp_reestablishment(ue_p->rrc_ue_id, srb_id, true);
} }
} }
/* PDCP Reestablishment over E1 */
// TODO: should send E1 UE Bearer Modification with PDCP Reestablishment flag cuup_notify_reestablishment(rrc, ue_p);
for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) { /* F1AP DL RRC Message Transfer */
if (ue_p->established_drbs[drb_id - 1].status != DRB_INACTIVE)
nr_pdcp_reestablishment(ue_p->rrc_ue_id, drb_id, false);
}
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
RETURN_IF_INVALID_ASSOC_ID(ue_data); RETURN_IF_INVALID_ASSOC_ID(ue_data);
uint32_t old_gNB_DU_ue_id = old_rnti; uint32_t old_gNB_DU_ue_id = old_rnti;
@@ -1017,11 +1114,11 @@ static void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *co
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP, int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP,
protocol_ctxt_t *const ctxt_pP, protocol_ctxt_t *const ctxt_pP,
const int dl_bwp_id, const int dl_bwp_id,
const int ul_bwp_id) { const int ul_bwp_id)
{
uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id);
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
ue_p->xids[xid] = RRC_DEDICATED_RECONF; ue_p->xids[xid] = RRC_DEDICATED_RECONF;
@@ -1044,7 +1141,10 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP
return 0; return 0;
} }
static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id, const NR_RRCSetupRequest_IEs_t *rrcSetupRequest, const f1ap_initial_ul_rrc_message_t *msg) static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc,
sctp_assoc_t assoc_id,
const NR_RRCSetupRequest_IEs_t *rrcSetupRequest,
const f1ap_initial_ul_rrc_message_t *msg)
{ {
rrc_gNB_ue_context_t *ue_context_p = NULL; rrc_gNB_ue_context_t *ue_context_p = NULL;
if (NR_InitialUE_Identity_PR_randomValue == rrcSetupRequest->ue_Identity.present) { if (NR_InitialUE_Identity_PR_randomValue == rrcSetupRequest->ue_Identity.present) {
@@ -1121,7 +1221,10 @@ static const char *get_reestab_cause(NR_ReestablishmentCause_t c)
return "UNKNOWN Failure (ASN.1 decoder error?)"; return "UNKNOWN Failure (ASN.1 decoder error?)";
} }
static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id, const NR_RRCReestablishmentRequest_IEs_t *req, const f1ap_initial_ul_rrc_message_t *msg) static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc,
sctp_assoc_t assoc_id,
const NR_RRCReestablishmentRequest_IEs_t *req,
const f1ap_initial_ul_rrc_message_t *msg)
{ {
uint64_t random_value = 0; uint64_t random_value = 0;
const char *scause = get_reestab_cause(req->reestablishmentCause); const char *scause = get_reestab_cause(req->reestablishmentCause);
@@ -1167,9 +1270,7 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, sctp_assoc_t
// 3GPP TS 38.321 version 15.13.0 Section 7.1 Table 7.1-1: RNTI values // 3GPP TS 38.321 version 15.13.0 Section 7.1 Table 7.1-1: RNTI values
if (req->ue_Identity.c_RNTI < 0x1 || req->ue_Identity.c_RNTI > 0xffef) { if (req->ue_Identity.c_RNTI < 0x1 || req->ue_Identity.c_RNTI > 0xffef) {
/* c_RNTI range error should not happen */ /* c_RNTI range error should not happen */
LOG_E(NR_RRC, LOG_E(NR_RRC, "NR_RRCReestablishmentRequest c_RNTI %04lx range error, fallback to RRC setup\n", req->ue_Identity.c_RNTI);
"NR_RRCReestablishmentRequest c_RNTI %04lx range error, fallback to RRC setup\n",
req->ue_Identity.c_RNTI);
goto fallback_rrc_setup; goto fallback_rrc_setup;
} }
@@ -1183,8 +1284,9 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, sctp_assoc_t
// update with new RNTI, and update secondary UE association // update with new RNTI, and update secondary UE association
UE->rnti = msg->crnti; UE->rnti = msg->crnti;
f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id);
ue_data.secondary_ue = msg->gNB_DU_ue_id;
cu_remove_f1_ue_data(UE->rrc_ue_id); cu_remove_f1_ue_data(UE->rrc_ue_id);
f1_ue_data_t ue_data = {.secondary_ue = msg->gNB_DU_ue_id, .du_assoc_id = assoc_id};
cu_add_f1_ue_data(UE->rrc_ue_id, &ue_data); cu_add_f1_ue_data(UE->rrc_ue_id, &ue_data);
LOG_I(NR_RRC, "Accept Reestablishment Request UE physCellId %ld cause %s\n", physCellId, scause); LOG_I(NR_RRC, "Accept Reestablishment Request UE physCellId %ld cause %s\n", physCellId, scause);
@@ -1231,9 +1333,7 @@ static int handle_rrcReestablishmentComplete(const protocol_ctxt_t *const ctxt_p
DevAssert(reestablishment_complete->criticalExtensions.present DevAssert(reestablishment_complete->criticalExtensions.present
== NR_RRCReestablishmentComplete__criticalExtensions_PR_rrcReestablishmentComplete); == NR_RRCReestablishmentComplete__criticalExtensions_PR_rrcReestablishmentComplete);
rrc_gNB_process_RRCReestablishmentComplete(ctxt_pP, rrc_gNB_process_RRCReestablishmentComplete(ctxt_pP, ue_context_p, reestablishment_complete->rrc_TransactionIdentifier);
ue_context_p,
reestablishment_complete->rrc_TransactionIdentifier);
UE->ue_reestablishment_counter++; UE->ue_reestablishment_counter++;
return 0; return 0;
@@ -1740,22 +1840,14 @@ static void fill_e1_bearer_modif(DRB_nGRAN_to_setup_t *drb_e1, const f1ap_drb_to
drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid; drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid;
} }
/* \brief find existing PDU session inside E1AP Bearer Modif message, or /**
* point to new one. * @brief Store F1-U DL TL and TEID in RRC
* \param bearer_modif E1AP Bearer Modification Message */
* \param pdu_id PDU session ID static void f1u_gtp_update(f1u_tunnel_t *f1u, const f1ap_drb_to_be_setup_t *drb_f1)
* \return pointer to existing PDU session, or to new/unused one. */
static pdu_session_to_setup_t *find_or_next_pdu_session(e1ap_bearer_setup_req_t *bearer_modif, int pdu_id)
{ {
for (int i = 0; i < bearer_modif->numPDUSessionsMod; ++i) { f1u->cuup_teid_f1u = drb_f1->up_dl_tnl[0].teid;
if (bearer_modif->pduSessionMod[i].sessionId == pdu_id) memcpy(&f1u->cuup_addr_f1u.buffer, &drb_f1->up_dl_tnl[0].tl_address, sizeof(uint8_t) * 4);
return &bearer_modif->pduSessionMod[i]; f1u->cuup_addr_f1u.length = sizeof(in_addr_t);
}
/* E1AP Bearer Modification has no PDU session to modify with that ID, create
* new entry */
DevAssert(bearer_modif->numPDUSessionsMod < E1AP_MAX_NUM_PDU_SESSIONS - 1);
bearer_modif->numPDUSessionsMod += 1;
return &bearer_modif->pduSessionMod[bearer_modif->numPDUSessionsMod - 1];
} }
/* \brief use list of DRBs and send the corresponding bearer update message via /* \brief use list of DRBs and send the corresponding bearer update message via
@@ -1763,7 +1855,7 @@ static pdu_session_to_setup_t *find_or_next_pdu_session(e1ap_bearer_setup_req_t
static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_to_be_setup_t *drbs) static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_to_be_setup_t *drbs)
{ {
// we assume the same UE ID in CU-UP and CU-CP // we assume the same UE ID in CU-UP and CU-CP
e1ap_bearer_setup_req_t req = { e1ap_bearer_mod_req_t req = {
.gNB_cu_cp_ue_id = UE->rrc_ue_id, .gNB_cu_cp_ue_id = UE->rrc_ue_id,
.gNB_cu_up_ue_id = UE->rrc_ue_id, .gNB_cu_up_ue_id = UE->rrc_ue_id,
}; };
@@ -1779,6 +1871,8 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f
DevAssert(pdu_e1 != NULL); DevAssert(pdu_e1 != NULL);
pdu_e1->sessionId = pdu_ue->param.pdusession_id; pdu_e1->sessionId = pdu_ue->param.pdusession_id;
DRB_nGRAN_to_setup_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify]; DRB_nGRAN_to_setup_t *drb_e1 = &pdu_e1->DRBnGRanModList[pdu_e1->numDRB2Modify];
f1u_gtp_update(&UE->established_drbs[drb_f1->drb_id].f1u_tunnel_config, drb_f1);
/* Fill E1 bearer context modification */
fill_e1_bearer_modif(drb_e1, drb_f1); fill_e1_bearer_modif(drb_e1, drb_f1);
pdu_e1->numDRB2Modify += 1; pdu_e1->numDRB2Modify += 1;
} }
@@ -2006,7 +2100,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
resp->gNB_cu_up_ue_id); resp->gNB_cu_up_ue_id);
// save the tunnel address for the PDU sessions // save the tunnel address for the PDU sessions
for (int i=0; i < resp->numPDUSessions; i++) { for (int i = 0; i < resp->numPDUSessions; i++) {
pdu_session_setup_t *e1_pdu = &resp->pduSession[i]; pdu_session_setup_t *e1_pdu = &resp->pduSession[i];
rrc_pdu_session_param_t *rrc_pdu = find_pduSession(UE, e1_pdu->id, false); rrc_pdu_session_param_t *rrc_pdu = find_pduSession(UE, e1_pdu->id, false);
if (rrc_pdu == NULL) { if (rrc_pdu == NULL) {
@@ -2115,7 +2209,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
/** /**
* @brief E1AP Bearer Context Modification Response processing on CU-CP * @brief E1AP Bearer Context Modification Response processing on CU-CP
*/ */
void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t *resp) void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t *resp)
{ {
gNB_RRC_INST *rrc = RC.nrrrc[0]; gNB_RRC_INST *rrc = RC.nrrrc[0];
@@ -2134,7 +2228,7 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t
/** /**
* @brief E1AP Bearer Context Release processing * @brief E1AP Bearer Context Release processing
*/ */
void rrc_gNB_process_e1_bearer_context_release_cplt(const e1ap_bearer_release_cplt_t *cplt) void rrc_gNB_process_e1_bearer_context_release_cplt(const e1ap_bearer_release_cplt_t *cplt)
{ {
// there is not really anything to do here as of now // there is not really anything to do here as of now
@@ -2301,6 +2395,7 @@ void *rrc_gnb_task(void *args_p) {
break; break;
/* Messages from PDCP */ /* Messages from PDCP */
/* From DU -> CU */
case F1AP_UL_RRC_MESSAGE: case F1AP_UL_RRC_MESSAGE:
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
instance, instance,
+10 -15
View File
@@ -60,6 +60,7 @@
#include "f1ap_messages_types.h" #include "f1ap_messages_types.h"
#include "openair2/F1AP/f1ap_ids.h" #include "openair2/F1AP/f1ap_ids.h"
#include "openair2/E1AP/e1ap_asnc.h" #include "openair2/E1AP/e1ap_asnc.h"
#include "openair2/E1AP/e1ap.h"
#include "NGAP_asn_constant.h" #include "NGAP_asn_constant.h"
#include "NGAP_PDUSessionResourceSetupRequestTransfer.h" #include "NGAP_PDUSessionResourceSetupRequestTransfer.h"
#include "NGAP_PDUSessionResourceModifyRequestTransfer.h" #include "NGAP_PDUSessionResourceModifyRequestTransfer.h"
@@ -130,9 +131,9 @@ nr_rrc_pdcp_config_security(
) )
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
{ {
uint8_t kRRCenc[16] = {0}; uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
uint8_t kRRCint[16] = {0}; uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
uint8_t kUPenc[16] = {0}; uint8_t kUPenc[NR_K_KEY_SIZE] = {0};
//uint8_t *k_kdf = NULL; //uint8_t *k_kdf = NULL;
static int print_keys= 1; static int print_keys= 1;
gNB_RRC_UE_t *UE = &ue_context_pP->ue_context; gNB_RRC_UE_t *UE = &ue_context_pP->ue_context;
@@ -406,19 +407,13 @@ static void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdu
DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j; DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j;
drb->id = rrc_drb->drb_id; drb->id = rrc_drb->drb_id;
/* SDAP */
struct sdap_config_s *sdap_config = &rrc_drb->cnAssociation.sdap_config; struct sdap_config_s *sdap_config = &rrc_drb->cnAssociation.sdap_config;
drb->defaultDRB = sdap_config->defaultDRB; drb->sdap_config.defaultDRB = sdap_config->defaultDRB;
drb->sDAP_Header_UL = sdap_config->sdap_HeaderUL; drb->sdap_config.sDAP_Header_UL = sdap_config->sdap_HeaderUL;
drb->sDAP_Header_DL = sdap_config->sdap_HeaderDL; drb->sdap_config.sDAP_Header_DL = sdap_config->sdap_HeaderDL;
/* PDCP */
struct pdcp_config_s *pdcp_config = &rrc_drb->pdcp_config; set_bearer_context_pdcp_config(&drb->pdcp_config, rrc_drb, rrc->configuration.um_on_default_drb);
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 drb->numCellGroups = 1; // assume one cell group associated with a DRB
+2 -2
View File
@@ -126,8 +126,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a
gtpv1u_enb_create_tunnel_req_t create_tunnel_req; gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp; gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
protocol_ctxt_t ctxt={0}; protocol_ctxt_t ctxt={0};
uint8_t kUPenc[16] = {0}; uint8_t kUPenc[NR_K_KEY_SIZE] = {0};
uint8_t kUPint[16] = {0}; uint8_t kUPint[NR_K_KEY_SIZE] = {0};
int i; int i;
gNB_RRC_UE_t *UE = &ue_context_p->ue_context; gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
+25 -14
View File
@@ -21,6 +21,7 @@
#include "rrc_gNB_radio_bearers.h" #include "rrc_gNB_radio_bearers.h"
#include "oai_asn1.h" #include "oai_asn1.h"
#include "openair2/E1AP/e1ap.h"
rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create) rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create)
{ {
@@ -56,6 +57,29 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id)
return &ue->established_drbs[drb_id - 1]; return &ue->established_drbs[drb_id - 1];
} }
void set_default_drb_pdcp_config(struct pdcp_config_s *pdcp_config, int do_drb_integrity, int do_drb_ciphering)
{
AssertError(pdcp_config != NULL, return, "Failed to set default PDCP configuration for DRB!\n");
pdcp_config->discardTimer = NR_PDCP_Config__drb__discardTimer_infinity;
pdcp_config->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits;
pdcp_config->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits;
pdcp_config->t_Reordering = NR_PDCP_Config__t_Reordering_ms100;
pdcp_config->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
pdcp_config->headerCompression.NotUsed = 0;
pdcp_config->integrityProtection = do_drb_integrity ? NR_PDCP_Config__drb__integrityProtection_enabled : 1;
pdcp_config->ext1.cipheringDisabled = do_drb_ciphering ? 1 : NR_PDCP_Config__ext1__cipheringDisabled_true;
}
void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb)
{
AssertError(rrc_drb != NULL && pdcp_config != NULL, return, "Failed to set default bearer context PDCP configuration!\n");
pdcp_config->pDCP_SN_Size_UL = rrc_drb->pdcp_config.pdcp_SN_SizeUL;
pdcp_config->pDCP_SN_Size_DL = rrc_drb->pdcp_config.pdcp_SN_SizeDL;
pdcp_config->discardTimer = rrc_drb->pdcp_config.discardTimer;
pdcp_config->reorderingTimer = rrc_drb->pdcp_config.t_Reordering;
pdcp_config->rLC_Mode = um_on_default_drb ? E1AP_RLC_Mode_rlc_um_bidirectional : E1AP_RLC_Mode_rlc_am;
}
drb_t *generateDRB(gNB_RRC_UE_t *ue, drb_t *generateDRB(gNB_RRC_UE_t *ue,
uint8_t drb_id, uint8_t drb_id,
const rrc_pdu_session_param_t *pduSession, const rrc_pdu_session_param_t *pduSession,
@@ -95,20 +119,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
est_drb->status = DRB_ACTIVE; est_drb->status = DRB_ACTIVE;
} }
/* PDCP Configuration */ /* PDCP Configuration */
est_drb->pdcp_config.discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering);
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); 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 */ DevAssert(rrc_drb == est_drb); /* to double check that we create the same which we would retrieve */
+3
View File
@@ -71,4 +71,7 @@ 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 /// @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); rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id);
/// @brief set PDCP configuration in a bearer context management message
void set_bearer_context_pdcp_config(bearer_context_pdcp_config_t *pdcp_config, drb_t *rrc_drb, bool um_on_default_drb);
#endif #endif
+5 -5
View File
@@ -987,9 +987,9 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc,
c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete; c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete;
} }
uint8_t kRRCenc[16] = {0}; uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
uint8_t kUPenc[16] = {0}; uint8_t kUPenc[NR_K_KEY_SIZE] = {0};
uint8_t kRRCint[16] = {0}; uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
nr_derive_key(UP_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kUPenc); nr_derive_key(UP_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kUPenc);
nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kRRCenc); nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kRRCint); nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kRRCint);
@@ -1167,8 +1167,8 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
if (radioBearerConfig->srb3_ToRelease) if (radioBearerConfig->srb3_ToRelease)
nr_pdcp_release_srb(ue_rrc->ue_id, 3); nr_pdcp_release_srb(ue_rrc->ue_id, 3);
uint8_t kRRCenc[16] = {0}; uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
uint8_t kRRCint[16] = {0}; uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
if (ue_rrc->as_security_activated) { if (ue_rrc->as_security_activated) {
if (radioBearerConfig->securityConfig != NULL) { if (radioBearerConfig->securityConfig != NULL) {
// When the field is not included, continue to use the currently configured keyToUse // When the field is not included, continue to use the currently configured keyToUse