Commit a724dfba authored by Robert Schmidt's avatar Robert Schmidt

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

parents 28e13fc6 60447a24
......@@ -37,6 +37,10 @@
370001
370000
370002
360001
100002
360002
350000
310011
310002
330201
......@@ -114,9 +118,9 @@
<testCase id="350000">
<class>Ping</class>
<desc>Ping: 20pings in 20sec</desc>
<desc>Ping: 50pings in 10sec</desc>
<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_rttavg_threshold>25</ping_rttavg_threshold>
</testCase>
......@@ -152,6 +156,27 @@
<iperf_profile>single-ue</iperf_profile>
</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">
<class>Undeploy_Object</class>
<desc>Undeploy CU-DU</desc>
......
......@@ -6,7 +6,7 @@ services:
privileged: true
container_name: sa-cucp-gnb
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:
- ../../conf_files/gnb-cucp.sa.f1.quectel.conf:/opt/oai-gnb/etc/gnb.conf
networks:
......@@ -43,7 +43,13 @@ services:
container_name: sa-du-b200-gnb
environment:
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:
- ../../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf
- /dev:/dev
......
......@@ -56,5 +56,4 @@ typedef enum { CPtype = 0, UPtype } E1_t;
#define GTPV1_U_PORT_NUMBER (2152)
typedef enum { non_dynamic, dynamic } fiveQI_type_t;
#define maxSRBs 4
#endif
......@@ -75,11 +75,11 @@ sequenceDiagram
Note over u: E1AP_CUUP_task (SCTP Handler)
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
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
......
<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
```
......@@ -57,7 +57,7 @@ Legacy unmaintained files:
# Designs
- 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 how NR nFAPI works](./NR_NFAPI_archi.md)
- [Flow graph of the L1 in gNB](SW-archi-graph.md)
......
......@@ -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 */
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 */
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 */
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 */
......
......@@ -47,7 +47,7 @@
#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_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_RELEASE_CMD(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_release_cmd
#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;
} up_params_t;
typedef struct drb_to_setup_s {
long drbId;
/* IE SDAP Configuration (clause 9.3.1.39 of 3GPP TS 38.463) */
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_DL;
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 qosPriorityLevel;
long pre_emptionCapability;
......@@ -161,26 +176,38 @@ typedef struct qos_flow_setup_e {
qos_flow_level_qos_parameters_t qos_params;
} qos_flow_to_setup_t;
/* DRB To Setup List according to 3GPP TS 38.463 */
typedef struct DRB_nGRAN_to_setup_s {
/* DRB ID (clause 9.3.1.16) */
long id;
long defaultDRB;
long sDAP_Header_UL;
long sDAP_Header_DL;
long pDCP_SN_Size_UL;
long pDCP_SN_Size_DL;
long discardTimer;
long reorderingTimer;
long rLC_Mode;
/* SDAP Configuration (clause 9.3.1.39) */
bearer_context_sdap_config_t sdap_config;
/* PDCP Configuration (clause 9.3.1.38) */
bearer_context_pdcp_config_t pdcp_config;
/* DRB Data Forwarding Information (clause 9.3.2.6) */
/* Transport Layer Address (clause 9.3.2.4) */
in_addr_t tlAddress;
/* GTP-TEID (clause 9.3.2.3) */
int teId;
/* DL UP Transport Layer Information (clause 9.3.2.1) */
int numDlUpParam;
up_params_t DlUpParamList[E1AP_MAX_NUM_UP_PARAM];
/* Cell Group Information (clause 9.3.1.11) */
int numCellGroups;
cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS];
/* DRB QoS Flows Parameters (clause 9.3.1.26) */
int numQosFlow2Setup;
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 {
long sessionId;
long sessionType;
......@@ -196,9 +223,14 @@ typedef struct pdu_session_to_setup_s {
long numDRB2Setup;
DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB];
long numDRB2Modify;
DRB_nGRAN_to_setup_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB];
} pdu_session_to_setup_t;
DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB];
} 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 {
uint32_t gNB_cu_cp_ue_id;
uint32_t gNB_cu_up_ue_id;
......@@ -212,8 +244,8 @@ typedef struct e1ap_bearer_setup_req_s {
int numPDUSessions;
pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS];
int numPDUSessionsMod;
pdu_session_to_setup_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS];
} e1ap_bearer_setup_req_t;
pdu_session_to_mod_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS];
} e1ap_bearer_setup_req_t, e1ap_bearer_mod_req_t;
typedef struct e1ap_bearer_release_cmd_s {
uint32_t gNB_cu_cp_ue_id;
......
......@@ -276,12 +276,14 @@ typedef struct pdusession_s {
/* The transport layer address for the IP packets */
pdu_session_type_t pdu_session_type;
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;
/* Stores the DRB ID of the DRBs used by this PDU Session */
uint8_t used_drbs[MAX_DRBS_PER_UE];
/* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t gNB_teid_N3;
transport_layer_addr_t gNB_addr_N3;
/* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t UPF_teid_N3;
transport_layer_addr_t UPF_addr_N3;
nssai_t nssai;
......@@ -306,7 +308,7 @@ typedef struct pdusession_setup_s {
uint8_t pdu_session_type;
transport_layer_addr_t gNB_addr;
/* UPF Tunnel endpoint identifier */
/* Incoming NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t gtp_teid;
/* qos flow list number */
......
......@@ -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
*/
static void fill_SETUP_REQUEST(e1ap_setup_req_t *setup, E1AP_E1AP_PDU_t *pdu)
{
/* 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++) {
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->sDAP_Configuration.defaultDRB = j->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_DL = j->sDAP_Header_DL;
ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_UL = j->pDCP_SN_Size_UL;
ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_DL = j->pDCP_SN_Size_DL;
asn1cCallocOne(ieC6_1_1->pDCP_Configuration.discardTimer, j->discardTimer);
/* SDAP config */
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_config.sDAP_Header_UL;
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_config.pDCP_SN_Size_UL;
ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_DL = j->pdcp_config.pDCP_SN_Size_DL;
asn1cCallocOne(ieC6_1_1->pDCP_Configuration.discardTimer, j->pdcp_config.discardTimer);
E1AP_T_ReorderingTimer_t *roTimer = calloc(1, sizeof(E1AP_T_ReorderingTimer_t));
ieC6_1_1->pDCP_Configuration.t_ReorderingTimer = roTimer;
roTimer->t_Reordering = j->reorderingTimer;
ieC6_1_1->pDCP_Configuration.rLC_Mode = j->rLC_Mode;
roTimer->t_Reordering = j->pdcp_config.reorderingTimer;
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++) {
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;
}
/* QoS Flows */
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);
ieC6_1_1_1->qoS_Flow_Identifier = k->qfi;
/* QoS Characteristics */
qos_characteristics_t *qos_char_in = &k->qos_params.qos_characteristics;
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;
......@@ -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_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;
ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = rent_priority_in->priority_level;
ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability =
......@@ -871,7 +870,7 @@ int e1apCUUP_send_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance)
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;
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];
drb->id = drb2Setup->dRB_ID;
drb->defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB == E1AP_DefaultDRB_true;
drb->sDAP_Header_UL = drb2Setup->sDAP_Configuration.sDAP_Header_UL;
drb->sDAP_Header_DL = drb2Setup->sDAP_Configuration.sDAP_Header_DL;
drb->pDCP_SN_Size_UL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_UL;
drb->pDCP_SN_Size_DL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_DL;
/* SDAP */
drb->sdap_config.defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB == E1AP_DefaultDRB_true;
drb->sdap_config.sDAP_Header_UL = drb2Setup->sDAP_Configuration.sDAP_Header_UL;
drb->sdap_config.sDAP_Header_DL = drb2Setup->sDAP_Configuration.sDAP_Header_DL;
/* PDCP */
drb->pdcp_config.pDCP_SN_Size_UL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_UL;
drb->pdcp_config.pDCP_SN_Size_DL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_DL;
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) {
drb->reorderingTimer = drb2Setup->pDCP_Configuration.t_ReorderingTimer->t_Reordering;
drb->pdcp_config.reorderingTimer = drb2Setup->pDCP_Configuration.t_ReorderingTimer->t_Reordering;
}
drb->rLC_Mode = drb2Setup->pDCP_Configuration.rLC_Mode;
drb->pdcp_config.rLC_Mode = drb2Setup->pDCP_Configuration.rLC_Mode;
E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information;
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_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics;
if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present ==
E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
qos_char->qos_type = non_dynamic;
qos_char->non_dynamic.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:
DevAssert(ie->criticality == E1AP_Criticality_reject);
DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse);
DevAssert(ie->value.choice.System_BearerContextSetupResponse.present ==
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;
DevAssert(ie->value.choice.System_BearerContextSetupResponse.present
== 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;
DevAssert(msgNGRAN_list->list.count == 1);
E1AP_NG_RAN_BearerContextSetupResponse_t *msgNGRAN = msgNGRAN_list->list.array[0];
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) {
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(
&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress,
pduSetup->tlAddress);
OCTET_STRING_TO_INT32(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID,
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;
......@@ -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);
E1AP_GTPTunnel_t *gTPTunnel = in_UL_UP_param->uP_TNL_Information.choice.gTPTunnel;
if (gTPTunnel) {
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress,
UL_UP_param->tlAddress);
OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID,
UL_UP_param->teId);
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, UL_UP_param->tlAddress);
OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, UL_UP_param->teId);
} else {
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->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;
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);
ieC3_1->pDU_Session_ID = i->sessionId;
for (DRB_nGRAN_to_setup_t *j = i->DRBnGRanModList; j < i->DRBnGRanModList + i->numDRB2Modify; j++) {
for (DRB_nGRAN_to_mod_t *j = i->DRBnGRanModList; j < i->DRBnGRanModList + i->numDRB2Modify; j++) {
asn1cCalloc(ieC3_1->dRB_To_Modify_List_NG_RAN, drb2Mod_List);
asn1cSequenceAdd(drb2Mod_List->list, E1AP_DRB_To_Modify_Item_NG_RAN_t, drb2Mod);
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) {
asn1cCalloc(drb2Mod->dL_UP_Parameters, DL_UP_Param_List);
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;
}
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};
fill_BEARER_CONTEXT_MODIFICATION_REQUEST(bearerCxt, &pdu);
......@@ -1314,7 +1311,10 @@ int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance)
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;
E1AP_BearerContextModificationRequestIEs_t *ie;
......@@ -1349,23 +1349,26 @@ void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1a
DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List);
DevAssert(msgNGRAN->value.present =
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;
bearerCxt->numPDUSessionsMod = pdu2ModList->list.count;
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];
pdu_session->sessionId = pdu2Mod->pDU_Session_ID;
E1AP_DRB_To_Modify_List_NG_RAN_t *drb2ModList = pdu2Mod->dRB_To_Modify_List_NG_RAN;
pdu_session->numDRB2Modify = drb2ModList->list.count;
/* DRBs to modify */
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];
drb->id = drb2Mod->dRB_ID;
if (drb2Mod->pDCP_Configuration != NULL
&& drb2Mod->pDCP_Configuration->pDCP_Reestablishment != NULL
&& *drb2Mod->pDCP_Configuration->pDCP_Reestablishment == E1AP_PDCP_Reestablishment_true) {
drb->pdcp_config.pDCP_Reestablishment = true;
}
if (drb2Mod->dL_UP_Parameters) { /* Optional IE in the DRB To Modify Item */
E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters;
drb->numDlUpParam = dl_up_paramList->list.count;
for (int k = 0; k < dl_up_paramList->list.count; k++) {
......@@ -1373,7 +1376,8 @@ void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1a
E1AP_UP_Parameters_Item_t *dl_up_param_in = dl_up_paramList->list.array[k];
if (dl_up_param_in->uP_TNL_Information.choice.gTPTunnel) { // Optional IE
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,
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 {
......@@ -1383,6 +1387,7 @@ void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1a
}
}
}
}
break;
default:
......@@ -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,
e1ap_upcp_inst_t *e1_inst,
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->criticality == E1AP_Criticality_reject);
DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest);
e1ap_bearer_setup_req_t bearerCxt = {0};
e1ap_bearer_mod_req_t bearerCxt = {0};
extract_BEARER_CONTEXT_MODIFICATION_REQUEST(pdu, &bearerCxt);
e1_bearer_context_modif(&bearerCxt);
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)
{
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) {
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:
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
== E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse);
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];
DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List);
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;
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->criticality == E1AP_Criticality_reject);
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);
e1ap_bearer_modif_resp_t *modif = &E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg);
extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(pdu, modif);
......@@ -1960,7 +1969,7 @@ void *E1AP_CUCP_task(void *arg)
break;
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;
case E1AP_BEARER_CONTEXT_RELEASE_CMD:
......
......@@ -37,7 +37,7 @@
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;
asn1cSequenceAdd(DRB_configList->list, struct NR_DRB_ToAddMod, ie);
ie->drb_Identity = drb->id;
......@@ -47,12 +47,12 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const
// sdap_Config
asn1cCalloc(ie->cnAssociation->choice.sdap_Config, sdap_config);
sdap_config->pdu_Session = pdu->sessionId;
sdap_config->sdap_HeaderDL = drb->sDAP_Header_DL;
sdap_config->sdap_HeaderUL = drb->sDAP_Header_UL;
sdap_config->defaultDRB = drb->defaultDRB;
/* SDAP */
sdap_config->sdap_HeaderDL = drb->sdap_config.sDAP_Header_DL;
sdap_config->sdap_HeaderUL = drb->sdap_config.sDAP_Header_UL;
sdap_config->defaultDRB = drb->sdap_config.defaultDRB;
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);
*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;
asn1cCalloc(ie->pdcp_Config, pdcp_config);
asn1cCalloc(pdcp_config->drb, drbCfg);
asn1cCallocOne(drbCfg->discardTimer, drb->discardTimer);
asn1cCallocOne(drbCfg->pdcp_SN_SizeUL, drb->pDCP_SN_Size_UL);
asn1cCallocOne(drbCfg->pdcp_SN_SizeDL, drb->pDCP_SN_Size_DL);
asn1cCallocOne(drbCfg->discardTimer, drb->pdcp_config.discardTimer);
asn1cCallocOne(drbCfg->pdcp_SN_SizeUL, drb->pdcp_config.pDCP_SN_Size_UL);
asn1cCallocOne(drbCfg->pdcp_SN_SizeDL, drb->pdcp_config.pDCP_SN_Size_DL);
drbCfg->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
drbCfg->headerCompression.choice.notUsed = 0;
drbCfg->integrityProtection = NULL;
drbCfg->statusReportRequired = NULL;
drbCfg->outOfOrderDelivery = NULL;
pdcp_config->moreThanOneRLC = NULL;
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;
if (pdu->integrityProtectionIndication == 0 || // Required
pdu->integrityProtectionIndication == 1) { // Preferred
asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled);
}
if (pdu->confidentialityProtectionIndication == 2) { // Not Needed
asn1cCalloc(pdcp_config->ext1, ext1);
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);
}
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");
......@@ -239,7 +238,8 @@ void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req)
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);
LOG_I(E1AP,
"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);
modif.pduSessionMod[i].id = req->pduSessionMod[i].sessionId;
modif.pduSessionMod[i].numDRBModified = req->pduSessionMod[i].numDRB2Modify;
for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) {
const DRB_nGRAN_to_setup_t *to_modif = &req->pduSessionMod[i].DRBnGRanModList[j];
/* DRBs to modify */
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];
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?
continue; // nothing to do
......
......@@ -416,6 +416,10 @@ static void free_rx_list(nr_pdcp_entity_t *entity)
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)
{
/* transmitting entity procedures */
......
......@@ -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);
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);
} 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);
......
......@@ -31,7 +31,7 @@ static void cucp_cuup_bearer_context_setup_direct(sctp_assoc_t assoc_id, const e
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);
e1_bearer_context_modif(req);
......
......@@ -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);
}
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);
MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_REQ);
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));
itti_send_msg_to_task(TASK_CUCP_E1, 0, msg);
}
......
......@@ -28,7 +28,8 @@
#define NR_RRC_HEADER_SIZE_MAX 64
#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 {
char Payload[NR_RRC_BUFFER_SIZE_MAX];
......
......@@ -189,6 +189,16 @@ typedef struct pdu_session_param_s {
uint8_t cause_value;
} 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 {
int status;
int defaultDRBid;
......@@ -221,6 +231,8 @@ typedef struct drb_s {
int cipheringDisabled;
} ext1;
} pdcp_config;
// F1-U
f1u_tunnel_t f1u_tunnel_config;
} drb_t;
typedef enum {
......@@ -241,7 +253,7 @@ typedef struct gNB_RRC_UE_s {
drb_t established_drbs[MAX_DRBS_PER_UE];
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_HANDOVER_INFO *handover_info;
NR_MeasResults_t *measResults;
......
......@@ -97,6 +97,7 @@
#include "openair2/F1AP/f1ap_common.h"
#include "openair2/F1AP/f1ap_ids.h"
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
#include "openair2/E1AP/e1ap.h"
#include "cucp_cuup_if.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);
}
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)
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)
{
DevAssert(size > 0);
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
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};
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);
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);
}
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)
{
DevAssert(cell_info != NULL && sib1 != NULL && mib != NULL);
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.array[0]->offsetToCarrier == 0, "cannot handle offsetToCarrier != 0, but is %ld\n", freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier);
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.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 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;
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) {
// 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).
const NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
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;
......@@ -348,7 +376,7 @@ static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish)
return NULL;
}
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) {
asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb);
srb->srb_Identity = i;
......@@ -408,8 +436,8 @@ static void activate_srb(gNB_RRC_UE_t *UE, int srb_id)
if (srb_id == 1) {
nr_pdcp_add_srbs(true, UE->rrc_ue_id, list, 0, NULL, NULL);
} else {
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kRRCenc[NR_K_KEY_SIZE] = {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_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);
}
//-----------------------------------------------------------------------------
/* \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,
const uint8_t *masterCellGroup_from_DU,
const rnti_t old_rnti,
const nr_rrc_du_container_t *du)
//-----------------------------------------------------------------------------
{
module_id_t module_id = 0;
gNB_RRC_INST *rrc = RC.nrrrc[module_id];
int enable_ciphering = 0;
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
uint8_t buffer[RRC_BUF_SIZE] = {0};
uint8_t xid = rrc_gNB_get_next_transaction_identifier(module_id);
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);
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kUPenc[16] = {0};
/* Ciphering and Integrity according to TS 33.501 */
uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
uint8_t kUPenc[NR_K_KEY_SIZE] = {0};
/* Derive the keys from kgnb */
if (ue_p->Srb[1].Active)
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_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kRRCint);
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);
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);
uint8_t security_mode =
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) {
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);
}
}
// TODO: should send E1 UE Bearer Modification with PDCP Reestablishment flag
for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) {
if (ue_p->established_drbs[drb_id - 1].status != DRB_INACTIVE)
nr_pdcp_reestablishment(ue_p->rrc_ue_id, drb_id, false);
}
/* PDCP Reestablishment over E1 */
cuup_notify_reestablishment(rrc, ue_p);
/* F1AP DL RRC Message Transfer */
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
RETURN_IF_INVALID_ASSOC_ID(ue_data);
uint32_t old_gNB_DU_ue_id = old_rnti;
......@@ -1020,8 +1117,8 @@ 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,
protocol_ctxt_t *const ctxt_pP,
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);
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
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;
}
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;
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?)";
}
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;
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
if (req->ue_Identity.c_RNTI < 0x1 || req->ue_Identity.c_RNTI > 0xffef) {
/* c_RNTI range error should not happen */
LOG_E(NR_RRC,
"NR_RRCReestablishmentRequest c_RNTI %04lx range error, fallback to RRC setup\n",
req->ue_Identity.c_RNTI);
LOG_E(NR_RRC, "NR_RRCReestablishmentRequest c_RNTI %04lx range error, fallback to RRC setup\n", req->ue_Identity.c_RNTI);
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
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);
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);
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
== NR_RRCReestablishmentComplete__criticalExtensions_PR_rrcReestablishmentComplete);
rrc_gNB_process_RRCReestablishmentComplete(ctxt_pP,
ue_context_p,
reestablishment_complete->rrc_TransactionIdentifier);
rrc_gNB_process_RRCReestablishmentComplete(ctxt_pP, ue_context_p, reestablishment_complete->rrc_TransactionIdentifier);
UE->ue_reestablishment_counter++;
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;
}
/* \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_setup_t *find_or_next_pdu_session(e1ap_bearer_setup_req_t *bearer_modif, int pdu_id)
/**
* @brief Store F1-U DL TL and TEID in RRC
*/
static void f1u_gtp_update(f1u_tunnel_t *f1u, const f1ap_drb_to_be_setup_t *drb_f1)
{
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];
f1u->cuup_teid_f1u = drb_f1->up_dl_tnl[0].teid;
memcpy(&f1u->cuup_addr_f1u.buffer, &drb_f1->up_dl_tnl[0].tl_address, sizeof(uint8_t) * 4);
f1u->cuup_addr_f1u.length = sizeof(in_addr_t);
}
/* \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)
{
// 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_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);
pdu_e1->sessionId = pdu_ue->param.pdusession_id;
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);
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);
// 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];
rrc_pdu_session_param_t *rrc_pdu = find_pduSession(UE, e1_pdu->id, false);
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
*/
*/
void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t *resp)
{
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
*/
*/
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
......@@ -2301,6 +2395,7 @@ void *rrc_gnb_task(void *args_p) {
break;
/* Messages from PDCP */
/* From DU -> CU */
case F1AP_UL_RRC_MESSAGE:
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
instance,
......
......@@ -60,6 +60,7 @@
#include "f1ap_messages_types.h"
#include "openair2/F1AP/f1ap_ids.h"
#include "openair2/E1AP/e1ap_asnc.h"
#include "openair2/E1AP/e1ap.h"
#include "NGAP_asn_constant.h"
#include "NGAP_PDUSessionResourceSetupRequestTransfer.h"
#include "NGAP_PDUSessionResourceModifyRequestTransfer.h"
......@@ -130,9 +131,9 @@ nr_rrc_pdcp_config_security(
)
//------------------------------------------------------------------------------
{
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kUPenc[16] = {0};
uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
uint8_t kUPenc[NR_K_KEY_SIZE] = {0};
//uint8_t *k_kdf = NULL;
static int print_keys= 1;
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->id = rrc_drb->drb_id;
/* SDAP */
struct sdap_config_s *sdap_config = &rrc_drb->cnAssociation.sdap_config;
drb->defaultDRB = sdap_config->defaultDRB;
drb->sDAP_Header_UL = sdap_config->sdap_HeaderUL;
drb->sDAP_Header_DL = sdap_config->sdap_HeaderDL;
struct pdcp_config_s *pdcp_config = &rrc_drb->pdcp_config;
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->sdap_config.defaultDRB = sdap_config->defaultDRB;
drb->sdap_config.sDAP_Header_UL = sdap_config->sdap_HeaderUL;
drb->sdap_config.sDAP_Header_DL = sdap_config->sdap_HeaderDL;
/* PDCP */
set_bearer_context_pdcp_config(&drb->pdcp_config, rrc_drb, rrc->configuration.um_on_default_drb);
drb->numCellGroups = 1; // assume one cell group associated with a DRB
......
......@@ -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_resp_t create_tunnel_resp;
protocol_ctxt_t ctxt={0};
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
uint8_t kUPenc[NR_K_KEY_SIZE] = {0};
uint8_t kUPint[NR_K_KEY_SIZE] = {0};
int i;
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
......
......@@ -21,6 +21,7 @@
#include "rrc_gNB_radio_bearers.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)
{
......@@ -56,6 +57,29 @@ drb_t *get_drb(gNB_RRC_UE_t *ue, uint8_t drb_id)
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,
uint8_t drb_id,
const rrc_pdu_session_param_t *pduSession,
......@@ -95,20 +119,7 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
est_drb->status = DRB_ACTIVE;
}
/* PDCP Configuration */
est_drb->pdcp_config.discardTimer = NR_PDCP_Config__drb__discardTimer_infinity;
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;
set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering);
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 */
......
......@@ -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
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
......@@ -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;
}
uint8_t kRRCenc[16] = {0};
uint8_t kUPenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
uint8_t kUPenc[NR_K_KEY_SIZE] = {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(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kRRCenc);
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)
nr_pdcp_release_srb(ue_rrc->ue_id, 3);
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
if (ue_rrc->as_security_activated) {
if (radioBearerConfig->securityConfig != NULL) {
// When the field is not included, continue to use the currently configured keyToUse
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment