diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4c2baa4de3..27a7c471d5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1216,6 +1216,10 @@ set(NR_PDCP_SRC
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c
+ openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c
+ openair2/LAYER2/nr_pdcp/cuup_cucp_if.c
+ openair2/LAYER2/nr_pdcp/cuup_cucp_direct.c
+ openair2/LAYER2/nr_pdcp/cuup_cucp_e1ap.c
)
set(NR_SDAP_SRC
@@ -1277,6 +1281,7 @@ set(L2_NR_SRC
${NR_RRC_DIR}/rrc_gNB_UE_context.c
${NR_RRC_DIR}/rrc_gNB_NGAP.c
${NR_RRC_DIR}/rrc_gNB_radio_bearers.c
+ ${NR_RRC_DIR}/rrc_gNB_cuup.c
)
set(L2_SRC_UE
@@ -1445,12 +1450,6 @@ add_library(e1_if
target_link_libraries(e1_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap SECURITY ${OPENSSL_LIBRARIES} e1ap GTPV1U)
-add_library(e1_pdcp_if
- ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_e1_api.c
- )
-
-target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
-
target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap nr_rlc)
if(E2_AGENT)
target_link_libraries(L2_NR PUBLIC e2_agent e2_ran_func)
@@ -2106,7 +2105,7 @@ add_executable(nr-cuup
target_link_libraries(nr-cuup PRIVATE
CONFIG_LIB ITTI SCTP_CLIENT
- GTPV1U e1ap e1_pdcp_if f1ap SIMU_ETH
+ GTPV1U e1ap f1ap SIMU_ETH
z sctp dl pthread shlib_loader ${T_LIB})
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
diff --git a/ci-scripts/conf_files/gnb-cucp.sa.f1.conf b/ci-scripts/conf_files/gnb-cucp.sa.f1.conf
index 5eb123dba1..469ab8d187 100644
--- a/ci-scripts/conf_files/gnb-cucp.sa.f1.conf
+++ b/ci-scripts/conf_files/gnb-cucp.sa.f1.conf
@@ -8,7 +8,7 @@ gNBs =
(
{
////////// Identification parameters:
- gNB_CU_ID = 0xe00;
+ gNB_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
diff --git a/ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf b/ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf
index 9d0c13cd74..8b9e865e0d 100644
--- a/ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf
+++ b/ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf
@@ -8,7 +8,7 @@ gNBs =
(
{
////////// Identification parameters:
- gNB_CU_ID = 0xe00;
+ gNB_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
diff --git a/ci-scripts/conf_files/gnb-cuup.sa.f1.conf b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf
index 6759654e0d..357518bcf2 100644
--- a/ci-scripts/conf_files/gnb-cuup.sa.f1.conf
+++ b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf
@@ -7,7 +7,7 @@ gNBs =
(
{
////////// Identification parameters:
- gNB_CU_ID = 0xe00;
+ gNB_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
@@ -56,32 +56,9 @@ gNBs =
}
);
-security = {
- # preferred ciphering algorithms
- # the first one of the list that an UE supports in chosen
- # valid values: nea0, nea1, nea2, nea3
- ciphering_algorithms = ( "nea0" );
-
- # preferred integrity algorithms
- # the first one of the list that an UE supports in chosen
- # valid values: nia0, nia1, nia2, nia3
- integrity_algorithms = ( "nia2", "nia0" );
-
- # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
- # what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
- drb_ciphering = "yes";
- drb_integrity = "no";
+log_config : {
+ global_log_level = "info";
+ pdcp_log_level = "info";
+ f1ap_log_level = "info";
+ ngap_log_level = "info";
};
- log_config :
- {
- global_log_level ="info";
- hw_log_level ="info";
- phy_log_level ="info";
- mac_log_level ="info";
- rlc_log_level ="debug";
- pdcp_log_level ="info";
- rrc_log_level ="info";
- f1ap_log_level ="info";
- ngap_log_level ="debug";
- };
-
diff --git a/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf b/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf
index 535ef68bd0..4e65547db9 100644
--- a/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf
+++ b/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf
@@ -7,7 +7,7 @@ gNBs =
(
{
////////// Identification parameters:
- gNB_CU_ID = 0xe00;
+ gNB_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
@@ -56,23 +56,6 @@ gNBs =
}
);
-security = {
- # preferred ciphering algorithms
- # the first one of the list that an UE supports in chosen
- # valid values: nea0, nea1, nea2, nea3
- ciphering_algorithms = ( "nea0" );
-
- # preferred integrity algorithms
- # the first one of the list that an UE supports in chosen
- # valid values: nia0, nia1, nia2, nia3
- integrity_algorithms = ( "nia2", "nia0" );
-
- # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
- # what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
- drb_ciphering = "yes";
- drb_integrity = "no";
-};
-
log_config: {
global_log_level = "info";
};
diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf
index a1e66c7ade..eb664f1ccb 100644
--- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf
+++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf
@@ -6,7 +6,7 @@ gNBs =
(
{
////////// Identification parameters:
- gNB_CU_ID = 0xe00;
+ gNB_ID = 0xe00;
gNB_name = "gNB-OAI";
diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf
index 4f615b8dba..dcdb8307dc 100644
--- a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf
+++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf
@@ -10,7 +10,7 @@ gNBs =
(
{
////////// Identification parameters:
- gNB_CU_ID = 0xe00;
+ gNB_ID = 0xe00;
gNB_name = "gNB-Eurecom-n78_20";
diff --git a/doc/E1-design.md b/doc/E1-design.md
index 6f9e8f4edd..983013dce7 100644
--- a/doc/E1-design.md
+++ b/doc/E1-design.md
@@ -2,38 +2,55 @@
# 1. Introduction
-E1 is named for the interface that lies between the nodes CU Control Plane (CUCP) and CU User Plane (CUUP). Once the nodes are configured, all user plane traffic flows through CUUP.
+E1 is the interface that lies between the nodes CU Control Plane (CUCP) and CU User Plane (CUUP). Once the nodes are configured, all user plane traffic flows through CUUP.
-The E1 design in OAI follows the 3GPP specification in TS 38.460. The code design on E1 in OAI is very similar to
-F1. The ITTI message passing mechanism is used to exchange messages between E1AP thread, SCTP thread and RRC thread.
-
-The following sequence chart shows the current E1AP message flow.
+The E1 design in OAI follows the 3GPP specification in TS 38.460/463. The code
+design on E1 in OAI is very similar to F1: OAI uses E1 internally to set up
+bearers, even in monolithic gNB, where the actual "way" the messages are passed
+is abstracted through function pointers. More specifically, there are handlers
+that handle the E1 messages as shown below, *which are the same* no matter if
+the CU is integrated or separate in CU-CP/UP. The below sequence diagram lists
+the handlers that are executed and the current E1AP message flow (SCTP
+connection setup only in split-mode, the rest is the same for CU):
```mermaid
sequenceDiagram
participant c as CUCP
participant u as CUUP
- u->>c: SCTP new association
- c->>u: SCTP new association response
- Note over u: Create UDP sockets for F1-U and N3
+ u->c: SCTP connection setup (in split mode)
u->>c: E1AP Setup Request
+ Note over c: Execute rrc_gNB_process_e1_setup_req()
c->>u: E1AP Setup Response
+
Note over c: Receives PDU session setup request from AMF
c->>u: Bearer Context Setup Request
- Note over u: Configure DRBs and create GTP Tunnels for F1-U and N3
+ Note over u: Execute e1_bearer_context_setup()
Configure DRBs and create GTP Tunnels for F1-U and N3
u->>c: Bearer Context Setup Response
- Note over c: Sends F1-U UL TNL info to DU and receives DL TNL info
+ Note over c: Execute rrc_gNB_process_e1_setup_req()
Sends F1-U UL TNL info to DU and receives DL TNL info
+
c->>u: Bearer Context Modification Request
- Note over u: Updates GTP Tunnels with received info
+ Note over u: Execute e1_bearer_context_modif()
Updates GTP Tunnels with received info
+ u->>c: Bearer Context Modification Response
+ Note over c: Execute rrc_gNB_process_e1_bearer_context_modif_resp()
+
+ Note over c: UE release triggered
+ c->>u: Bearer Context Release Request
+ Note over u: Execute e1_bearer_release_cmd()
Frees GTP tunnels, PDCP data etc
+ u->>c: Bearer Context Release Complete
+ Note over c: Execute rrc_gNB_process_e1_bearer_context_release_cplt()
```
-_Note that the E1 bearer release procedures are currently not implemented._
+The files that implement the callback towards these handlers are in
+- `cucp_cuup_direct.c`: integrated CU (for CP=>UP messages)
+- `cucp_cuup_e1ap.c`: E1 split mode (for CP=>UP messages)
+- `cuup_cucp_direct.c`: integrated CU (for UP=>CP messages)
+- `cuup_cucp_e1ap.c`: E1 split mode (for UP=>CP messages)
# 2. Running the E1 Split
## 2.1 Configuration File
-The gNB is started based on the node type that is specified in the configuration file. To start a gNB instance in CUCP or CUUP, the `tr_s_preference` should be set to "f1" and the config member `E1_INTERFACE` should be present in the config file. The `type` parameter within the `E1_INTERFACE` should be set to `cp`, and `nr-softmodem` should be used to run a CU-CP. The type should be `up` and `nr-cuup` should be used to run the CU-UP. Further, there are the parameters `ipv4_cucp` and `ipv4_cuup` to specify the IP addresses of the respective network functions.
+The gNB is started based on the node type that is specified in the configuration file. To start a gNB instance in CUCP or CUUP, the `tr_s_preference` should be set to "f1" and the config member `E1_INTERFACE` should be present in the config file. The `type` parameter within the `E1_INTERFACE` should be set to `cp`, and executable `nr-softmodem` should be used to run a CU-CP. The type should be `up` and executable `nr-cuup` should be used to run the CU-UP. Further, there are the parameters `ipv4_cucp` and `ipv4_cuup` to specify the IP addresses of the respective network functions.
For CUCP, a typical `E1_INTERFACE` config looks like
```
@@ -62,7 +79,7 @@ One could take an existing CU configuration file and add the above parameters to
The CUUP uses the IP address specified in `local_s_address` for F1-U and `GNB_IPV4_ADDRESS_FOR_NGU` for N3 links. Note that `local_s_address` is under `gNBs` and `GNB_IPV4_ADDRESS_FOR_NGU` is part of the `NETWORK_INTERFACES` config member.
-Alternatively, you can use the config files `ci-scripts/conf_files/gnb-cucp.sa.conf` and `ci-scripts/conf_files/gnb-cuup.sa.conf` which are already in the repository.
+Alternatively, you can use the config files `ci-scripts/conf_files/gnb-cucp.sa.f1.conf` and `ci-scripts/conf_files/gnb-cuup.sa.f1.conf`.
## 2.2 Steps to Run the Split in rfsimulator with OAI UE
@@ -73,7 +90,7 @@ Note: A 5G core must be running at this point. Steps to start the OAI 5G core ca
1. Start the CUCP first by running the following command
```
-sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gnb-cucp.sa.conf --gNBs.[0].min_rxtxtime 6 --sa
+sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gnb-cucp.sa.f1.conf --gNBs.[0].min_rxtxtime 6 --sa
```
Note that `min_rxtxtime` should be set to `6` only when you are connecting an OAI UE to the gNB.
@@ -82,7 +99,7 @@ Note that `min_rxtxtime` should be set to `6` only when you are connecting an OA
CUUP (has its own executable):
```
-sudo ./nr-cuup -O ../../../ci-scripts/conf_files/gnb-cuup.sa.conf --sa
+sudo ./nr-cuup -O ../../../ci-scripts/conf_files/gnb-cuup.sa.f1.conf --sa
```
DU:
@@ -106,3 +123,25 @@ You can also run the nodes on different machines. If you do so please change the
{width=1200}
[PDF version](images/e1-archi.pdf) | [LaTeX/TikZ version](img/e1-archi.tex) if you want to modify to reflect your setup
+
+# 4. Multiple CU-UP
+
+It is possible to connect multiple CU-UP to the same CU-CP. In the handler of
+the E1 Setup Request, the CU-CP verifies that the PLMN(s) (MCC, MNC) between
+both nodes match, and that no CU-UP with the same ID exists. Note that the
+NSSAIs for the CU-UPs can be different.
+
+During attach, the following rules are used to select a CU-UP at the CU-CP, in
+order:
+- Select a CU-UP based on slice identifiers:
+ - If both the SST and SD match exactly, that CU-UP is selected. (If multiple
+ have the same NSSAI, the first is always selected.)
+ - Otherwise, the first CU-UP with the same SST but different SD is selected.
+- Round-robin across all CU-UPs.
+- The first CU-UP.
+- If no CU-UP is selected, the CU-CP asserts.
+
+Note that CU-UPs are not released from CU-CP internal structures. That means
+that you have to restart the CU-CP if you want to connect the CU-UP again
+(e.g., after a crash). The CU-CP might also misfunction during attach if a
+CU-UP was connected, but disconnected in the meantime.
diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c
index 2992953ef0..d83137c328 100644
--- a/executables/nr-cuup.c
+++ b/executables/nr-cuup.c
@@ -95,12 +95,6 @@ void nr_rlc_add_drb(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_Beare
abort();
}
-int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ctxt_pP, const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_p, int offset)
-{
- abort();
- return 0;
-}
-
void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp)
{
abort();
@@ -108,14 +102,14 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex
f1ap_cudu_inst_t *getCxt(instance_t instanceP)
{
- abort();
- return NULL;
-}
-
-NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue)
-{
- abort();
- return NULL;
+ // the E1 module uses F1's getCxt() to decide whether there is F1-U and if
+ // so, what is the GTP instance. In the CU-UP, we don't start the F1 module,
+ // and instead, E1 handles the GTP-U endpoint. In the following, we fake the
+ // instance and put the right GTP-U instance number in.
+ const e1ap_upcp_inst_t *e1inst = getCxtE1(instanceP);
+ static f1ap_cudu_inst_t fake = {0};
+ fake.gtpInst = e1inst->gtpInstF1U;
+ return &fake;
}
int main(int argc, char **argv)
@@ -134,7 +128,7 @@ int main(int argc, char **argv)
AssertFatal(rc >= 0, "Create task for GTPV1U failed\n");
rc = itti_create_task(TASK_CUUP_E1, E1AP_CUUP_task, NULL);
AssertFatal(rc >= 0, "Create task for CUUP E1 failed\n");
- nr_pdcp_layer_init();
+ nr_pdcp_layer_init(true);
cu_init_f1_ue_data(); // for CU-UP/CP mapping: we use the same
MessageDef *msg = RCconfig_NR_CU_E1(true);
AssertFatal(msg != NULL, "Send init to task for E1AP UP failed\n");
diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c
index 553f21a9fb..75a9e0dc24 100644
--- a/executables/nr-softmodem.c
+++ b/executables/nr-softmodem.c
@@ -80,7 +80,6 @@ unsigned short config_frames[4] = {2,9,11,13};
#include "nfapi/oai_integration/vendor_ext.h"
#include "gnb_config.h"
#include "openair2/E1AP/e1ap_common.h"
-#include "openair2/E1AP/e1ap_api.h"
#ifdef E2_AGENT
#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
@@ -403,12 +402,16 @@ static int create_gNB_tasks(ngran_node_t node_type)
if (node_type == ngran_gNB_CU || node_type == ngran_gNB) {
MessageDef *msg = RCconfig_NR_CU_E1(false);
instance_t inst = 0;
- createE1inst(UPtype, inst, &E1AP_SETUP_REQ(msg));
+ createE1inst(UPtype, inst, &E1AP_REGISTER_REQ(msg).net_config, NULL);
cuup_init_n3(inst);
- itti_free(TASK_UNKNOWN, msg);
- getCxtE1(inst)->same_process = true;
- ;
RC.nrrrc[gnb_id_start]->e1_inst = inst; // stupid instance !!!*/
+
+ /* send E1 Setup Request to RRC */
+ MessageDef *new_msg = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_SETUP_REQ);
+ E1AP_SETUP_REQ(new_msg) = E1AP_REGISTER_REQ(msg).setup_req;
+ new_msg->ittiMsgHeader.originInstance = -1; /* meaning, it is local */
+ itti_send_msg_to_task(TASK_RRC_GNB, 0 /*unused by callee*/, new_msg);
+ itti_free(TASK_UNKNOWN, msg);
}
//Use check on x2ap to consider the NSA scenario
@@ -562,7 +565,7 @@ void init_pdcp(void) {
LINK_ENB_PDCP_TO_GTPV1U_BIT;
if (!NODE_IS_DU(get_node_type())) {
- nr_pdcp_layer_init();
+ nr_pdcp_layer_init(get_node_type() == ngran_gNB_CUCP);
nr_pdcp_module_init(pdcp_initmask, 0);
}
}
diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c
index e5332e8e5e..a267211ce5 100644
--- a/executables/nr-uesoftmodem.c
+++ b/executables/nr-uesoftmodem.c
@@ -380,7 +380,7 @@ static void init_pdcp(int ue_id) {
if (get_softmodem_params()->nsa && rlc_module_init(0) != 0) {
LOG_I(RLC, "Problem at RLC initiation \n");
}
- nr_pdcp_layer_init();
+ nr_pdcp_layer_init(false);
nr_pdcp_module_init(pdcp_initmask, ue_id);
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index 6d80ac619c..21a237785d 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -108,6 +108,10 @@ void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB
return;
}
+void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); }
+void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) { abort(); }
+void e1_bearer_release_cmd(const e1ap_bearer_release_cmd_t *cmd) { abort(); }
+
int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
return 0;
}
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index 77a1d6d821..668c1cb633 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -104,6 +104,10 @@ void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB
return;
}
+void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); }
+void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) { abort(); }
+void e1_bearer_release_cmd(const e1ap_bearer_release_cmd_t *cmd) { abort(); }
+
int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
return 0;
}
diff --git a/openair2/COMMON/e1ap_messages_def.h b/openair2/COMMON/e1ap_messages_def.h
index 70533f8add..ea24ac9e18 100644
--- a/openair2/COMMON/e1ap_messages_def.h
+++ b/openair2/COMMON/e1ap_messages_def.h
@@ -20,6 +20,9 @@
*/
/* gNB_CUUP application layer -> E1AP messages */
+MESSAGE_DEF(E1AP_REGISTER_REQ, MESSAGE_PRIORITY_MED, e1ap_register_req_t, e1ap_register_req)
+
+/* E1AP messages -> RRC (CU-CP) */
MESSAGE_DEF(E1AP_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_setup_req_t , e1ap_setup_req)
/* E1AP -> eNB_DU or eNB_CU_RRC -> E1AP application layer messages */
@@ -30,4 +33,7 @@ MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_s
MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_RESP , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_resp_t , e1ap_bearer_setup_resp)
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_RESP, MESSAGE_PRIORITY_MED, e1ap_bearer_modif_resp_t, e1ap_bearer_modif_resp)
+MESSAGE_DEF(E1AP_BEARER_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, e1ap_bearer_release_cmd_t, e1ap_bearer_release_cmd)
+MESSAGE_DEF(E1AP_BEARER_CONTEXT_RELEASE_CPLT, MESSAGE_PRIORITY_MED, e1ap_bearer_release_cplt_t, e1ap_bearer_release_cplt)
diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h
index fba56ccb14..f98058b85c 100644
--- a/openair2/COMMON/e1ap_messages_types.h
+++ b/openair2/COMMON/e1ap_messages_types.h
@@ -32,6 +32,7 @@
#define E1AP_MAX_NUM_TRANSAC_IDS 4
#define E1AP_MAX_NUM_PLMNS 4
+#define E1AP_MAX_NUM_SLICES 1024
#define E1AP_MAX_NUM_CELL_GROUPS 4
#define E1AP_MAX_NUM_QOS_FLOWS 4
#define E1AP_MAX_NUM_NGRAN_DRB 4
@@ -40,11 +41,15 @@
#define E1AP_MAX_NUM_DRBS 4
#define E1AP_MAX_NUM_UP_PARAM 4
+#define E1AP_REGISTER_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_register_req
#define E1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_req
#define E1AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_resp
#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_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
typedef f1ap_net_ip_address_t e1ap_net_ip_address_t;
@@ -54,27 +59,39 @@ typedef struct PLMN_ID_s {
int mnc_digit_length;
} PLMN_ID_t;
-typedef struct e1ap_setup_req_s {
- uint64_t gNB_cu_up_id;
- char * gNB_cu_up_name;
- sctp_assoc_t assoc_id;
- uint64_t transac_id;
- int supported_plmns;
- PLMN_ID_t plmns[E1AP_MAX_NUM_PLMNS];
- uint16_t sctp_in_streams;
- uint16_t sctp_out_streams;
- uint16_t default_sctp_stream_id;
+typedef struct e1ap_nssai_t {
+ uint8_t sst;
+ uint32_t sd; // optional: "No SD" is 0xffffff, see 23.003 Sec 28.4.2
+} e1ap_nssai_t;
+
+typedef struct e1ap_net_config_t {
net_ip_address_t CUUP_e1_ip_address;
net_ip_address_t CUCP_e1_ip_address;
- long cn_support;
uint16_t remotePortF1U;
char* localAddressF1U;
uint16_t localPortF1U;
char* localAddressN3;
uint16_t localPortN3;
uint16_t remotePortN3;
+} e1ap_net_config_t;
+
+typedef struct e1ap_setup_req_s {
+ uint64_t gNB_cu_up_id;
+ char * gNB_cu_up_name;
+ uint64_t transac_id;
+ int supported_plmns;
+ struct {
+ PLMN_ID_t id;
+ int supported_slices;
+ e1ap_nssai_t *slice;
+ } plmn[E1AP_MAX_NUM_PLMNS];
} e1ap_setup_req_t;
+typedef struct e1ap_register_req_t {
+ e1ap_setup_req_t setup_req;
+ e1ap_net_config_t net_config;
+} e1ap_register_req_t;
+
typedef struct e1ap_setup_resp_s {
long transac_id;
} e1ap_setup_resp_t;
@@ -140,7 +157,7 @@ typedef struct DRB_nGRAN_to_setup_s {
typedef struct pdu_session_to_setup_s {
long sessionId;
long sessionType;
- int8_t sst;
+ e1ap_nssai_t nssai;
long integrityProtectionIndication;
long confidentialityProtectionIndication;
in_addr_t tlAddress;
@@ -165,8 +182,6 @@ typedef struct e1ap_bearer_setup_req_s {
long ueDlAggMaxBitRate;
PLMN_ID_t servingPLMNid;
long activityNotificationLevel;
- int numDRBs;
- drb_to_setup_t DRBList[E1AP_MAX_NUM_DRBS];
int numPDUSessions;
pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS];
int numPDUSessionsMod;
@@ -180,13 +195,10 @@ typedef struct e1ap_bearer_release_cmd_s {
long cause;
} e1ap_bearer_release_cmd_t;
-typedef struct drb_setup_s {
- int drbId;
- in_addr_t tlAddress;
- int teId;
- int numUpParam;
- up_params_t UpParamList[E1AP_MAX_NUM_UP_PARAM];
-} drb_setup_t;
+typedef struct e1ap_bearer_release_cplt_s {
+ uint32_t gNB_cu_cp_ue_id;
+ uint32_t gNB_cu_up_ue_id;
+} e1ap_bearer_release_cplt_t;
typedef struct qos_flow_setup_s {
long id;
@@ -200,6 +212,10 @@ typedef struct DRB_nGRAN_setup_s {
qos_flow_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS];
} DRB_nGRAN_setup_t;
+typedef struct DRB_nGRAN_modified_s {
+ long id;
+} DRB_nGRAN_modified_t;
+
typedef struct DRB_nGRAN_failed_s {
long id;
long cause_type;
@@ -216,13 +232,25 @@ typedef struct pdu_session_setup_s {
DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_NGRAN_DRB];
} pdu_session_setup_t;
+typedef struct pdu_session_modif_s {
+ long id;
+ // setup as part of PDU session modification not supported yet
+ int numDRBModified;
+ DRB_nGRAN_modified_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB];
+} pdu_session_modif_t;
+
typedef struct e1ap_bearer_setup_resp_s {
uint32_t gNB_cu_cp_ue_id;
uint32_t gNB_cu_up_ue_id;
- int numDRBs;
- drb_setup_t DRBList[E1AP_MAX_NUM_DRBS];
int numPDUSessions;
pdu_session_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS];
} e1ap_bearer_setup_resp_t;
+typedef struct e1ap_bearer_modif_resp_s {
+ uint32_t gNB_cu_cp_ue_id;
+ uint32_t gNB_cu_up_ue_id;
+ int numPDUSessionsMod;
+ pdu_session_modif_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS];
+} e1ap_bearer_modif_resp_t;
+
#endif /* E1AP_MESSAGES_TYPES_H */
diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h
index 465c6c5342..037dfbe86c 100644
--- a/openair2/COMMON/rrc_messages_types.h
+++ b/openair2/COMMON/rrc_messages_types.h
@@ -403,13 +403,13 @@ typedef struct NbIoTRrcConfigurationReq_s {
// gNB: GNB_APP -> RRC messages
typedef struct NRRrcConfigurationReq_s {
- uint64_t cell_identity;
uint32_t tac;
uint16_t mcc[PLMN_LIST_MAX_SIZE];
uint16_t mnc[PLMN_LIST_MAX_SIZE];
uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE];
uint8_t num_plmn;
+ bool um_on_default_drb;
bool enable_sdap;
int drbs;
} gNB_RrcConfigurationReq;
diff --git a/openair2/E1AP/CMakeLists.txt b/openair2/E1AP/CMakeLists.txt
index 01a969de7e..c7657eed5a 100644
--- a/openair2/E1AP/CMakeLists.txt
+++ b/openair2/E1AP/CMakeLists.txt
@@ -1,7 +1,7 @@
add_subdirectory(MESSAGES)
-add_library(e1ap e1ap.c e1ap_common.c e1ap_api.c)
+add_library(e1ap e1ap.c e1ap_common.c)
target_link_libraries(e1ap
PUBLIC asn1_e1ap f1ap
- PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap UTIL e1_pdcp_if e1_if)
+ PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap UTIL e1_if)
target_include_directories(e1ap PUBLIC ${CMAKE_CURRENT_DIR})
diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c
index 2390b23d2e..077c67ca98 100644
--- a/openair2/E1AP/e1ap.c
+++ b/openair2/E1AP/e1ap.c
@@ -23,7 +23,6 @@
#include "e1ap.h"
#include "e1ap_common.h"
-#include "e1ap_api.h"
#include "gnb_config.h"
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
#include "openair3/UTILS/conversions.h"
@@ -33,9 +32,10 @@
#include "openair2/F1AP/f1ap_common.h"
#include "e1ap_default_values.h"
#include "gtp_itf.h"
+#include "openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h"
#define E1AP_NUM_MSG_HANDLERS 14
-typedef int (*e1ap_message_processing_t)(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *message_p);
+typedef int (*e1ap_message_processing_t)(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *message_p);
const e1ap_message_processing_t e1ap_message_processing[E1AP_NUM_MSG_HANDLERS][3] = {
{0, 0, 0}, /* Reset */
@@ -49,7 +49,9 @@ const e1ap_message_processing_t e1ap_message_processing[E1AP_NUM_MSG_HANDLERS][3
{e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST,
e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE,
e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE}, /* bearerContextSetup */
- {e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST, 0, 0}, /* bearerContextModification */
+ {e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST,
+ e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE,
+ 0}, /* bearerContextModification */
{0, 0, 0}, /* bearerContextModificationRequired */
{e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND, e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE, 0}, /* bearerContextRelease */
{0, 0, 0}, /* bearerContextReleaseRequired */
@@ -91,8 +93,8 @@ int e1ap_handle_message(instance_t instance, sctp_assoc_t assoc_id, const uint8_
ret=-1;
} else {
/* Calling the right handler */
- LOG_I(E1AP, "Calling handler with instance %ld\n",instance);
- ret = (*e1ap_message_processing[procedureCode][pdu.present - 1])(getCxtE1(instance), &pdu);
+ LOG_D(E1AP, "Calling handler with instance %ld\n",instance);
+ ret = (*e1ap_message_processing[procedureCode][pdu.present - 1])(assoc_id, getCxtE1(instance), &pdu);
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, &pdu);
@@ -109,18 +111,11 @@ void e1_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_dat
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
-void e1ap_itti_send_sctp_close_association(bool isCu, instance_t instance) {
- MessageDef *message = itti_alloc_new_message(TASK_S1AP, 0, SCTP_CLOSE_ASSOCIATION);
- sctp_close_association_t *sctp_close_association = &message->ittiMsg.sctp_close_association;
- sctp_close_association->assoc_id = e1ap_assoc_id(isCu,instance);
- itti_send_msg_to_task(TASK_SCTP, instance, message);
-}
-
-int e1ap_send_RESET(bool isCu, e1ap_setup_req_t *setupReq, E1AP_Reset_t *Reset)
+int e1ap_send_RESET(bool isCu, sctp_assoc_t assoc_id, E1AP_Reset_t *Reset)
{
AssertFatal(false,"Not implemented yet\n");
E1AP_E1AP_PDU_t pdu= {0};
- return e1ap_encode_send(isCu, setupReq, &pdu, 0, __func__);
+ return e1ap_encode_send(isCu, assoc_id, &pdu, 0, __func__);
}
int e1ap_send_RESET_ACKNOWLEDGE(instance_t instance, E1AP_Reset_t *Reset) {
@@ -177,7 +172,7 @@ static void fill_SETUP_REQUEST(e1ap_setup_req_t *setup, E1AP_E1AP_PDU_t *pdu)
ieC1->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_TransactionID;
setup->transac_id = E1AP_get_next_transaction_identifier();
ieC1->value.choice.TransactionID = setup->transac_id;
- LOG_I(E1AP, "Transaction ID of setup request %ld\n", setup->transac_id);
+ LOG_D(E1AP, "Transaction ID of setup request %ld\n", setup->transac_id);
/* mandatory */
/* c2. GNB_CU_ID (integer value) */
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC2);
@@ -185,13 +180,23 @@ static void fill_SETUP_REQUEST(e1ap_setup_req_t *setup, E1AP_E1AP_PDU_t *pdu)
ieC2->criticality = E1AP_Criticality_reject;
ieC2->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_ID;
asn_int642INTEGER(&ieC2->value.choice.GNB_CU_UP_ID, setup->gNB_cu_up_id);
+
+ /* optional */
+ if (setup->gNB_cu_up_name) {
+ asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC3);
+ ieC3->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name;
+ ieC3->criticality = E1AP_Criticality_ignore;
+ ieC3->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_Name;
+ OCTET_STRING_fromBuf(&ieC3->value.choice.GNB_CU_UP_Name, setup->gNB_cu_up_name, strlen(setup->gNB_cu_up_name));
+ }
+
/* mandatory */
/* c4. CN Support */
asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC4);
ieC4->id = E1AP_ProtocolIE_ID_id_CNSupport;
ieC4->criticality = E1AP_Criticality_reject;
ieC4->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_CNSupport;
- ieC4->value.choice.CNSupport = setup->cn_support;
+ ieC4->value.choice.CNSupport = E1AP_CNSupport_c_5gc; /* only 5GC supported */
/* mandatory */
/* c5. Supported PLMNs */
@@ -205,7 +210,24 @@ static void fill_SETUP_REQUEST(e1ap_setup_req_t *setup, E1AP_E1AP_PDU_t *pdu)
for (int i=0; i < numSupportedPLMNs; i++) {
asn1cSequenceAdd(ieC5->value.choice.SupportedPLMNs_List.list, E1AP_SupportedPLMNs_Item_t, supportedPLMN);
/* 5.1 PLMN Identity */
- MCC_MNC_TO_PLMNID(setup->plmns[i].mcc, setup->plmns[i].mnc, setup->plmns[i].mnc_digit_length, &supportedPLMN->pLMN_Identity);
+ PLMN_ID_t *id = &setup->plmn[i].id;
+ MCC_MNC_TO_PLMNID(id->mcc, id->mnc, id->mnc_digit_length, &supportedPLMN->pLMN_Identity);
+
+ int n = setup->plmn[i].supported_slices;
+ if (setup->plmn[i].slice != NULL && n > 0) {
+ supportedPLMN->slice_Support_List = calloc(1, sizeof(*supportedPLMN->slice_Support_List));
+ AssertFatal(supportedPLMN->slice_Support_List != NULL, "out of memory\n");
+ for (int s = 0; s < n; ++s) {
+ asn1cSequenceAdd(supportedPLMN->slice_Support_List->list, E1AP_Slice_Support_Item_t, slice);
+ e1ap_nssai_t *nssai = &setup->plmn[i].slice[s];
+ INT8_TO_OCTET_STRING(nssai->sst, &slice->sNSSAI.sST);
+ if (nssai->sd != 0xffffff) {
+ slice->sNSSAI.sD = malloc(sizeof(*slice->sNSSAI.sD));
+ AssertFatal(slice->sNSSAI.sD != NULL, "out of memory\n");
+ INT24_TO_OCTET_STRING(nssai->sd, slice->sNSSAI.sD);
+ }
+ }
+ }
}
}
@@ -228,13 +250,11 @@ static void fill_SETUP_RESPONSE(const e1ap_setup_resp_t *e1ap_setup_resp, E1AP_E
ieC1->value.choice.TransactionID = e1ap_setup_resp->transac_id;
}
-void e1ap_send_SETUP_RESPONSE(instance_t inst, const e1ap_setup_resp_t *e1ap_setup_resp)
+void e1ap_send_SETUP_RESPONSE(sctp_assoc_t assoc_id, const e1ap_setup_resp_t *e1ap_setup_resp)
{
- AssertFatal(getCxtE1(inst), "");
- e1ap_setup_req_t *setupReq = &getCxtE1(inst)->setupReq;
E1AP_E1AP_PDU_t pdu = {0};
fill_SETUP_RESPONSE(e1ap_setup_resp, &pdu);
- e1ap_encode_send(getCxtE1(inst)->type, setupReq, &pdu, 0, __func__);
+ e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__);
}
static void fill_SETUP_FAILURE(long transac_id, E1AP_E1AP_PDU_t *pdu)
@@ -264,19 +284,17 @@ static void fill_SETUP_FAILURE(long transac_id, E1AP_E1AP_PDU_t *pdu)
ieC2->value.choice.Cause.choice.radioNetwork = E1AP_CauseRadioNetwork_unspecified;
}
-void e1apCUCP_send_SETUP_FAILURE(e1ap_setup_req_t *setupReq, long transac_id)
+void e1apCUCP_send_SETUP_FAILURE(sctp_assoc_t assoc_id, long transac_id)
{
E1AP_E1AP_PDU_t pdu = {0};
fill_SETUP_FAILURE(transac_id, &pdu);
- e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__);
+ e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__);
}
void extract_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu,
e1ap_setup_req_t *req) {
E1AP_GNB_CU_UP_E1SetupRequestIEs_t *ie;
E1AP_GNB_CU_UP_E1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_E1SetupRequest;
- /* assoc_id */
- /* req->assoc_id = assoc_id; */
/* transac_id */
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in,
@@ -290,11 +308,21 @@ void extract_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu,
asn_INTEGER2ulong(&ie->value.choice.GNB_CU_UP_ID, &req->gNB_cu_up_id);
LOG_D(E1AP, "gNB CU UP ID: %ld\n", req->gNB_cu_up_id);
+ /* gNB CU UP name */
+ F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in,
+ E1AP_ProtocolIE_ID_id_gNB_CU_UP_Name, false);
+ req->gNB_cu_up_name = NULL;
+ if (ie != NULL) {
+ req->gNB_cu_up_name = calloc(ie->value.choice.GNB_CU_UP_Name.size + 1, sizeof(char));
+ AssertFatal(req->gNB_cu_up_name != NULL, "out of memory\n");
+ memcpy(req->gNB_cu_up_name, ie->value.choice.GNB_CU_UP_Name.buf, ie->value.choice.GNB_CU_UP_Name.size);
+ LOG_D(E1AP, "req->gNB_cu_up_name %s\n", req->gNB_cu_up_name);
+ }
+
/* CN Support */
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in,
E1AP_ProtocolIE_ID_id_CNSupport, true);
- req->cn_support = ie->value.choice.CNSupport;
- LOG_D(E1AP, "E1ap CN support: %ld\n", req->cn_support);
+ AssertFatal(ie->value.choice.CNSupport == E1AP_CNSupport_c_5gc, "only 5GC CN Support supported\n");
/* Supported PLMNs */
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in,
@@ -306,26 +334,41 @@ void extract_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu,
E1AP_SupportedPLMNs_Item_t *supported_plmn_item = (E1AP_SupportedPLMNs_Item_t *)(ie->value.choice.SupportedPLMNs_List.list.array[i]);
/* PLMN Identity */
- PLMNID_TO_MCC_MNC(&supported_plmn_item->pLMN_Identity,
- req->plmns[i].mcc,
- req->plmns[i].mnc,
- req->plmns[i].mnc_digit_length);
- LOG_D(E1AP, "MCC: %d\nMNC: %d\n", req->plmns[i].mcc, req->plmns[i].mnc);
+ PLMN_ID_t *id = &req->plmn[i].id;
+ PLMNID_TO_MCC_MNC(&supported_plmn_item->pLMN_Identity, id->mcc, id->mnc, id->mnc_digit_length);
+ LOG_D(E1AP, "MCC %d MNC %d\n", id->mcc, id->mnc);
+
+ /* NSSAI */
+ if (supported_plmn_item->slice_Support_List) {
+ int n = supported_plmn_item->slice_Support_List->list.count;
+ req->plmn[i].supported_slices = n;
+ req->plmn[i].slice = calloc(n, sizeof(*req->plmn[i].slice));
+ AssertFatal(req->plmn[i].slice != NULL, "out of memory\n");
+ for (int s = 0; s < n; ++s) {
+ e1ap_nssai_t *slice = &req->plmn[i].slice[s];
+ const E1AP_SNSSAI_t *es = &supported_plmn_item->slice_Support_List->list.array[s]->sNSSAI;
+ OCTET_STRING_TO_INT8(&es->sST, slice->sst);
+ slice->sd = 0xffffff;
+ if (es->sD != NULL)
+ OCTET_STRING_TO_INT24(es->sD, slice->sd);
+ LOG_D(E1AP, "SST %d SD %06x\n", slice->sst, slice->sd);
+ }
+ }
}
}
-int e1apCUCP_handle_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUCP_handle_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
DevAssert(pdu != NULL);
- extract_SETUP_REQUEST(pdu, &inst->setupReq);
/* Create ITTI message and send to queue */
MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0 /*unused by callee*/, E1AP_SETUP_REQ);
- memcpy(&E1AP_SETUP_REQ(msg_p), &inst->setupReq, sizeof(e1ap_setup_req_t));
+ extract_SETUP_REQUEST(pdu, &E1AP_SETUP_REQ(msg_p));
+ msg_p->ittiMsgHeader.originInstance = assoc_id;
- if (inst->setupReq.supported_plmns > 0) {
+ if (E1AP_SETUP_REQ(msg_p).supported_plmns > 0) {
itti_send_msg_to_task(TASK_RRC_GNB, 0 /*unused by callee*/, msg_p);
} else {
- e1apCUCP_send_SETUP_FAILURE(&inst->setupReq, inst->setupReq.transac_id);
+ e1apCUCP_send_SETUP_FAILURE(assoc_id, E1AP_SETUP_REQ(msg_p).transac_id);
itti_free(TASK_CUCP_E1, msg_p);
return -1;
}
@@ -333,7 +376,7 @@ int e1apCUCP_handle_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t
return 0;
}
-int e1apCUUP_handle_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUUP_handle_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
LOG_D(E1AP, "%s\n", __func__);
DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome);
@@ -345,7 +388,7 @@ int e1apCUUP_handle_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t
/* transac_id */
long transaction_id;
- long old_transaction_id = inst->setupReq.transac_id;
+ long old_transaction_id = inst->cuup.setupReq.transac_id;
F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ie, in,
E1AP_ProtocolIE_ID_id_TransactionID, true);
transaction_id = ie->value.choice.TransactionID;
@@ -361,7 +404,7 @@ int e1apCUUP_handle_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t
return 0;
}
-int e1apCUUP_handle_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUUP_handle_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
E1AP_GNB_CU_UP_E1SetupFailureIEs_t *ie;
DevAssert(pdu != NULL);
@@ -428,26 +471,26 @@ static void fill_CONFIGURATION_UPDATE(E1AP_E1AP_PDU_t *pdu)
E1 configuration update: can be sent in both ways, to be refined
*/
-void e1apCUUP_send_CONFIGURATION_UPDATE(e1ap_setup_req_t *setupReq)
+void e1apCUUP_send_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id)
{
E1AP_E1AP_PDU_t pdu = {0};
fill_CONFIGURATION_UPDATE(&pdu);
- e1ap_encode_send(UPtype, setupReq, &pdu, 0, __func__);
+ e1ap_encode_send(UPtype, assoc_id, &pdu, 0, __func__);
}
-int e1apCUCP_send_gNB_DU_CONFIGURATION_FAILURE(e1ap_setup_req_t *setupReq)
+int e1apCUCP_send_gNB_DU_CONFIGURATION_FAILURE(void)
{
AssertFatal(false,"Not implemented yet\n");
return -1;
}
-int e1apCUCP_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(e1ap_setup_req_t *setupReq)
+int e1apCUCP_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(void)
{
AssertFatal(false,"Not implemented yet\n");
return -1;
}
-int e1apCUCP_handle_CONFIGURATION_UPDATE(e1ap_setup_req_t *setupReq, E1AP_E1AP_PDU_t *pdu)
+int e1apCUCP_handle_CONFIGURATION_UPDATE(E1AP_E1AP_PDU_t *pdu)
{
/*
E1AP_GNB_CU_UP_E1SetupRequestIEs_t *ie;
@@ -459,8 +502,7 @@ int e1apCUCP_handle_CONFIGURATION_UPDATE(e1ap_setup_req_t *setupReq, E1AP_E1AP_P
return -1;
}
-int e1apCUUP_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(e1ap_setup_req_t *setupReq,
- sctp_assoc_t assoc_id,
+int e1apCUUP_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id,
uint32_t stream,
E1AP_E1AP_PDU_t *pdu)
{
@@ -468,8 +510,7 @@ int e1apCUUP_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(e1ap_setup_req_t *se
return -1;
}
-int e1apCUUP_handle_gNB_DU_CONFIGURATION_FAILURE(e1ap_setup_req_t *setupReq,
- sctp_assoc_t assoc_id,
+int e1apCUUP_handle_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id,
uint32_t stream,
E1AP_E1AP_PDU_t *pdu)
{
@@ -507,7 +548,7 @@ int e1ap_handle_RELEASE_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id,
BEARER CONTEXT SETUP REQUEST
*/
-static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_setup_req_t *setup, e1ap_bearer_setup_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu)
+static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu)
{
pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage;
asn1cCalloc(pdu->choice.initiatingMessage, msg);
@@ -548,7 +589,7 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_setup_req_t *setup, e1ap_beare
ieC4->id = E1AP_ProtocolIE_ID_id_Serving_PLMN;
ieC4->criticality = E1AP_Criticality_ignore;
ieC4->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity;
- PLMN_ID_t *servingPLMN = setup->plmns; // First PLMN is serving PLMN. TODO: Remove hard coding here
+ PLMN_ID_t *servingPLMN = &bearerCxt->servingPLMNid;
MCC_MNC_TO_PLMNID(servingPLMN->mcc, servingPLMN->mnc, servingPLMN->mnc_digit_length, &ieC4->value.choice.PLMN_Identity);
/* mandatory */
/* Activity Notification Level */
@@ -576,7 +617,12 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_setup_req_t *setup, e1ap_beare
ieC6_1->pDU_Session_ID = i->sessionId;
ieC6_1->pDU_Session_Type = i->sessionType;
- INT8_TO_OCTET_STRING(i->sst, &ieC6_1->sNSSAI.sST);
+ INT8_TO_OCTET_STRING(i->nssai.sst, &ieC6_1->sNSSAI.sST);
+ if (i->nssai.sd != 0xffffff) {
+ ieC6_1->sNSSAI.sD = malloc(sizeof(*ieC6_1->sNSSAI.sD));
+ AssertFatal(ieC6_1->sNSSAI.sD != NULL, "out of memory\n");
+ INT24_TO_OCTET_STRING(i->nssai.sd, ieC6_1->sNSSAI.sD);
+ }
ieC6_1->securityIndication.integrityProtectionIndication = i->integrityProtectionIndication;
ieC6_1->securityIndication.confidentialityProtectionIndication = i->confidentialityProtectionIndication;
@@ -633,21 +679,14 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_setup_req_t *setup, e1ap_beare
return 0;
}
-void e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance, e1ap_bearer_setup_req_t *const bearerCxt)
+void e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const bearerCxt)
{
- if (!getCxtE1(instance)) {
- LOG_E(E1AP, "Received a UE bearer to establish while no CU-UP is connected, response on NGAP to send failure is not developped\n");
- // Fixme: add response on NGAP to send failure
- return;
- }
-
E1AP_E1AP_PDU_t pdu = {0};
- e1ap_setup_req_t *setupReq = &getCxtE1(instance)->setupReq;
- fill_BEARER_CONTEXT_SETUP_REQUEST(setupReq, bearerCxt, &pdu);
- e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__);
+ fill_BEARER_CONTEXT_SETUP_REQUEST(bearerCxt, &pdu);
+ e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__);
}
-static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const resp, E1AP_E1AP_PDU_t *pdu)
+static void fill_BEARER_CONTEXT_SETUP_RESPONSE(const e1ap_bearer_setup_resp_t *resp, E1AP_E1AP_PDU_t *pdu)
{
/* Create */
/* 0. pdu Type */
@@ -676,7 +715,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r
ieC3->id = E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse;
ieC3->criticality = E1AP_Criticality_reject;
ieC3->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse;
- if (0) { // EUTRAN
+ /*if (0) { // EUTRAN
ieC3->value.choice.System_BearerContextSetupResponse.present = E1AP_System_BearerContextSetupResponse_PR_e_UTRAN_BearerContextSetupResponse;
E1AP_ProtocolIE_Container_4932P21_t *msgEUTRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P21_t));
ieC3->value.choice.System_BearerContextSetupResponse.choice.e_UTRAN_BearerContextSetupResponse = (struct E1AP_ProtocolIE_Container *) msgEUTRAN_list;
@@ -703,7 +742,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r
INT32_TO_OCTET_STRING(j->teId, &gTPTunnel->gTP_TEID);
}
}
- } else {
+ } else */{
ieC3->value.choice.System_BearerContextSetupResponse.present = E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse;
E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P22_t));
ieC3->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse = (struct E1AP_ProtocolIE_Container *) msgNGRAN_list;
@@ -713,7 +752,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r
msgNGRAN->value.present = E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List;
E1AP_PDU_Session_Resource_Setup_List_t *pduSetup = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List;
- for (pdu_session_setup_t *i=resp->pduSession; i < resp->pduSession+resp->numPDUSessions; i++) {
+ for (const pdu_session_setup_t *i=resp->pduSession; i < resp->pduSession+resp->numPDUSessions; i++) {
asn1cSequenceAdd(pduSetup->list, E1AP_PDU_Session_Resource_Setup_Item_t, ieC3_1);
ieC3_1->pDU_Session_ID = i->id;
@@ -722,11 +761,11 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(i->tlAddress, &gTPTunnel->transportLayerAddress);
INT32_TO_OCTET_STRING(i->teId, &gTPTunnel->gTP_TEID);
- for (DRB_nGRAN_setup_t *j=i->DRBnGRanList; j < i->DRBnGRanList+i->numDRBSetup; j++) {
+ for (const DRB_nGRAN_setup_t *j=i->DRBnGRanList; j < i->DRBnGRanList+i->numDRBSetup; j++) {
asn1cSequenceAdd(ieC3_1->dRB_Setup_List_NG_RAN.list, E1AP_DRB_Setup_Item_NG_RAN_t, ieC3_1_1);
ieC3_1_1->dRB_ID = j->id;
- for (up_params_t *k=j->UpParamList; k < j->UpParamList+j->numUpParam; k++) {
+ for (const up_params_t *k=j->UpParamList; k < j->UpParamList+j->numUpParam; k++) {
asn1cSequenceAdd(ieC3_1_1->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, ieC3_1_1_1);
ieC3_1_1_1->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel;
asn1cCalloc(ieC3_1_1_1->uP_TNL_Information.choice.gTPTunnel, gTPTunnel);
@@ -734,7 +773,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r
INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID);
}
- for (qos_flow_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlowSetup; k++) {
+ for (const qos_flow_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlowSetup; k++) {
asn1cSequenceAdd(ieC3_1_1->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, ieC3_1_1_1);
ieC3_1_1_1->qoS_Flow_Identifier = k->id;
}
@@ -743,7 +782,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r
if (i->numDRBFailed > 0)
ieC3_1->dRB_Failed_List_NG_RAN = calloc(1, sizeof(E1AP_DRB_Failed_List_NG_RAN_t));
- for (DRB_nGRAN_failed_t *j=i->DRBnGRanFailedList; j < i->DRBnGRanFailedList+i->numDRBFailed; j++) {
+ for (const DRB_nGRAN_failed_t *j=i->DRBnGRanFailedList; j < i->DRBnGRanFailedList+i->numDRBFailed; j++) {
asn1cSequenceAdd(ieC3_1->dRB_Failed_List_NG_RAN->list, E1AP_DRB_Failed_Item_NG_RAN_t, ieC3_1_1);
ieC3_1_1->dRB_ID = j->id;
@@ -774,11 +813,11 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const r
}
}
-void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, e1ap_bearer_setup_resp_t *const resp)
+void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, const e1ap_bearer_setup_resp_t *resp)
{
E1AP_E1AP_PDU_t pdu = {0};
fill_BEARER_CONTEXT_SETUP_RESPONSE(resp, &pdu);
- e1ap_encode_send(UPtype, &inst->setupReq, &pdu, 0, __func__);
+ e1ap_encode_send(UPtype, assoc_id, &pdu, 0, __func__);
}
int e1apCUUP_send_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance) {
@@ -791,7 +830,7 @@ void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu,
const E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest;
E1AP_BearerContextSetupRequestIEs_t *ie;
- LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count);
+ LOG_D(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count);
for (int i=0; i < in->protocolIEs.list.count; i++) {
ie = in->protocolIEs.list.array[i];
@@ -862,7 +901,10 @@ void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu,
pdu_session->sessionId = pdu2Setup->pDU_Session_ID;
pdu_session->sessionType = pdu2Setup->pDU_Session_Type;
- OCTET_STRING_TO_INT8(&pdu2Setup->sNSSAI.sST, pdu_session->sst);
+ OCTET_STRING_TO_INT8(&pdu2Setup->sNSSAI.sST, pdu_session->nssai.sst);
+ pdu_session->nssai.sd = 0xffffff;
+ if (pdu2Setup->sNSSAI.sD != NULL)
+ OCTET_STRING_TO_INT24(pdu2Setup->sNSSAI.sD, pdu_session->nssai.sd);
pdu_session->integrityProtectionIndication = pdu2Setup->securityIndication.integrityProtectionIndication;
pdu_session->confidentialityProtectionIndication = pdu2Setup->securityIndication.confidentialityProtectionIndication;
@@ -946,7 +988,7 @@ void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu,
}
-int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
{
DevAssert(pdu != NULL);
DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage);
@@ -956,7 +998,8 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(e1ap_upcp_inst_t *e1_inst, cons
e1ap_bearer_setup_req_t bearerCxt = {0};
extract_BEARER_CONTEXT_SETUP_REQUEST(pdu, &bearerCxt);
- process_e1_bearer_context_setup_req(e1_inst->instance, &bearerCxt);
+
+ e1_bearer_context_setup(&bearerCxt);
return 0;
}
@@ -965,7 +1008,7 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu,
const E1AP_BearerContextSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse;
E1AP_BearerContextSetupResponseIEs_t *ie;
- LOG_I(E1AP, "Bearer context setup response number of IEs %d\n", in->protocolIEs.list.count);
+ LOG_D(E1AP, "Bearer context setup response number of IEs %d\n", in->protocolIEs.list.count);
for (int i=0; i < in->protocolIEs.list.count; i++) {
ie = in->protocolIEs.list.array[i];
@@ -1046,7 +1089,7 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu,
}
}
-int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome);
DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_bearerContextSetup);
@@ -1056,6 +1099,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const
MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP);
e1ap_bearer_setup_resp_t *bearerCxt = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg);
extract_BEARER_CONTEXT_SETUP_RESPONSE(pdu, bearerCxt);
+ msg->ittiMsgHeader.originInstance = assoc_id;
// Fixme: instance is the NGAP instance, no good way to set it here
instance_t instance = 0;
itti_send_msg_to_task(TASK_RRC_GNB, instance, msg);
@@ -1063,7 +1107,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const
return 0;
}
-int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
{
AssertFatal(false,"Not implemented yet\n");
return -1;
@@ -1073,7 +1117,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E
BEARER CONTEXT MODIFICATION REQUEST
*/
-static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_setup_req_t *setupReq, e1ap_bearer_setup_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu)
+static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu)
{
pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage;
asn1cCalloc(pdu->choice.initiatingMessage, msg);
@@ -1135,18 +1179,76 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_setup_req_t *setupReq,
return 0;
}
-static void e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t inst, e1ap_bearer_setup_req_t *const bearerCxt)
+static void e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const bearerCxt)
{
- AssertFatal(getCxtE1(inst), "");
- e1ap_setup_req_t *setupReq = &getCxtE1(inst)->setupReq;
E1AP_E1AP_PDU_t pdu = {0};
- fill_BEARER_CONTEXT_MODIFICATION_REQUEST(setupReq, bearerCxt, &pdu);
- e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__);
+ fill_BEARER_CONTEXT_MODIFICATION_REQUEST(bearerCxt, &pdu);
+ e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__);
}
-int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) {
- AssertFatal(false,"Not implemented yet\n");
- return -1;
+static void fill_BEARER_CONTEXT_MODIFICATION_RESPONSE(const e1ap_bearer_modif_resp_t *resp, E1AP_E1AP_PDU_t *pdu)
+{
+ pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome;
+ asn1cCalloc(pdu->choice.successfulOutcome, msg);
+ msg->procedureCode = E1AP_ProcedureCode_id_bearerContextModification;
+ msg->criticality = E1AP_Criticality_reject;
+ msg->value.present = E1AP_SuccessfulOutcome__value_PR_BearerContextModificationResponse;
+ E1AP_BearerContextModificationResponse_t *out = &pdu->choice.successfulOutcome->value.choice.BearerContextModificationResponse;
+
+ /* mandatory */
+ /* c1. gNB-CU-CP UE E1AP ID */
+ asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ieCuCpId);
+ ieCuCpId->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID;
+ ieCuCpId->criticality = E1AP_Criticality_reject;
+ ieCuCpId->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID;
+ ieCuCpId->value.choice.GNB_CU_CP_UE_E1AP_ID = resp->gNB_cu_cp_ue_id;
+
+ /* mandatory */
+ /* c2. gNB-CU-UP UE E1AP ID */
+ asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ieCuUpId);
+ ieCuUpId->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID;
+ ieCuUpId->criticality = E1AP_Criticality_reject;
+ ieCuUpId->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID;
+ ieCuUpId->value.choice.GNB_CU_UP_UE_E1AP_ID = resp->gNB_cu_up_ue_id;
+
+ /* optional */
+ /* PDU sessions that have been modified */
+ asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ieSys);
+ ieSys->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse;
+ ieSys->criticality = E1AP_Criticality_ignore;
+ ieSys->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse;
+
+ E1AP_System_BearerContextModificationResponse_t *sys = &ieSys->value.choice.System_BearerContextModificationResponse;
+ E1AP_ProtocolIE_Container_4932P29_t *piel = calloc(1, sizeof(*piel));
+ sys->present = E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse;
+ sys->choice.nG_RAN_BearerContextModificationResponse = (struct E1AP_ProtocolIE_Container *)piel;
+ asn1cSequenceAdd(piel->list, E1AP_NG_RAN_BearerContextModificationResponse_t, ngran_bcmr);
+ ngran_bcmr->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List;
+ ngran_bcmr->criticality = E1AP_Criticality_reject;
+ ngran_bcmr->value.present = E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List;
+ E1AP_PDU_Session_Resource_Modified_List_t *pdu_mod_l = &ngran_bcmr->value.choice.PDU_Session_Resource_Modified_List;
+ for (int i = 0; i < resp->numPDUSessionsMod; ++i) {
+ const pdu_session_modif_t *pdu = &resp->pduSessionMod[i];
+ asn1cSequenceAdd(pdu_mod_l->list, E1AP_PDU_Session_Resource_Modified_Item_t, iePdu);
+ iePdu->pDU_Session_ID = pdu->id;
+ if (pdu->numDRBModified > 0) {
+ iePdu->dRB_Modified_List_NG_RAN = calloc(1, sizeof(*iePdu->dRB_Modified_List_NG_RAN));
+ AssertFatal(iePdu->dRB_Modified_List_NG_RAN != NULL, "out of memory\n");
+ E1AP_DRB_Modified_List_NG_RAN_t *drb_mod_l = iePdu->dRB_Modified_List_NG_RAN;
+ for (int j = 0; j < pdu->numDRBModified; ++j) {
+ const DRB_nGRAN_modified_t *drb = &pdu->DRBnGRanModList[j];
+ asn1cSequenceAdd(drb_mod_l->list, E1AP_DRB_Modified_Item_NG_RAN_t, drb_mod);
+ drb_mod->dRB_ID = drb->id;
+ }
+ }
+ }
+}
+
+static int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, const e1ap_bearer_modif_resp_t *resp)
+{
+ E1AP_E1AP_PDU_t pdu = {0};
+ fill_BEARER_CONTEXT_MODIFICATION_RESPONSE(resp, &pdu);
+ return e1ap_encode_send(UPtype, assoc_id, &pdu, 0, __func__);
}
int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance) {
@@ -1159,7 +1261,7 @@ void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu,
const E1AP_BearerContextModificationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest;
E1AP_BearerContextModificationRequestIEs_t *ie;
- LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count);
+ LOG_D(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count);
for (int i=0; i < in->protocolIEs.list.count; i++) {
ie = in->protocolIEs.list.array[i];
@@ -1232,7 +1334,7 @@ void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu,
}
}
-int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
{
DevAssert(pdu != NULL);
DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage);
@@ -1242,17 +1344,91 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_upcp_inst_t *e1_ins
e1ap_bearer_setup_req_t bearerCxt = {0};
extract_BEARER_CONTEXT_MODIFICATION_REQUEST(pdu, &bearerCxt);
- CUUP_process_bearer_context_mod_req(e1_inst->instance, &bearerCxt);
+
+ e1_bearer_context_modif(&bearerCxt);
return 0;
}
-int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(instance_t instance,
- sctp_assoc_t assoc_id,
- uint32_t stream,
- E1AP_E1AP_PDU_t *pdu)
+static void extract_BEARER_CONTEXT_MODIFICATION_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_modif_resp_t *resp)
{
- AssertFatal(false,"Not implemented yet\n");
- return -1;
+ memset(resp, 0, sizeof(*resp));
+ 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];
+
+ switch (ie->id) {
+ case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID:
+ DevAssert(ie->criticality == E1AP_Criticality_reject);
+ DevAssert(ie->value.present == E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID);
+ resp->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID;
+ break;
+
+ case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID:
+ DevAssert(ie->criticality == E1AP_Criticality_reject);
+ DevAssert(ie->value.present == E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID);
+ resp->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID;
+ break;
+
+ 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.choice.System_BearerContextModificationResponse.present
+ == E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse);
+ E1AP_ProtocolIE_Container_4932P29_t *msgNGRAN_list =
+ (E1AP_ProtocolIE_Container_4932P29_t *)
+ ie->value.choice.System_BearerContextModificationResponse.choice.nG_RAN_BearerContextModificationResponse;
+ DevAssert(msgNGRAN_list->list.count == 1);
+ 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);
+ E1AP_PDU_Session_Resource_Modified_List_t *pduModifiedList = &msgNGRAN->value.choice.PDU_Session_Resource_Modified_List;
+ resp->numPDUSessionsMod = pduModifiedList->list.count;
+
+ for (int i=0; i < pduModifiedList->list.count; i++) {
+ pdu_session_modif_t *pduModified = &resp->pduSessionMod[i];
+ E1AP_PDU_Session_Resource_Modified_Item_t *mod_it = pduModifiedList->list.array[i];
+ pduModified->id = mod_it->pDU_Session_ID;
+
+ AssertFatal(mod_it->nG_DL_UP_TNL_Information == NULL, "not implemented\n");
+ AssertFatal(mod_it->securityResult == NULL, "not implemented\n");
+ AssertFatal(mod_it->pDU_Session_Data_Forwarding_Information_Response == NULL, "not implemented\n");
+ AssertFatal(mod_it->dRB_Setup_List_NG_RAN == NULL, "not implemented\n");
+ AssertFatal(mod_it->dRB_Failed_List_NG_RAN == NULL, "not implemented\n");
+ AssertFatal(mod_it->dRB_Failed_To_Modify_List_NG_RAN == NULL, "not implemented\n");
+
+ pduModified->numDRBModified = mod_it->dRB_Modified_List_NG_RAN->list.count;
+ for (int j=0; j < mod_it->dRB_Modified_List_NG_RAN->list.count; j++) {
+ DRB_nGRAN_modified_t *drbModified = &pduModified->DRBnGRanModList[j];
+ E1AP_DRB_Modified_Item_NG_RAN_t *drb = mod_it->dRB_Modified_List_NG_RAN->list.array[j];
+
+ drbModified->id = drb->dRB_ID;
+
+ AssertFatal(drb->uL_UP_Transport_Parameters == NULL, "not implemented\n");
+ AssertFatal(drb->pDCP_SN_Status_Information == NULL, "not implemented\n");
+ AssertFatal(drb->flow_Setup_List == NULL, "not implemented\n");
+ AssertFatal(drb->flow_Failed_List == NULL, "not implemented\n");
+ }
+ }
+ break;
+ }
+ }
+}
+
+int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
+{
+ DevAssert(pdu != NULL);
+ DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome);
+ 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);
+ itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
+ return 0;
}
int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance,
@@ -1295,7 +1471,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_CONFIRM(instance_t instance,
BEARER CONTEXT RELEASE
*/
-static int fill_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_setup_req_t *setupReq, e1ap_bearer_release_cmd_t *const cmd, E1AP_E1AP_PDU_t *pdu)
+static int fill_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_bearer_release_cmd_t *const cmd, E1AP_E1AP_PDU_t *pdu)
{
pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage;
asn1cCalloc(pdu->choice.initiatingMessage, msg);
@@ -1321,14 +1497,14 @@ static int fill_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_setup_req_t *setupReq, e1ap_
return 0;
}
-int e1apCUCP_send_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_setup_req_t *setupReq, e1ap_bearer_release_cmd_t *const cmd)
+int e1apCUCP_send_BEARER_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, e1ap_bearer_release_cmd_t *const cmd)
{
E1AP_E1AP_PDU_t pdu = {0};
- fill_BEARER_CONTEXT_RELEASE_COMMAND(setupReq, cmd, &pdu);
- return e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__);
+ fill_BEARER_CONTEXT_RELEASE_COMMAND(cmd, &pdu);
+ return e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__);
}
-int fill_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_setup_req_t *setupReq, e1ap_bearer_release_cmd_t *const cmd, E1AP_E1AP_PDU_t *pdu)
+static int fill_BEARER_CONTEXT_RELEASE_COMPLETE(const e1ap_bearer_release_cplt_t *cplt, E1AP_E1AP_PDU_t *pdu)
{
pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome;
asn1cCalloc(pdu->choice.successfulOutcome, msg);
@@ -1342,23 +1518,23 @@ int fill_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_setup_req_t *setupReq, e1ap_bearer
ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID;
ieC1->criticality = E1AP_Criticality_reject;
ieC1->value.present = E1AP_BearerContextReleaseCompleteIEs__value_PR_GNB_CU_CP_UE_E1AP_ID;
- ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = cmd->gNB_cu_cp_ue_id;
+ ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = cplt->gNB_cu_cp_ue_id;
/* mandatory */
/* c2. gNB-CU-UP UE E1AP ID */
asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextReleaseCompleteIEs_t, ieC2);
ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID;
ieC2->criticality = E1AP_Criticality_reject;
ieC2->value.present = E1AP_BearerContextReleaseCompleteIEs__value_PR_GNB_CU_UP_UE_E1AP_ID;
- ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = cmd->gNB_cu_cp_ue_id;
+ ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = cplt->gNB_cu_cp_ue_id;
return 0;
}
-int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *inst, e1ap_bearer_release_cmd_t *const cmd)
+int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, const e1ap_bearer_release_cplt_t *cplt)
{
E1AP_E1AP_PDU_t pdu = {0};
- fill_BEARER_CONTEXT_RELEASE_COMPLETE(&inst->setupReq, cmd, &pdu);
- return e1ap_encode_send(CPtype, &inst->setupReq, &pdu, 0, __func__);
+ fill_BEARER_CONTEXT_RELEASE_COMPLETE(cplt, &pdu);
+ return e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__);
}
int e1apCUUP_send_BEARER_CONTEXT_RELEASE_REQUEST(instance_t instance) {
@@ -1371,7 +1547,7 @@ void extract_BEARER_CONTEXT_RELEASE_COMMAND(const E1AP_E1AP_PDU_t *pdu,
const E1AP_BearerContextReleaseCommand_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextReleaseCommand;
E1AP_BearerContextReleaseCommandIEs_t *ie;
- LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count);
+ LOG_D(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count);
for (int i=0; i < in->protocolIEs.list.count; i++) {
ie = in->protocolIEs.list.array[i];
@@ -1405,7 +1581,7 @@ void extract_BEARER_CONTEXT_RELEASE_COMMAND(const E1AP_E1AP_PDU_t *pdu,
}
}
-int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
{
DevAssert(pdu != NULL);
DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage);
@@ -1415,16 +1591,16 @@ int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_upcp_inst_t *e1_inst, co
e1ap_bearer_release_cmd_t bearerCxt = {0};
extract_BEARER_CONTEXT_RELEASE_COMMAND(pdu, &bearerCxt);
- CUUP_process_bearer_release_command(e1_inst->instance, &bearerCxt);
+ e1_bearer_release_cmd(&bearerCxt);
return 0;
}
void extract_BEARER_CONTEXT_RELEASE_COMPLETE(const E1AP_E1AP_PDU_t *pdu,
- e1ap_bearer_release_cmd_t *bearerCxt) {
+ e1ap_bearer_release_cplt_t *bearerCxt) {
const E1AP_BearerContextReleaseComplete_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextReleaseComplete;
E1AP_BearerContextReleaseCompleteIEs_t *ie;
- LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count);
+ LOG_D(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count);
for (int i=0; i < in->protocolIEs.list.count; i++) {
ie = in->protocolIEs.list.array[i];
@@ -1449,7 +1625,7 @@ void extract_BEARER_CONTEXT_RELEASE_COMPLETE(const E1AP_E1AP_PDU_t *pdu,
}
}
-int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
{
DevAssert(pdu != NULL);
DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome);
@@ -1457,9 +1633,12 @@ int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *e1_inst, c
DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject);
DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_BearerContextReleaseComplete);
- e1ap_bearer_release_cmd_t bearerCxt = {0};
+ e1ap_bearer_release_cplt_t bearerCxt = {0};
extract_BEARER_CONTEXT_RELEASE_COMPLETE(pdu, &bearerCxt);
- //TODO: CUCP_process_bearer_release_complete(&beareCxt, instance);
+ MessageDef *msg = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_RELEASE_CPLT);
+ e1ap_bearer_release_cplt_t *cplt = &E1AP_BEARER_CONTEXT_RELEASE_CPLT(msg);
+ *cplt = bearerCxt;
+ itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
return 0;
}
@@ -1519,32 +1698,31 @@ static instance_t cuup_task_create_gtpu_instance_to_du(eth_params_t *IPaddrs) {
openAddr_t tmp= {0};
strncpy(tmp.originHost, IPaddrs->my_addr, sizeof(tmp.originHost)-1);
sprintf(tmp.originService, "%d", IPaddrs->my_portd);
+ sprintf(tmp.destinationService, "%d", IPaddrs->remote_portd);
return gtpv1Init(tmp);
}
-static void e1_task_send_sctp_association_req(long task_id, instance_t instance, e1ap_setup_req_t *e1ap_setup_req)
+static void e1_task_send_sctp_association_req(long task_id, instance_t instance, e1ap_net_config_t *e1ap_nc)
{
- DevAssert(e1ap_setup_req != NULL);
+ DevAssert(e1ap_nc != NULL);
getCxtE1(instance)->sockState = SCTP_STATE_CLOSED;
MessageDef *message_p = itti_alloc_new_message(task_id, 0, SCTP_NEW_ASSOCIATION_REQ);
sctp_new_association_req_t *sctp_new_req = &message_p->ittiMsg.sctp_new_association_req;
sctp_new_req->ulp_cnx_id = instance;
sctp_new_req->port = E1AP_PORT_NUMBER;
sctp_new_req->ppid = E1AP_SCTP_PPID;
- sctp_new_req->in_streams = e1ap_setup_req->sctp_in_streams;
- sctp_new_req->out_streams = e1ap_setup_req->sctp_out_streams;
// remote
- sctp_new_req->remote_address = e1ap_setup_req->CUCP_e1_ip_address;
+ sctp_new_req->remote_address = e1ap_nc->CUCP_e1_ip_address;
// local
- sctp_new_req->local_address = e1ap_setup_req->CUUP_e1_ip_address;
+ sctp_new_req->local_address = e1ap_nc->CUUP_e1_ip_address;
itti_send_msg_to_task(TASK_SCTP, instance, message_p);
}
-static void e1apCUUP_send_SETUP_REQUEST(e1ap_setup_req_t *setup)
+static void e1apCUUP_send_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_setup_req_t *setup)
{
E1AP_E1AP_PDU_t pdu = {0};
fill_SETUP_REQUEST(setup, &pdu);
- e1ap_encode_send(UPtype, setup, &pdu, 0, __func__);
+ e1ap_encode_send(UPtype, assoc_id, &pdu, 0, __func__);
}
static void e1_task_handle_sctp_association_resp(E1_t type, instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp)
@@ -1562,15 +1740,14 @@ static void e1_task_handle_sctp_association_resp(E1_t type, instance_t instance,
}
if (type == UPtype) {
- e1ap_setup_req_t *e1ap_cuup_setup_req = &getCxtE1(instance)->setupReq;
- e1ap_cuup_setup_req->assoc_id = sctp_new_association_resp->assoc_id;
- e1ap_cuup_setup_req->sctp_in_streams = sctp_new_association_resp->in_streams;
- e1ap_cuup_setup_req->sctp_out_streams = sctp_new_association_resp->out_streams;
- e1ap_cuup_setup_req->default_sctp_stream_id = 0;
+ e1ap_upcp_inst_t *inst = getCxtE1(instance);
+ inst->cuup.assoc_id = sctp_new_association_resp->assoc_id;
- eth_params_t IPaddr;
- IPaddr.my_addr = e1ap_cuup_setup_req->localAddressF1U;
- IPaddr.my_portd = e1ap_cuup_setup_req->localPortF1U;
+ e1ap_net_config_t *nc = &inst->net_config;
+ eth_params_t IPaddr = {0};
+ IPaddr.my_addr = nc->localAddressF1U;
+ IPaddr.my_portd = nc->localPortF1U;
+ IPaddr.remote_portd = nc->remotePortF1U;
if (getCxtE1(instance)->gtpInstF1U < 0)
getCxtE1(instance)->gtpInstF1U = cuup_task_create_gtpu_instance_to_du(&IPaddr);
if (getCxtE1(instance)->gtpInstF1U < 0)
@@ -1578,18 +1755,18 @@ static void e1_task_handle_sctp_association_resp(E1_t type, instance_t instance,
extern instance_t CUuniqInstance;
CUuniqInstance = getCxtE1(instance)->gtpInstF1U;
cuup_init_n3(instance);
- e1apCUUP_send_SETUP_REQUEST(&getCxtE1(instance)->setupReq);
+ e1apCUUP_send_SETUP_REQUEST(inst->cuup.assoc_id, &inst->cuup.setupReq);
}
}
void cuup_init_n3(instance_t instance)
{
if (getCxtE1(instance)->gtpInstN3 < 0) {
- e1ap_setup_req_t *setup = &getCxtE1(instance)->setupReq;
+ e1ap_net_config_t *nc = &getCxtE1(instance)->net_config;
openAddr_t tmp = {0};
- strcpy(tmp.originHost, setup->localAddressN3);
- sprintf(tmp.originService, "%d", setup->localPortN3);
- sprintf(tmp.destinationService, "%d", setup->remotePortN3);
+ strcpy(tmp.originHost, nc->localAddressN3);
+ sprintf(tmp.originService, "%d", nc->localPortN3);
+ sprintf(tmp.destinationService, "%d", nc->remotePortN3);
LOG_I(GTPU, "Configuring GTPu address : %s, port : %s\n", tmp.originHost, tmp.originService);
// Fixme: fully inconsistent instances management
// dirty global var is a bad fix
@@ -1623,24 +1800,19 @@ void cucp_task_send_sctp_init_req(instance_t instance, char *my_addr) {
void e1_task_handle_sctp_association_ind(E1_t type, instance_t instance, sctp_new_association_ind_t *sctp_new_ind)
{
- if (getCxtE1(instance))
- LOG_W(E1AP, "CUCP incoming call, re-use older socket context, finish implementation required\n");
- else
- createE1inst(type, instance, NULL);
- getCxtE1(instance)->sockState = SCTP_STATE_ESTABLISHED;
- getCxtE1(instance)->incoming_sock = true;
- e1ap_setup_req_t *setup_req = &getCxtE1(instance)->setupReq;
- setup_req->assoc_id = sctp_new_ind->assoc_id;
- setup_req->sctp_in_streams = sctp_new_ind->in_streams;
- setup_req->sctp_out_streams = sctp_new_ind->out_streams;
- setup_req->default_sctp_stream_id = 0;
+ if (!getCxtE1(instance))
+ createE1inst(type, instance, NULL, NULL);
+ e1ap_upcp_inst_t *inst = getCxtE1(instance);
+ inst->sockState = SCTP_STATE_ESTABLISHED;
+ if (type == UPtype)
+ inst->cuup.assoc_id = sctp_new_ind->assoc_id;
}
void e1apHandleTimer(instance_t myInstance)
{
LOG_W(E1AP, "Try to reconnect to CP\n");
if (getCxtE1(myInstance)->sockState != SCTP_STATE_ESTABLISHED)
- e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, &getCxtE1(myInstance)->setupReq);
+ e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, &getCxtE1(myInstance)->net_config);
}
void *E1AP_CUCP_task(void *arg) {
@@ -1653,7 +1825,8 @@ void *E1AP_CUCP_task(void *arg) {
itti_receive_msg(TASK_CUCP_E1, &msg);
instance_t myInstance=ITTI_MSG_DESTINATION_INSTANCE(msg);
const int msgType = ITTI_MSG_ID(msg);
- LOG_I(E1AP, "CUCP received %s for instance %ld\n", messages_info[msgType].name, myInstance);
+ LOG_D(E1AP, "CUCP received %s for instance %ld\n", messages_info[msgType].name, myInstance);
+ sctp_assoc_t assoc_id = msg->ittiMsgHeader.originInstance;
switch (ITTI_MSG_ID(msg)) {
case SCTP_NEW_ASSOCIATION_IND:
@@ -1664,29 +1837,37 @@ void *E1AP_CUCP_task(void *arg) {
e1_task_handle_sctp_association_resp(CPtype, ITTI_MSG_ORIGIN_INSTANCE(msg), &msg->ittiMsg.sctp_new_association_resp);
break;
- case E1AP_SETUP_REQ: {
- e1ap_setup_req_t *req = &E1AP_SETUP_REQ(msg);
- if (req->CUCP_e1_ip_address.ipv4 == 0) {
- LOG_E(E1AP, "No IPv4 address configured\n");
- return NULL;
- }
- cucp_task_send_sctp_init_req(0, req->CUCP_e1_ip_address.ipv4_address);
+ case E1AP_REGISTER_REQ: {
+ // note: we use E1AP_REGISTER_REQ only to set up sockets, the
+ // E1AP_SETUP_REQ is not used and comes through the socket from the
+ // CU-UP later!
+ e1ap_net_config_t *nc = &E1AP_REGISTER_REQ(msg).net_config;
+ AssertFatal(nc->CUCP_e1_ip_address.ipv4 != 0, "No IPv4 address configured\n");
+ cucp_task_send_sctp_init_req(0, nc->CUCP_e1_ip_address.ipv4_address);
} break;
+ case E1AP_SETUP_REQ:
+ AssertFatal(false, "should not receive E1AP_SETUP_REQ in CU-CP!\n");
+ break;
+
case SCTP_DATA_IND:
e1_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind);
break;
case E1AP_SETUP_RESP:
- e1ap_send_SETUP_RESPONSE(myInstance, &E1AP_SETUP_RESP(msg));
+ e1ap_send_SETUP_RESPONSE(assoc_id, &E1AP_SETUP_RESP(msg));
break;
case E1AP_BEARER_CONTEXT_SETUP_REQ:
- e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(myInstance, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg));
+ e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg));
break;
case E1AP_BEARER_CONTEXT_MODIFICATION_REQ:
- e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(myInstance, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg));
+ e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg));
+ break;
+
+ case E1AP_BEARER_CONTEXT_RELEASE_CMD:
+ e1apCUCP_send_BEARER_CONTEXT_RELEASE_COMMAND(assoc_id, &E1AP_BEARER_CONTEXT_RELEASE_CMD(msg));
break;
default:
@@ -1712,13 +1893,12 @@ void *E1AP_CUUP_task(void *arg) {
itti_receive_msg(TASK_CUUP_E1, &msg);
const instance_t myInstance = ITTI_MSG_DESTINATION_INSTANCE(msg);
const int msgType = ITTI_MSG_ID(msg);
- LOG_I(E1AP, "CUUP received %s for instance %ld\n", messages_info[msgType].name, myInstance);
+ LOG_D(E1AP, "CUUP received %s for instance %ld\n", messages_info[msgType].name, myInstance);
switch (msgType) {
- case E1AP_SETUP_REQ: {
- e1ap_setup_req_t *msgSetup = &E1AP_SETUP_REQ(msg);
- createE1inst(UPtype, myInstance, msgSetup);
-
- e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, msgSetup);
+ case E1AP_REGISTER_REQ: {
+ e1ap_register_req_t *reg_req = &E1AP_REGISTER_REQ(msg);
+ createE1inst(UPtype, myInstance, ®_req->net_config, ®_req->setup_req);
+ e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, ®_req->net_config);
} break;
case SCTP_NEW_ASSOCIATION_RESP:
@@ -1733,6 +1913,27 @@ void *E1AP_CUUP_task(void *arg) {
e1apHandleTimer(myInstance);
break;
+ case E1AP_BEARER_CONTEXT_SETUP_RESP: {
+ const e1ap_bearer_setup_resp_t *resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg);
+ const e1ap_upcp_inst_t *inst = getCxtE1(myInstance);
+ AssertFatal(inst != NULL, "no E1 instance found for instance %ld\n", myInstance);
+ e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(inst->cuup.assoc_id, resp);
+ } break;
+
+ case E1AP_BEARER_CONTEXT_MODIFICATION_RESP: {
+ const e1ap_bearer_modif_resp_t *resp = &E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg);
+ const e1ap_upcp_inst_t *inst = getCxtE1(myInstance);
+ AssertFatal(inst != NULL, "no E1 instance found for instance %ld\n", myInstance);
+ e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_RESPONSE(inst->cuup.assoc_id, resp);
+ } break;
+
+ case E1AP_BEARER_CONTEXT_RELEASE_CPLT: {
+ const e1ap_bearer_release_cplt_t *cplt = &E1AP_BEARER_CONTEXT_RELEASE_CPLT(msg);
+ const e1ap_upcp_inst_t *inst = getCxtE1(myInstance);
+ AssertFatal(inst != NULL, "no E1 instance found for instance %ld\n", myInstance);
+ e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(inst->cuup.assoc_id, cplt);
+ } break;
+
default:
LOG_E(E1AP, "Unknown message received in TASK_CUUP_E1\n");
break;
diff --git a/openair2/E1AP/e1ap.h b/openair2/E1AP/e1ap.h
index af1dcae363..b41559de09 100644
--- a/openair2/E1AP/e1ap.h
+++ b/openair2/E1AP/e1ap.h
@@ -28,27 +28,29 @@
#include "e1ap_asnc.h"
#include "openair2/E1AP/e1ap_common.h"
-int e1apCUCP_handle_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUCP_handle_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
-int e1apCUUP_handle_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUUP_handle_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
-int e1apCUUP_handle_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUUP_handle_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
-int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
-int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
-int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
-int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
-void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, e1ap_bearer_setup_resp_t *const resp);
+int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu);
-int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, const e1ap_bearer_setup_resp_t *resp);
-int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
-int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *inst, e1ap_bearer_release_cmd_t *const cmd);
+int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+
+int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, const e1ap_bearer_release_cplt_t *cplt);
void *E1AP_CUUP_task(void *arg);
diff --git a/openair2/E1AP/e1ap_api.c b/openair2/E1AP/e1ap_api.c
deleted file mode 100644
index 9cec6b69f3..0000000000
--- a/openair2/E1AP/e1ap_api.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The OpenAirInterface Software Alliance licenses this file to You under
- * the OAI Public License, Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.openairinterface.org/?page_id=698
- *
- * Author and copyright: Laurent Thomas, open-cells.com
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *-------------------------------------------------------------------------------
- * For more information about the OpenAirInterface (OAI) Software Alliance:
- * contact@openairinterface.org
- */
-
-#include
-#include "e1ap_api.h"
-
-#include "nr_pdcp/nr_pdcp_entity.h"
-#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
-#include "openair2/RRC/NR/cucp_cuup_if.h"
-#include "openair2/RRC/LTE/MESSAGES/asn1_msg.h"
-#include "openair3/SECU/key_nas_deriver.h"
-#include "openair3/ocp-gtpu/gtp_itf.h"
-#include "openair2/F1AP/f1ap_ids.h"
-#include "e1ap_asnc.h"
-#include "e1ap_common.h"
-#include "e1ap.h"
-
-struct NR_DRB_ToAddMod;
-static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, pdu_session_to_setup_t *pdu) {
-
- for (int i=0; i < pdu->numDRB2Setup; i++) {
- DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i;
- asn1cSequenceAdd(DRB_configList->list, struct NR_DRB_ToAddMod, ie);
- ie->drb_Identity = drb->id;
- ie->cnAssociation = CALLOC(1, sizeof(*ie->cnAssociation));
- ie->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config;
-
- // 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;
-
- asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd);
- for (int j=0; j < drb->numQosFlow2Setup; j++) {
- asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, qfi);
- *qfi = drb->qosFlows[j].fiveQI;
- }
- sdap_config->mappedQoS_FlowsToRelease = NULL;
-
- // pdcp_Config
- ie->reestablishPDCP = NULL;
- 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);
- 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->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);
- }
- }
-}
-
-static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t * const req,
- gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp,
- instance_t instance) {
-
- gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0};
-
- NR_DRB_ToAddModList_t DRB_configList = {0};
- for (int i=0; i < req->numPDUSessions; i++) {
- pdu_session_to_setup_t *const pdu = &req->pduSession[i];
- create_tunnel_req.pdusession_id[i] = pdu->sessionId;
- create_tunnel_req.incoming_rb_id[i] = pdu->DRBnGRanList[0].id; // taking only the first DRB. TODO:change this
- memcpy(&create_tunnel_req.dst_addr[i].buffer,
- &pdu->tlAddress,
- sizeof(uint8_t)*4);
- create_tunnel_req.dst_addr[i].length = 32; // 8bits * 4bytes
- create_tunnel_req.outgoing_teid[i] = pdu->teId;
- fill_DRB_configList_e1(&DRB_configList, pdu);
- }
- create_tunnel_req.num_tunnels = req->numPDUSessions;
- create_tunnel_req.ue_id = req->gNB_cu_cp_ue_id;
-
- // Create N3 tunnel
- int ret = gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, create_tunnel_resp, nr_pdcp_data_req_drb, sdap_data_req);
- if (ret != 0) {
- LOG_E(NR_RRC,
- "drb_config_N3gtpu_create=>gtpv1u_create_ngu_tunnel failed, cannot set up GTP tunnel for data transmissions of UE %ld\n",
- create_tunnel_req.ue_id);
- return ret;
- }
-
- // Configure DRBs
- nr_pdcp_e1_add_drbs(true, // set this to notify PDCP that his not UE
- create_tunnel_req.ue_id,
- &DRB_configList,
- (req->integrityProtectionAlgorithm << 4) | req->cipheringAlgorithm,
- (uint8_t *)req->encryptionKey,
- (uint8_t *)req->integrityProtectionKey);
- return ret;
-}
-
-void process_e1_bearer_context_setup_req(instance_t instance, e1ap_bearer_setup_req_t *const req)
-{
- e1ap_upcp_inst_t *inst = getCxtE1(instance);
- AssertFatal(inst, "");
- gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp_N3={0};
-
- uint32_t gNB_cu_up_ue_id = req ->gNB_cu_cp_ue_id;
- LOG_I(E1AP, "adding UE with CU-CP UE ID %d and CU-UP UE ID %d\n", req->gNB_cu_cp_ue_id, gNB_cu_up_ue_id);
- f1_ue_data_t ue_data = {.secondary_ue = req->gNB_cu_cp_ue_id};
- cu_add_f1_ue_data(gNB_cu_up_ue_id, &ue_data);
-
- // GTP tunnel for UL
- drb_config_N3gtpu_create(req, &create_tunnel_resp_N3, inst->gtpInstN3);
-
- MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP);
- e1ap_bearer_setup_resp_t *resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg);
-
- in_addr_t my_addr;
- if (inet_pton(AF_INET, inst->setupReq.localAddressF1U, &my_addr) != 1)
- LOG_E(E1AP, "can't use the F1-U local interface: %s\n", inst->setupReq.localAddressF1U);
- fill_e1ap_bearer_setup_resp(resp, req, inst->gtpInstF1U, req->gNB_cu_cp_ue_id, inst->setupReq.remotePortF1U, my_addr);
-
- resp->gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id;
- resp->gNB_cu_up_ue_id = gNB_cu_up_ue_id;
- resp->numPDUSessions = req->numPDUSessions;
- for (int i=0; i < req->numPDUSessions; i++) {
- pdu_session_setup_t *pduSetup = resp->pduSession + i;
- pdu_session_to_setup_t *pdu2Setup = req->pduSession + i;
-
- pduSetup->id = pdu2Setup->sessionId;
- if (inet_pton(AF_INET, inst->setupReq.localAddressN3, &pduSetup->tlAddress) != 1)
- LOG_E(E1AP, "can't use the N3 local interface: %s\n", inst->setupReq.localAddressN3);
- pduSetup->teId = create_tunnel_resp_N3.gnb_NGu_teid[i];
- pduSetup->numDRBSetup = pdu2Setup->numDRB2Setup;
-
- // At this point we don't have a way to know the DRBs that failed to setup
- // We assume all DRBs to setup have are setup successfully so we always send successful outcome in response
- // TODO: Modify nr_pdcp_add_drbs() to return DRB list that failed to setup to support E1AP
- pduSetup->numDRBFailed = 0;
- }
-
- e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(inst, resp);
-}
-
-void CUUP_process_bearer_context_mod_req(instance_t instance, e1ap_bearer_setup_req_t *const req)
-{
- e1ap_upcp_inst_t *inst = getCxtE1(instance);
- AssertFatal(inst, "");
- // assume we receive modification of F1-U but it is wrong, we can also get modification of N3 when HO will occur
- CU_update_UP_DL_tunnel(req, inst->gtpInstF1U, req->gNB_cu_cp_ue_id);
- // TODO: send bearer cxt mod response
-}
-
-void CUUP_process_bearer_release_command(instance_t instance, e1ap_bearer_release_cmd_t *const cmd)
-{
- e1ap_upcp_inst_t *inst = getCxtE1(instance);
- AssertFatal(inst, "");
- newGtpuDeleteAllTunnels(inst->gtpInstN3, cmd->gNB_cu_up_ue_id);
- newGtpuDeleteAllTunnels(inst->gtpInstF1U, cmd->gNB_cu_up_ue_id);
- e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(inst, cmd);
-}
diff --git a/openair2/E1AP/e1ap_asnc.h b/openair2/E1AP/e1ap_asnc.h
index 00dbcc13f3..ed5d1817a8 100644
--- a/openair2/E1AP/e1ap_asnc.h
+++ b/openair2/E1AP/e1ap_asnc.h
@@ -47,10 +47,14 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -61,5 +65,7 @@
#include
#include
#include
+#include
+#include
#endif
diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c
index caf97b680d..cf8982339d 100644
--- a/openair2/E1AP/e1ap_common.c
+++ b/openair2/E1AP/e1ap_common.c
@@ -37,18 +37,19 @@ e1ap_upcp_inst_t *getCxtE1(instance_t instance)
return e1ap_inst[instance];
}
-int e1ap_assoc_id(E1_t type, instance_t instance) {
- AssertFatal(e1ap_inst[instance] != NULL, "Trying to access uninitiated instance of CUCP\n");
- return e1ap_inst[instance]->setupReq.assoc_id;
-}
-
-void createE1inst(E1_t type, instance_t instance, e1ap_setup_req_t *req) {
+void createE1inst(E1_t type, instance_t instance, e1ap_net_config_t *nc, e1ap_setup_req_t *req)
+{
AssertFatal(e1ap_inst[instance] == NULL, "Double call to E1 instance %d\n", (int)instance);
e1ap_inst[instance] = calloc(1, sizeof(e1ap_upcp_inst_t));
e1ap_inst[instance]->type = type;
e1ap_inst[instance]->instance = instance;
- if (req)
- memcpy(&e1ap_inst[instance]->setupReq, req, sizeof(*req));
+ e1ap_inst[instance]->cuup.assoc_id = -1;
+ if (nc)
+ memcpy(&e1ap_inst[instance]->net_config, nc, sizeof(*nc));
+ if (req) {
+ AssertFatal(type == UPtype, "E1 setup request only to be stored for CU-UP\n");
+ memcpy(&e1ap_inst[instance]->cuup.setupReq, req, sizeof(*req));
+ }
e1ap_inst[instance]->gtpInstN3 = -1;
e1ap_inst[instance]->gtpInstF1U = -1;
}
@@ -59,8 +60,8 @@ void e1ap_common_init() {
srand(time(NULL));
}
-bool check_transac_id(E1AP_TransactionID_t id, int *freeIdx) {
-
+static bool check_transac_id(E1AP_TransactionID_t id, int *freeIdx)
+{
bool isFreeIdxSet = false;
for (int i=0; i < E1AP_MAX_NUM_TRANSAC_IDS; i++) {
if (id == transacID[i])
@@ -74,10 +75,10 @@ bool check_transac_id(E1AP_TransactionID_t id, int *freeIdx) {
return true;
}
-E1AP_TransactionID_t E1AP_get_next_transaction_identifier() {
+long E1AP_get_next_transaction_identifier() {
E1AP_TransactionID_t genTransacId;
bool isTransacIdValid = false;
- int freeIdx;
+ int freeIdx = 0;
while (!isTransacIdValid) {
genTransacId = rand() & 255;
@@ -89,7 +90,7 @@ E1AP_TransactionID_t E1AP_get_next_transaction_identifier() {
return genTransacId;
}
-void E1AP_free_transaction_identifier(E1AP_TransactionID_t id) {
+void E1AP_free_transaction_identifier(long id) {
for (int i=0; i < E1AP_MAX_NUM_TRANSAC_IDS; i++) {
if (id == transacID[i]) {
@@ -116,6 +117,9 @@ int e1ap_decode_initiating_message(E1AP_E1AP_PDU_t *pdu) {
case E1AP_ProcedureCode_id_bearerContextModification:
break;
+ case E1AP_ProcedureCode_id_bearerContextRelease:
+ break;
+
default:
LOG_E(E1AP, "Unsupported procedure code (%d) for initiating message\n",
(int)pdu->choice.initiatingMessage->procedureCode);
@@ -133,6 +137,12 @@ int e1ap_decode_successful_outcome(E1AP_E1AP_PDU_t *pdu) {
case E1AP_ProcedureCode_id_bearerContextSetup:
break;
+ case E1AP_ProcedureCode_id_bearerContextModification:
+ break;
+
+ case E1AP_ProcedureCode_id_bearerContextRelease:
+ break;
+
default:
LOG_E(E1AP, "Unsupported procedure code (%d) for successful message\n",
(int)pdu->choice.successfulOutcome->procedureCode);
@@ -195,7 +205,7 @@ int e1ap_decode_pdu(E1AP_E1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t
return -1;
}
-int e1ap_encode_send(E1_t type, e1ap_setup_req_t *setupReq, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func)
+int e1ap_encode_send(E1_t type, sctp_assoc_t assoc_id, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func)
{
DevAssert(pdu != NULL);
@@ -223,11 +233,11 @@ int e1ap_encode_send(E1_t type, e1ap_setup_req_t *setupReq, E1AP_E1AP_PDU_t *pdu
}
MessageDef *message = itti_alloc_new_message((type == CPtype) ? TASK_CUCP_E1 : TASK_CUUP_E1, 0, SCTP_DATA_REQ);
sctp_data_req_t *s = &message->ittiMsg.sctp_data_req;
- s->assoc_id = setupReq->assoc_id;
+ s->assoc_id = assoc_id;
s->buffer = buffer;
s->buffer_length = encoded;
s->stream = stream;
- LOG_I(E1AP, "%s: Sending ITTI message to SCTP Task\n", func);
+ LOG_D(E1AP, "%s: Sending ITTI message to SCTP Task\n", func);
itti_send_msg_to_task(TASK_SCTP, 0 /*unused by callee*/, message);
return encoded;
diff --git a/openair2/E1AP/e1ap_common.h b/openair2/E1AP/e1ap_common.h
index cddf5b9ea6..e0aea6990f 100644
--- a/openair2/E1AP/e1ap_common.h
+++ b/openair2/E1AP/e1ap_common.h
@@ -24,41 +24,39 @@
#ifndef E1AP_COMMON_H_
#define E1AP_COMMON_H_
#include "openair2/COMMON/e1ap_messages_types.h"
-#include "e1ap_asnc.h"
#include "openair2/COMMON/sctp_messages_types.h"
#include "common/ngran_types.h"
typedef struct e1ap_upcp_inst_s {
- bool incoming_sock;
instance_t instance;
- bool same_process;
E1_t type;
enum sctp_state_e sockState;
- sctp_assoc_t assoc_id;
+ struct {
+ sctp_assoc_t assoc_id;
+ e1ap_setup_req_t setupReq;
+ } cuup;
instance_t gtpInstN3;
instance_t gtpInstF1U;
- e1ap_setup_req_t setupReq;
- e1ap_bearer_setup_req_t bearerSetupReq;
- e1ap_bearer_setup_resp_t bearerSetupResp;
+ e1ap_net_config_t net_config;
} e1ap_upcp_inst_t;
extern int asn1_xer_print;
-int e1ap_decode_pdu(E1AP_E1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length);
+// forward declaration so we don't require E1AP ASN.1 when including this
+// header
+struct E1AP_E1AP_PDU;
+int e1ap_decode_pdu(struct E1AP_E1AP_PDU *pdu, const uint8_t *const buffer, uint32_t length);
e1ap_upcp_inst_t *getCxtE1(instance_t instance);
-E1AP_TransactionID_t E1AP_get_next_transaction_identifier();
+long E1AP_get_next_transaction_identifier();
+void E1AP_free_transaction_identifier(long id);
-void createE1inst(E1_t type, instance_t instance, e1ap_setup_req_t *req);
+void createE1inst(E1_t type, instance_t instance, e1ap_net_config_t *nc, e1ap_setup_req_t *req);
-bool check_transac_id(E1AP_TransactionID_t id, int *freeIdx);
-
-int e1ap_assoc_id(E1_t type, instance_t instance);
-
-int e1ap_encode_send(E1_t type, e1ap_setup_req_t *setupReq, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func);
+int e1ap_encode_send(E1_t type, sctp_assoc_t assoc_id, struct E1AP_E1AP_PDU *pdu, uint16_t stream, const char *func);
void e1ap_common_init();
+void cuup_init_n3(instance_t instance);
-void E1AP_free_transaction_identifier(E1AP_TransactionID_t id);
#endif /* E1AP_COMMON_H_ */
diff --git a/openair2/E1AP/e1ap_setup.c b/openair2/E1AP/e1ap_setup.c
index da643636fc..f2b9d05503 100644
--- a/openair2/E1AP/e1ap_setup.c
+++ b/openair2/E1AP/e1ap_setup.c
@@ -68,7 +68,7 @@ static void get_NGU_S1U_addr(char **addr, uint16_t *port)
MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process)
{
- MessageDef *msgConfig = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_SETUP_REQ);
+ MessageDef *msgConfig = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_REGISTER_REQ);
if (!msgConfig)
return NULL;
@@ -85,9 +85,11 @@ MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process)
config_getlist(&GNBParamList, GNBParams, sizeofArray(GNBParams), NULL);
paramdef_t *gnbParms = GNBParamList.paramarray[0];
AssertFatal(gnbParms[GNB_GNB_ID_IDX].uptr != NULL, "gNB id %d is not defined in configuration file\n", 0);
- e1ap_setup_req_t *e1Setup = &E1AP_SETUP_REQ(msgConfig);
+ e1ap_setup_req_t *e1Setup = &E1AP_REGISTER_REQ(msgConfig).setup_req;
msgConfig->ittiMsgHeader.destinationInstance = 0;
e1Setup->gNB_cu_up_id = *(gnbParms[GNB_GNB_ID_IDX].uptr);
+ if (*gnbParms[GNB_GNB_NAME_IDX].strptr)
+ e1Setup->gNB_cu_up_name = *(gnbParms[GNB_GNB_NAME_IDX].strptr);
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
@@ -102,27 +104,41 @@ MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process)
e1Setup->supported_plmns = numPLMNs;
for (int I = 0; I < numPLMNs; I++) {
- e1Setup->plmns[I].mcc = *PLMNParamList.paramarray[I][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
- e1Setup->plmns[I].mnc = *PLMNParamList.paramarray[I][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
- e1Setup->plmns[I].mnc = *PLMNParamList.paramarray[I][GNB_MNC_DIGIT_LENGTH].u8ptr;
+ e1Setup->plmn[I].id.mcc = *PLMNParamList.paramarray[I][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
+ e1Setup->plmn[I].id.mnc = *PLMNParamList.paramarray[I][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
+ e1Setup->plmn[I].id.mnc_digit_length = *PLMNParamList.paramarray[I][GNB_MNC_DIGIT_LENGTH].uptr;
+
+ char snssaistr[MAX_OPTNAME_SIZE*2 + 8];
+ sprintf(snssaistr, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_PLMN_LIST, I);
+ paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0};
+ paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC;
+ config_getlist(&SNSSAIParamList, SNSSAIParams, sizeof(SNSSAIParams)/sizeof(paramdef_t), snssaistr);
+ e1Setup->plmn[I].supported_slices = SNSSAIParamList.numelt;
+ e1Setup->plmn[I].slice = calloc(SNSSAIParamList.numelt, sizeof(*e1Setup->plmn[I].slice));
+ AssertFatal(e1Setup->plmn[I].slice != NULL, "out of memory\n");
+ for (int s = 0; s < SNSSAIParamList.numelt; ++s) {
+ e1ap_nssai_t *slice = &e1Setup->plmn[I].slice[s];
+ slice->sst = *SNSSAIParamList.paramarray[s][GNB_SLICE_SERVICE_TYPE_IDX].uptr;
+ slice->sd = *SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr;
+ }
}
- e1Setup->remotePortF1U = *(GNBParamList.paramarray[0][GNB_REMOTE_S_PORTD_IDX].uptr);
- e1Setup->localAddressF1U = strdup(*(GNBParamList.paramarray[0][GNB_LOCAL_S_ADDRESS_IDX].strptr));
- e1Setup->localPortF1U = *(GNBParamList.paramarray[0][GNB_LOCAL_S_PORTD_IDX].uptr);
- get_NGU_S1U_addr(&e1Setup->localAddressN3, &e1Setup->localPortN3);
- e1Setup->remotePortN3 = e1Setup->localPortN3 ;
+ e1ap_net_config_t *e1ap_nc = &E1AP_REGISTER_REQ(msgConfig).net_config;
+ e1ap_nc->remotePortF1U = *(GNBParamList.paramarray[0][GNB_REMOTE_S_PORTD_IDX].uptr);
+ e1ap_nc->localAddressF1U = strdup(*(GNBParamList.paramarray[0][GNB_LOCAL_S_ADDRESS_IDX].strptr));
+ e1ap_nc->localPortF1U = *(GNBParamList.paramarray[0][GNB_LOCAL_S_PORTD_IDX].uptr);
+ get_NGU_S1U_addr(&e1ap_nc->localAddressN3, &e1ap_nc->localPortN3);
+ e1ap_nc->remotePortN3 = e1ap_nc->localPortN3 ;
if (separate_CUUP_process) {
paramlist_def_t GNBE1ParamList = {GNB_CONFIG_STRING_E1_PARAMETERS, NULL, 0};
paramdef_t GNBE1Params[] = GNBE1PARAMS_DESC;
config_getlist(&GNBE1ParamList, GNBE1Params, sizeofArray(GNBE1Params), aprefix);
paramdef_t *e1Parms = GNBE1ParamList.paramarray[0];
- strcpy(e1Setup->CUCP_e1_ip_address.ipv4_address, *(e1Parms[GNB_CONFIG_E1_IPV4_ADDRESS_CUCP].strptr));
- e1Setup->CUCP_e1_ip_address.ipv4 = 1;
- strcpy(e1Setup->CUUP_e1_ip_address.ipv4_address, *(e1Parms[GNB_CONFIG_E1_IPV4_ADDRESS_CUUP].strptr));
- e1Setup->CUUP_e1_ip_address.ipv4 = 1;
- e1Setup->cn_support = *e1Parms[GNB_CONFIG_E1_CN_SUPPORT].uptr;
+ strcpy(e1ap_nc->CUCP_e1_ip_address.ipv4_address, *(e1Parms[GNB_CONFIG_E1_IPV4_ADDRESS_CUCP].strptr));
+ e1ap_nc->CUCP_e1_ip_address.ipv4 = 1;
+ strcpy(e1ap_nc->CUUP_e1_ip_address.ipv4_address, *(e1Parms[GNB_CONFIG_E1_IPV4_ADDRESS_CUUP].strptr));
+ e1ap_nc->CUUP_e1_ip_address.ipv4 = 1;
}
}
return msgConfig;
diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c
index 2d47398d51..3d1f0b6aac 100644
--- a/openair2/F1AP/f1ap_cu_task.c
+++ b/openair2/F1AP/f1ap_cu_task.c
@@ -45,6 +45,7 @@ static instance_t cu_task_create_gtpu_instance(eth_params_t *IPaddrs) {
openAddr_t tmp= {0};
strncpy(tmp.originHost, IPaddrs->my_addr, sizeof(tmp.originHost)-1);
sprintf(tmp.originService, "%d", IPaddrs->my_portd);
+ sprintf(tmp.destinationService, "%d", IPaddrs->remote_portd);
return gtpv1Init(tmp);
}
diff --git a/openair2/F1AP/f1ap_ids.h b/openair2/F1AP/f1ap_ids.h
index 96b146f6ba..60d35de737 100644
--- a/openair2/F1AP/f1ap_ids.h
+++ b/openair2/F1AP/f1ap_ids.h
@@ -27,10 +27,13 @@
#include
#include
+#include
+#include
+#include
typedef struct f1_ue_data_t {
uint32_t secondary_ue;
- /* can be extended with F1-specific data also relevant for monolithic */
+ sctp_assoc_t e1_assoc_id;
} f1_ue_data_t;
void cu_init_f1_ue_data(void);
diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c
index cd701f01f5..74a8a997bd 100644
--- a/openair2/GNB_APP/gnb_app.c
+++ b/openair2/GNB_APP/gnb_app.c
@@ -147,10 +147,10 @@ void *gNB_app_task(void *args_p)
if (itti_create_task(TASK_CUCP_E1, E1AP_CUCP_task, NULL) < 0)
AssertFatal(false, "Create task for E1AP CP failed\n");
MessageDef *msg = RCconfig_NR_CU_E1(true);
- if (msg)
- itti_send_msg_to_task(TASK_CUCP_E1, 0, msg);
- else
- AssertFatal(false, "Send inti to task for E1AP CP failed\n");
+ AssertFatal(msg != NULL, "Send inti to task for E1AP CP failed\n");
+ // this sends the E1AP_REGISTER_REQ to CU-CP so it sets up the socket
+ // it does NOT use the E1AP part
+ itti_send_msg_to_task(TASK_CUCP_E1, 0, msg);
}
if (node_type == ngran_gNB_CUUP) {
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index e190b21748..64fa933970 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -1523,7 +1523,7 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
sprintf(aprefix,"%s.[%u].%s",GNB_CONFIG_STRING_GNB_LIST,i,GNB_CONFIG_STRING_SCTP_CONFIG);
config_get(SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix);
- rrc->node_id = *(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr);
+ rrc->node_id = gnb_id;
LOG_I(GNB_APP,"F1AP: gNB_CU_id[%d] %d\n",k,rrc->node_id);
rrc->node_name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr));
LOG_I(GNB_APP,"F1AP: gNB_CU_name[%d] %s\n",k,rrc->node_name);
@@ -1541,7 +1541,6 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
rrc->nr_cellid = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr);
- rrc->um_on_default_drb = *(GNBParamList.paramarray[i][GNB_UMONDEFAULTDRB_IDX].uptr);
if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_mac") == 0) {
} else if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "cudu") == 0) {
@@ -1575,7 +1574,6 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
- nrrrc_config.cell_identity = gnb_id;
nrrrc_config.tac = *GNBParamList.paramarray[i][GNB_TRACKING_AREA_CODE_IDX].uptr;
AssertFatal(!GNBParamList.paramarray[i][GNB_MOBILE_COUNTRY_CODE_IDX_OLD].strptr
&& !GNBParamList.paramarray[i][GNB_MOBILE_NETWORK_CODE_IDX_OLD].strptr,
@@ -1606,6 +1604,7 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
nrrrc_config.enable_sdap = *GNBParamList.paramarray[i][GNB_ENABLE_SDAP_IDX].iptr;
LOG_I(GNB_APP, "SDAP layer is %s\n", nrrrc_config.enable_sdap ? "enabled" : "disabled");
nrrrc_config.drbs = *GNBParamList.paramarray[i][GNB_DRBS].iptr;
+ nrrrc_config.um_on_default_drb = *(GNBParamList.paramarray[i][GNB_UMONDEFAULTDRB_IDX].uptr);
LOG_I(GNB_APP, "Data Radio Bearer count %d\n", nrrrc_config.drbs);
}//
diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h
index d59ecb9eb3..4ce9da2124 100644
--- a/openair2/GNB_APP/gnb_paramdef.h
+++ b/openair2/GNB_APP/gnb_paramdef.h
@@ -161,7 +161,7 @@ typedef enum {
{GNB_CONFIG_STRING_NRCELLID, NULL, 0, .u64ptr=NULL,.defint64val=1, TYPE_UINT64, 0}, \
{GNB_CONFIG_STRING_MINRXTXTIME, NULL, 0, .iptr=NULL, .defintval=2, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_ULPRBBLACKLIST, NULL, 0, .strptr=NULL,.defstrval="", TYPE_STRING, 0}, \
-{GNB_CONFIG_STRING_UMONDEFAULTDRB, NULL, 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
+{GNB_CONFIG_STRING_UMONDEFAULTDRB, NULL, PARAMFLAG_BOOL, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
{GNB_CONFIG_STRING_FORCE256QAMOFF, GNB_CONFIG_HLP_FORCE256QAMOFF, PARAMFLAG_BOOL, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_ENABLE_SDAP, GNB_CONFIG_HLP_STRING_ENABLE_SDAP, PARAMFLAG_BOOL,.iptr=NULL, .defintval=0, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_DRBS, GNB_CONFIG_HLP_STRING_DRBS, 0, .iptr=NULL, .defintval=1, TYPE_INT, 0}, \
@@ -376,19 +376,16 @@ typedef enum {
#define GNB_CONFIG_E1_CU_TYPE_IDX 0
#define GNB_CONFIG_E1_IPV4_ADDRESS_CUCP 1
#define GNB_CONFIG_E1_IPV4_ADDRESS_CUUP 2
-#define GNB_CONFIG_E1_CN_SUPPORT 3
#define GNB_CONFIG_STRING_E1_CU_TYPE "type"
#define GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUCP "ipv4_cucp"
#define GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUUP "ipv4_cuup"
-#define GNB_CONFIG_STRING_E1_CN_SUPPORT "cn_support"
// clang-format off
#define GNBE1PARAMS_DESC { \
{GNB_CONFIG_STRING_E1_CU_TYPE, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
{GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUCP, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
{GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUUP, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
- {GNB_CONFIG_STRING_E1_CN_SUPPORT, NULL, 0, .uptr =NULL, .defintval=1L, TYPE_UINT, 0} \
}
// clang-format on
/* L1 configuration section names */
diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
index b4ec1cb9eb..77c6fd6c8d 100644
--- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
+++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
@@ -96,7 +96,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) {
fill_nr_noS1_bearer_config(&rbconfig, &rlc_rbconfig);
// set up PDCP, RLC, MAC
- nr_pdcp_layer_init();
+ nr_pdcp_layer_init(false);
nr_pdcp_add_drbs(ENB_FLAG_NO, nr_ue_mac_inst->crnti, rbconfig->drb_ToAddModList, 0, NULL, NULL);
nr_rlc_add_drb(nr_ue_mac_inst->crnti, rbconfig->drb_ToAddModList->list.array[0]->drb_Identity, rlc_rbconfig);
struct NR_CellGroupConfig__rlc_BearerToAddModList rlc_toadd_list;
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h
index b90e490302..62a4ae0248 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h
@@ -16,7 +16,7 @@
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
- * conmnc_digit_lengtht@openairinterface.org
+ * contact@openairinterface.org
*/
#ifndef MAC_RRC_UL_H
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c
index 905b9255e4..ab3b7646e7 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c
@@ -16,7 +16,7 @@
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
- * conmnc_digit_lengtht@openairinterface.org
+ * contact@openairinterface.org
*/
#include "nr_mac_gNB.h"
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c
index b98de08a0d..8ee2913e0c 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c
@@ -16,7 +16,7 @@
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
- * conmnc_digit_lengtht@openairinterface.org
+ * contact@openairinterface.org
*/
#include
diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c
index d0ee9587ef..fba6dde507 100644
--- a/openair2/LAYER2/NR_MAC_gNB/main.c
+++ b/openair2/LAYER2/NR_MAC_gNB/main.c
@@ -271,7 +271,7 @@ void mac_top_init_gNB(ngran_node_t node_type,
AssertFatal(rlc_module_init(1) == 0,"Could not initialize RLC layer\n");
// These should be out of here later
- if (get_softmodem_params()->usim_test == 0 ) nr_pdcp_layer_init();
+ if (get_softmodem_params()->usim_test == 0 ) nr_pdcp_layer_init(false);
if(IS_SOFTMODEM_NOS1 && get_softmodem_params()->phy_test) {
// get default noS1 configuration
diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c
new file mode 100644
index 0000000000..7e00b0ee8d
--- /dev/null
+++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c
@@ -0,0 +1,280 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "cucp_cuup_handler.h"
+
+#include "NR_DRB-ToAddModList.h"
+
+#include "platform_types.h"
+#include "intertask_interface.h"
+#include "openair2/COMMON/e1ap_messages_types.h"
+#include "openair3/ocp-gtpu/gtp_itf.h"
+#include "openair2/F1AP/f1ap_ids.h"
+#include "nr_pdcp_oai_api.h"
+#include "cuup_cucp_if.h"
+#include "common/utils/oai_asn1.h"
+#include "openair2/SDAP/nr_sdap/nr_sdap.h"
+#include "openair2/E1AP/e1ap_common.h"
+#include "openair2/F1AP/f1ap_common.h"
+
+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++) {
+ const DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i;
+ asn1cSequenceAdd(DRB_configList->list, struct NR_DRB_ToAddMod, ie);
+ ie->drb_Identity = drb->id;
+ ie->cnAssociation = CALLOC(1, sizeof(*ie->cnAssociation));
+ ie->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config;
+
+ // 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;
+
+ asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd);
+ for (int j=0; j < drb->numQosFlow2Setup; j++) {
+ asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, id);
+ *id = drb->qosFlows[j].id;
+ }
+ sdap_config->mappedQoS_FlowsToRelease = NULL;
+
+ // pdcp_Config
+ ie->reestablishPDCP = NULL;
+ 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);
+ 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->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);
+ }
+ }
+}
+
+static int drb_gtpu_create(instance_t instance,
+ uint32_t ue_id,
+ int incoming_id,
+ int outgoing_id,
+ int qfi,
+ in_addr_t tlAddress, // only IPv4 now
+ teid_t outgoing_teid,
+ gtpCallback callBack,
+ gtpCallbackSDAP callBackSDAP,
+ gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp)
+{
+ gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0};
+ create_tunnel_req.incoming_rb_id[0] = incoming_id;
+ create_tunnel_req.pdusession_id[0] = outgoing_id;
+ memcpy(&create_tunnel_req.dst_addr[0].buffer, &tlAddress, sizeof(uint8_t) * 4);
+ create_tunnel_req.dst_addr[0].length = 32;
+ create_tunnel_req.outgoing_teid[0] = outgoing_teid;
+ create_tunnel_req.outgoing_qfi[0] = qfi;
+ create_tunnel_req.num_tunnels = 1;
+ create_tunnel_req.ue_id = ue_id;
+
+ // we use gtpv1u_create_ngu_tunnel because it returns the interface
+ // address and port of the interface; apart from that, we also might call
+ // newGtpuCreateTunnel() directly
+ return gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, create_tunnel_resp, callBack, callBackSDAP);
+}
+
+static instance_t get_n3_gtp_instance(void)
+{
+ const e1ap_upcp_inst_t *inst = getCxtE1(0);
+ AssertFatal(inst != NULL, "need to have E1 instance\n");
+ return inst->gtpInstN3;
+}
+
+static instance_t get_f1_gtp_instance(void)
+{
+ const f1ap_cudu_inst_t *inst = getCxt(0);
+ if (!inst)
+ return -1; // means no F1
+ return inst->gtpInst;
+}
+
+void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
+{
+ /* mirror the CU-CP UE ID for CU-UP */
+ uint32_t cu_up_ue_id = req->gNB_cu_cp_ue_id;
+ f1_ue_data_t ued = {.secondary_ue = req->gNB_cu_cp_ue_id};
+ cu_add_f1_ue_data(cu_up_ue_id, &ued);
+ LOG_I(E1AP, "adding UE with CU-CP UE ID %d and CU-UP UE ID %d\n", req->gNB_cu_cp_ue_id, cu_up_ue_id);
+
+ instance_t n3inst = get_n3_gtp_instance();
+ instance_t f1inst = get_f1_gtp_instance();
+
+ e1ap_bearer_setup_resp_t resp = {
+ .gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id,
+ .gNB_cu_up_ue_id = cu_up_ue_id,
+ };
+ resp.numPDUSessions = req->numPDUSessions;
+ for (int i = 0; i < resp.numPDUSessions; ++i) {
+ pdu_session_setup_t *resp_pdu = resp.pduSession + i;
+ const pdu_session_to_setup_t *req_pdu = req->pduSession + i;
+ resp_pdu->id = req_pdu->sessionId;
+
+ AssertFatal(req_pdu->numDRB2Modify == 0, "DRB modification not implemented\n");
+ AssertFatal(req_pdu->numDRB2Setup == 1, "can only handle one DRB per PDU session\n");
+ resp_pdu->numDRBSetup = req_pdu->numDRB2Setup;
+ const DRB_nGRAN_to_setup_t *req_drb = &req_pdu->DRBnGRanList[0];
+ DRB_nGRAN_setup_t *resp_drb = &resp_pdu->DRBnGRanList[0];
+ resp_drb->id = req_drb->id;
+ resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup;
+ for (int k = 0; k < resp_drb->numQosFlowSetup; k++)
+ resp_drb->qosFlows[k].id = req_drb->qosFlows[k].id;
+
+ // GTP tunnel for N3/to core
+ gtpv1u_gnb_create_tunnel_resp_t resp_n3 = {0};
+ int qfi = 0; // put PDU session marker
+ int ret = drb_gtpu_create(n3inst,
+ cu_up_ue_id,
+ req_drb->id,
+ req_pdu->sessionId,
+ qfi,
+ req_pdu->tlAddress,
+ req_pdu->teId,
+ nr_pdcp_data_req_drb,
+ sdap_data_req,
+ &resp_n3);
+ AssertFatal(ret >= 0, "Unable to create GTP Tunnel for NG-U\n");
+ AssertFatal(resp_n3.num_tunnels == req->numPDUSessions, "could not create all tunnels\n");
+ resp_pdu->teId = resp_n3.gnb_NGu_teid[i];
+ memcpy(&resp_pdu->tlAddress, &resp_n3.gnb_addr.buffer, 4);
+
+ // create PDCP bearers. This will also create SDAP bearers
+ NR_DRB_ToAddModList_t DRB_configList = {0};
+ fill_DRB_configList_e1(&DRB_configList, req_pdu);
+ nr_pdcp_add_drbs(true, // set this to notify PDCP that his not UE
+ cu_up_ue_id,
+ &DRB_configList,
+ (req->integrityProtectionAlgorithm << 4) | req->cipheringAlgorithm,
+ (uint8_t *)req->encryptionKey,
+ (uint8_t *)req->integrityProtectionKey);
+
+ if (f1inst >= 0) { /* we have F1(-U) */
+ teid_t dummy_teid = 0xffff; // we will update later with answer from DU
+ in_addr_t dummy_address = {0}; // IPv4, updated later with answer from DU
+ gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0};
+ int qfi = -1; // don't put PDU session marker in GTP
+ int ret = drb_gtpu_create(f1inst,
+ cu_up_ue_id,
+ req_drb->id,
+ req_drb->id,
+ qfi,
+ dummy_address,
+ dummy_teid,
+ cu_f1u_data_req,
+ NULL,
+ &resp_f1);
+ resp_drb->numUpParam = 1;
+ AssertFatal(ret >= 0, "Unable to create GTP Tunnel for F1-U\n");
+ memcpy(&resp_drb->UpParamList[0].tlAddress, &resp_f1.gnb_addr.buffer, 4);
+ resp_drb->UpParamList[0].teId = resp_f1.gnb_NGu_teid[0];
+ }
+
+ // We assume all DRBs to setup have been setup successfully, so we always
+ // send successful outcome in response and no failed DRBs
+ resp_pdu->numDRBFailed = 0;
+ }
+
+ get_e1_if()->bearer_setup_response(&resp);
+}
+
+void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req)
+{
+ AssertFatal(req->numPDUSessionsMod > 0, "need at least one PDU session to modify\n");
+
+ e1ap_bearer_modif_resp_t modif = {
+ .gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id,
+ .gNB_cu_up_ue_id = req->gNB_cu_up_ue_id,
+ .numPDUSessionsMod = req->numPDUSessionsMod,
+ };
+
+ instance_t f1inst = get_f1_gtp_instance();
+
+ for (int i=0; i < req->numPDUSessionsMod; i++) {
+ LOG_I(E1AP,
+ "UE %d: updating PDU session ID %ld (%ld bearers)\n",
+ req->gNB_cu_up_ue_id,
+ req->pduSessionMod[i].sessionId,
+ 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];
+ DRB_nGRAN_modified_t *modified = &modif.pduSessionMod[i].DRBnGRanModList[j];
+ modified->id = to_modif->id;
+
+ if (f1inst < 0) // no F1-U?
+ continue; // nothing to do
+
+ in_addr_t addr = {0};
+ memcpy(&addr, &to_modif->DlUpParamList[0].tlAddress, sizeof(in_addr_t));
+
+ GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, req->gNB_cu_cp_ue_id, to_modif->id, addr, to_modif->DlUpParamList[0].teId);
+ }
+ }
+
+ get_e1_if()->bearer_modif_response(&modif);
+}
+
+void e1_bearer_release_cmd(const e1ap_bearer_release_cmd_t *cmd)
+{
+ instance_t n3inst = get_n3_gtp_instance();
+ instance_t f1inst = get_f1_gtp_instance();
+
+ LOG_I(E1AP, "releasing UE %d\n", cmd->gNB_cu_up_ue_id);
+
+ newGtpuDeleteAllTunnels(n3inst, cmd->gNB_cu_up_ue_id);
+ if (f1inst >= 0) // is there F1-U?
+ newGtpuDeleteAllTunnels(f1inst, cmd->gNB_cu_up_ue_id);
+ nr_pdcp_remove_UE(cmd->gNB_cu_up_ue_id);
+ cu_remove_f1_ue_data(cmd->gNB_cu_up_ue_id);
+
+ e1ap_bearer_release_cplt_t cplt = {
+ .gNB_cu_cp_ue_id = cmd->gNB_cu_cp_ue_id,
+ .gNB_cu_up_ue_id = cmd->gNB_cu_up_ue_id,
+ };
+
+ get_e1_if()->bearer_release_complete(&cplt);
+}
diff --git a/openair2/E1AP/e1ap_api.h b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h
similarity index 66%
rename from openair2/E1AP/e1ap_api.h
rename to openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h
index 1b9f219fcc..7290043371 100644
--- a/openair2/E1AP/e1ap_api.h
+++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h
@@ -9,8 +9,6 @@
*
* http://www.openairinterface.org/?page_id=698
*
- * Author and copyright: Laurent Thomas, open-cells.com
- *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,15 +19,17 @@
* contact@openairinterface.org
*/
-#ifndef E1AP_API_H
-#define E1AP_API_H
+#ifndef CUCP_CUUP_HANDLER_H
+#define CUCP_CUUP_HANDLER_H
-#include "platform_types.h"
-#include "openair2/COMMON/e1ap_messages_types.h"
-#include "openair2/E1AP/e1ap_common.h"
-void cuup_init_n3(instance_t instance);
-void process_e1_bearer_context_setup_req(instance_t, e1ap_bearer_setup_req_t *const req);
-void CUUP_process_bearer_context_mod_req(instance_t, e1ap_bearer_setup_req_t *const req);
+#include
-void CUUP_process_bearer_release_command(instance_t, e1ap_bearer_release_cmd_t *const cmd);
-#endif
+void nr_pdcp_e1_if_init(bool uses_e1);
+
+struct e1ap_bearer_setup_req_s;
+struct e1ap_bearer_release_cmd_s;
+void e1_bearer_context_setup(const struct e1ap_bearer_setup_req_s *req);
+void e1_bearer_context_modif(const struct e1ap_bearer_setup_req_s *req);
+void e1_bearer_release_cmd(const struct e1ap_bearer_release_cmd_s *cmd);
+
+#endif /* CUCP_CUUP_HANDLER_H */
diff --git a/openair2/LAYER2/nr_pdcp/cuup_cucp_direct.c b/openair2/LAYER2/nr_pdcp/cuup_cucp_direct.c
new file mode 100644
index 0000000000..b6ad66e18c
--- /dev/null
+++ b/openair2/LAYER2/nr_pdcp/cuup_cucp_direct.c
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "cuup_cucp_if.h"
+#include "e1ap_messages_types.h"
+#include "intertask_interface.h"
+
+static void bearer_setup_response_direct(const e1ap_bearer_setup_resp_t *resp)
+{
+ MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, E1AP_BEARER_CONTEXT_SETUP_RESP);
+ e1ap_bearer_setup_resp_t *msg_resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg);
+ *msg_resp = *resp;
+ itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
+}
+
+static void bearer_modif_response_direct(const e1ap_bearer_modif_resp_t *resp)
+{
+ MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, E1AP_BEARER_CONTEXT_MODIFICATION_RESP);
+ e1ap_bearer_modif_resp_t *msg_resp = &E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg);
+ *msg_resp = *resp;
+ itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
+}
+
+static void bearer_release_complete_direct(const e1ap_bearer_release_cplt_t *cplt)
+{
+ MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, E1AP_BEARER_CONTEXT_RELEASE_CPLT);
+ e1ap_bearer_release_cplt_t *msg_cplt = &E1AP_BEARER_CONTEXT_RELEASE_CPLT(msg);
+ *msg_cplt = *cplt;
+ itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
+}
+
+void cuup_cucp_init_direct(e1_if_t *iface)
+{
+ iface->bearer_setup_response = bearer_setup_response_direct;
+ iface->bearer_modif_response = bearer_modif_response_direct;
+ iface->bearer_release_complete = bearer_release_complete_direct;
+}
diff --git a/openair2/LAYER2/nr_pdcp/cuup_cucp_e1ap.c b/openair2/LAYER2/nr_pdcp/cuup_cucp_e1ap.c
new file mode 100644
index 0000000000..8454d5a7d8
--- /dev/null
+++ b/openair2/LAYER2/nr_pdcp/cuup_cucp_e1ap.c
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "cuup_cucp_if.h"
+#include "intertask_interface.h"
+#include "e1ap_messages_types.h"
+
+static void bearer_setup_response_e1ap(const e1ap_bearer_setup_resp_t *resp)
+{
+ MessageDef *msg_p = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP);
+ e1ap_bearer_setup_resp_t *bearer_resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p);
+ *bearer_resp = *resp;
+ itti_send_msg_to_task (TASK_CUUP_E1, 0, msg_p);
+}
+
+static void bearer_modif_response_e1ap(const e1ap_bearer_modif_resp_t *resp)
+{
+ MessageDef *msg_p = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_RESP);
+ e1ap_bearer_modif_resp_t *modif_resp = &E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg_p);
+ *modif_resp = *resp;
+ itti_send_msg_to_task (TASK_CUUP_E1, 0, msg_p);
+}
+
+static void bearer_release_complete_e1ap(const e1ap_bearer_release_cplt_t *cplt)
+{
+ MessageDef *msg_p = itti_alloc_new_message(TASK_CUUP_E1, 0, E1AP_BEARER_CONTEXT_RELEASE_CPLT);
+ e1ap_bearer_release_cplt_t *msg_cplt = &E1AP_BEARER_CONTEXT_RELEASE_CPLT(msg_p);
+ *msg_cplt = *cplt;
+ itti_send_msg_to_task (TASK_CUUP_E1, 0, msg_p);
+}
+
+void cuup_cucp_init_e1ap(e1_if_t *iface)
+{
+ iface->bearer_setup_response = bearer_setup_response_e1ap;
+ iface->bearer_modif_response = bearer_modif_response_e1ap;
+ iface->bearer_release_complete = bearer_release_complete_e1ap;
+}
diff --git a/openair2/LAYER2/nr_pdcp/cuup_cucp_if.c b/openair2/LAYER2/nr_pdcp/cuup_cucp_if.c
new file mode 100644
index 0000000000..ddeb59205e
--- /dev/null
+++ b/openair2/LAYER2/nr_pdcp/cuup_cucp_if.c
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "cuup_cucp_if.h"
+
+static e1_if_t e1_if;
+
+e1_if_t *get_e1_if(void)
+{
+ return &e1_if;
+}
+
+void nr_pdcp_e1_if_init(bool uses_e1)
+{
+ if (uses_e1)
+ cuup_cucp_init_e1ap(&e1_if);
+ else
+ cuup_cucp_init_direct(&e1_if);
+}
diff --git a/openair2/LAYER2/nr_pdcp/cuup_cucp_if.h b/openair2/LAYER2/nr_pdcp/cuup_cucp_if.h
new file mode 100644
index 0000000000..c33694dac3
--- /dev/null
+++ b/openair2/LAYER2/nr_pdcp/cuup_cucp_if.h
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#ifndef CUUP_CUCP_IF_H
+#define CUUP_CUCP_IF_H
+
+#include
+
+struct e1ap_bearer_setup_resp_s;
+struct e1ap_bearer_modif_resp_s;
+struct e1ap_bearer_release_cplt_s;
+typedef void (*e1_bearer_setup_response_func_t)(const struct e1ap_bearer_setup_resp_s *resp);
+typedef void (*e1_bearer_modif_response_func_t)(const struct e1ap_bearer_modif_resp_s *resp);
+typedef void (*e1_bearer_release_complete_func_t)(const struct e1ap_bearer_release_cplt_s *cplt);
+
+typedef struct e1_if_t {
+ e1_bearer_setup_response_func_t bearer_setup_response;
+ e1_bearer_modif_response_func_t bearer_modif_response;
+ e1_bearer_release_complete_func_t bearer_release_complete;
+} e1_if_t;
+
+e1_if_t *get_e1_if(void);
+void nr_pdcp_e1_if_init(bool uses_e1);
+
+void cuup_cucp_init_direct(e1_if_t *iface);
+void cuup_cucp_init_e1ap(e1_if_t *iface);
+
+#endif /* CUUP_CUCP_IF_H */
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c
deleted file mode 100644
index c7c91a38a0..0000000000
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The OpenAirInterface Software Alliance licenses this file to You under
- * the OAI Public License, Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.openairinterface.org/?page_id=698
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *-------------------------------------------------------------------------------
- * For more information about the OpenAirInterface (OAI) Software Alliance:
- * contact@openairinterface.org
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#include "nr_pdcp_e1_api.h"
-
-void e1_add_drb(int is_gnb,
- uint64_t ue_id,
- struct NR_DRB_ToAddMod *s,
- int ciphering_algorithm,
- int integrity_algorithm,
- unsigned char *ciphering_key,
- unsigned char *integrity_key)
-{
- add_drb(is_gnb, ue_id, s, ciphering_algorithm, integrity_algorithm, ciphering_key, integrity_key);
- LOG_I(PDCP, "%s:%s:%d: added DRB for UE ID %ld\n", __FILE__, __FUNCTION__, __LINE__, ue_id);
-}
-
-void nr_pdcp_e1_add_drbs(eNB_flag_t enb_flag,
- uint64_t ue_id,
- NR_DRB_ToAddModList_t *const drb2add_list,
- const uint8_t security_modeP,
- uint8_t *const kUPenc,
- uint8_t *const kUPint) {
-
- if (drb2add_list != NULL) {
- for (int i = 0; i < drb2add_list->list.count; i++) {
- e1_add_drb(enb_flag, ue_id, drb2add_list->list.array[i],
- security_modeP & 0x0f, (security_modeP >> 4) & 0x0f,
- kUPenc, kUPint);
- }
- } else
- LOG_W(PDCP, "%s with void list\n", __FUNCTION__);
-}
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h
deleted file mode 100644
index 3c16996126..0000000000
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The OpenAirInterface Software Alliance licenses this file to You under
- * the OAI Public License, Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.openairinterface.org/?page_id=698
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *-------------------------------------------------------------------------------
- * For more information about the OpenAirInterface (OAI) Software Alliance:
- * contact@openairinterface.org
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#include "common/utils/oai_asn1.h"
-#include "NR_RadioBearerConfig.h"
-
-#include "nr_pdcp_oai_api.h"
-#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
-#include
-#include "openair2/SDAP/nr_sdap/nr_sdap.h"
-
-void e1_add_drb(int is_gnb,
- uint64_t ue_id,
- struct NR_DRB_ToAddMod *s,
- int ciphering_algorithm,
- int integrity_algorithm,
- unsigned char *ciphering_key,
- unsigned char *integrity_key);
-
-void nr_pdcp_e1_add_drbs(eNB_flag_t enb_flag,
- uint64_t ue_id,
- NR_DRB_ToAddModList_t *const drb2add_list,
- const uint8_t security_modeP,
- uint8_t *const kUPenc,
- uint8_t *const kUPint);
-
-void add_drb_am(int is_gnb, ue_id_t rntiMaybeUEid, struct NR_DRB_ToAddMod *s,
- int ciphering_algorithm,
- int integrity_algorithm,
- unsigned char *ciphering_key,
- unsigned char *integrity_key);
-
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
index 21331ee607..eb1367c724 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
@@ -39,9 +39,9 @@
#include "openair2/F1AP/f1ap_ids.h"
#include
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
-#include "nr_pdcp_e1_api.h"
#include "gnb_config.h"
#include "executables/softmodem-common.h"
+#include "cuup_cucp_if.h"
#define TODO do { \
printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \
@@ -538,7 +538,7 @@ void pdcp_layer_init(void)
abort();
}
-void nr_pdcp_layer_init(void)
+void nr_pdcp_layer_init(bool uses_e1)
{
/* hack: be sure to initialize only once */
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
@@ -559,6 +559,7 @@ void nr_pdcp_layer_init(void)
init_nr_rlc_data_req_queue();
}
+ nr_pdcp_e1_if_init(uses_e1);
init_nr_pdcp_data_ind_queue();
nr_pdcp_init_timer_thread(nr_pdcp_ue_manager);
}
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h
index 6035e34bf4..85e2c4b46b 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h
@@ -25,7 +25,7 @@
#include "pdcp.h"
#include "nr_pdcp_ue_manager.h"
-void nr_pdcp_layer_init(void);
+void nr_pdcp_layer_init(bool uses_e1);
uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id);
void du_rlc_data_req(const protocol_ctxt_t *const ctxt_pP,
diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h
index b233cd502d..8e41bf69d3 100644
--- a/openair2/RRC/LTE/rrc_defs.h
+++ b/openair2/RRC/LTE/rrc_defs.h
@@ -16,7 +16,7 @@
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
- * conmnc_digit_lengtht@openairinterface.org
+ * contact@openairinterface.org
*/
/*! \file RRC/LTE/defs.h
diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c
index 485edc08a4..ee3555a14b 100644
--- a/openair2/RRC/NR/cucp_cuup_direct.c
+++ b/openair2/RRC/NR/cucp_cuup_direct.c
@@ -16,204 +16,35 @@
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
- * conmnc_digit_lengtht@openairinterface.org
+ * contact@openairinterface.org
*/
-#include
-
#include "cucp_cuup_if.h"
-#include "platform_types.h"
+
#include "nr_rrc_defs.h"
-
-#include "softmodem-common.h"
-#include "nr_rrc_proto.h"
-#include "nr_rrc_extern.h"
#include "openair2/COMMON/e1ap_messages_types.h"
-#include "openair3/SECU/key_nas_deriver.h"
+#include "openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h"
-#include "nr_pdcp/nr_pdcp_entity.h"
-#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
-#include
-#include "openair3/ocp-gtpu/gtp_itf.h"
-#include "rrc_gNB_GTPV1U.h"
-#include "common/ran_context.h"
-#include "openair2/F1AP/f1ap_common.h"
-#include "openair2/E1AP/e1ap_common.h"
-
-extern RAN_CONTEXT_t RC;
-
-void fill_e1ap_bearer_setup_resp(e1ap_bearer_setup_resp_t *resp,
- e1ap_bearer_setup_req_t *const req,
- instance_t gtpInst,
- ue_id_t ue_id,
- int remote_port,
- in_addr_t my_addr) {
-
- resp->numPDUSessions = req->numPDUSessions;
- transport_layer_addr_t dummy_address = {0};
- dummy_address.length = 32; // IPv4
- for (int i=0; i < req->numPDUSessions; i++) {
- resp->pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup;
- for (int j=0; j < req->pduSession[i].numDRB2Setup; j++) {
- DRB_nGRAN_to_setup_t *drb2Setup = req->pduSession[i].DRBnGRanList + j;
- DRB_nGRAN_setup_t *drbSetup = resp->pduSession[i].DRBnGRanList + j;
-
- drbSetup->numUpParam = 1;
- drbSetup->UpParamList[0].tlAddress = my_addr;
- drbSetup->UpParamList[0].teId = newGtpuCreateTunnel(gtpInst,
- ue_id,
- drb2Setup->id,
- drb2Setup->id,
- 0xFFFF, // We will set the right value from DU answer
- -1, // no qfi
- dummy_address, // We will set the right value from DU answer
- remote_port,
- cu_f1u_data_req,
- NULL);
- drbSetup->id = drb2Setup->id;
-
- drbSetup->numQosFlowSetup = drb2Setup->numQosFlow2Setup;
- for (int k=0; k < drbSetup->numQosFlowSetup; k++) {
- drbSetup->qosFlows[k].id = drb2Setup->qosFlows[k].id;
- }
- }
- }
-}
-
-void CU_update_UP_DL_tunnel(e1ap_bearer_setup_req_t *const req, instance_t instance, ue_id_t ue_id) {
- for (int i=0; i < req->numPDUSessionsMod; i++) {
- for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) {
- DRB_nGRAN_to_setup_t *drb_p = req->pduSessionMod[i].DRBnGRanModList + j;
-
- in_addr_t addr = {0};
- memcpy(&addr, &drb_p->DlUpParamList[0].tlAddress, sizeof(in_addr_t));
-
- GtpuUpdateTunnelOutgoingAddressAndTeid(instance,
- (ue_id & 0xFFFF),
- (ebi_t)drb_p->id,
- addr,
- drb_p->DlUpParamList[0].teId);
- }
- }
-}
-
-static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p,
- rrc_gNB_ue_context_t *ue_context_p,
- e1ap_bearer_setup_req_t *const req,
- NR_DRB_ToAddModList_t *DRB_configList,
- instance_t instance)
+static void cucp_cuup_bearer_context_setup_direct(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req)
{
- gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0};
- gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0};
- gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
- LOG_W(NR_RRC, "recreate existing tunnels, while adding new ones\n");
- for (int i = 0; i < UE->nb_of_pdusessions; i++) {
- rrc_pdu_session_param_t *pdu = UE->pduSession + i;
- create_tunnel_req.pdusession_id[i] = pdu->param.pdusession_id;
- create_tunnel_req.incoming_rb_id[i] = i + 1;
- create_tunnel_req.outgoing_qfi[i] = req->pduSession[i].DRBnGRanList[0].qosFlows[0].id;
- memcpy(&create_tunnel_req.dst_addr[i].buffer, &pdu->param.upf_addr.buffer, sizeof(create_tunnel_req.dst_addr[0].buffer));
- create_tunnel_req.dst_addr[i].length = pdu->param.upf_addr.length;
- create_tunnel_req.outgoing_teid[i] = pdu->param.gtp_teid;
- }
- create_tunnel_req.num_tunnels = UE->nb_of_pdusessions;
- create_tunnel_req.ue_id = UE->rrc_ue_id;
- int ret = gtpv1u_create_ngu_tunnel(getCxtE1(instance)->gtpInstN3,
- &create_tunnel_req,
- &create_tunnel_resp,
- nr_pdcp_data_req_drb,
- sdap_data_req);
-
- if (ret != 0) {
- LOG_E(NR_RRC,
- "drb_config_gtpu_create=>gtpv1u_create_ngu_tunnel failed, cannot set up GTP tunnel for data transmissions of UE %ld\n",
- create_tunnel_req.ue_id);
- return ret;
- }
-
- nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(ctxt_p, &create_tunnel_resp, 0);
-
- uint8_t kRRCenc[16] = {0};
- uint8_t kRRCint[16] = {0};
- uint8_t kUPenc[16] = {0};
- uint8_t kUPint[16] = {0};
- /* Derive the keys from kgnb */
- if (DRB_configList != NULL) {
- nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kUPenc);
- nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, kUPint);
- }
-
- nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc);
- nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint);
-
- /* Refresh SRBs/DRBs */
-
- LOG_D(NR_RRC, "Configuring PDCP DRBs for UE %x\n", UE->rnti);
- nr_pdcp_add_drbs(ctxt_p->enb_flag,
- UE->rrc_ue_id,
- DRB_configList,
- (UE->integrity_algorithm << 4) | UE->ciphering_algorithm,
- kUPenc,
- kUPint);
-
- return ret;
+ AssertFatal(assoc_id == -1, "illegal assoc_id %d, impossible for integrated CU\n", assoc_id);
+ e1_bearer_context_setup(req);
}
-static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const req, instance_t instance)
+static void cucp_cuup_bearer_context_modif_direct(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req)
{
- rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], req->gNB_cu_cp_ue_id);
- gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
- protocol_ctxt_t ctxt = {0};
- PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rrc_ue_id, 0, 0, 0);
-
- e1ap_bearer_setup_resp_t resp = {0};
- resp.numPDUSessions = req->numPDUSessions;
- for (int i = 0; i < resp.numPDUSessions; ++i) {
- resp.pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup;
- for (int j = 0; j < req->pduSession[i].numDRB2Setup; j++) {
- DRB_nGRAN_to_setup_t *req_drb = req->pduSession[i].DRBnGRanList + j;
- DRB_nGRAN_setup_t *resp_drb = resp.pduSession[i].DRBnGRanList + j;
- resp_drb->id = req_drb->id;
- resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup;
- for (int k = 0; k < resp_drb->numQosFlowSetup; k++)
- resp_drb->qosFlows[k].id = req_drb->qosFlows[k].id;
- }
- }
-
- gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
- // GTP tunnel for UL
- NR_DRB_ToAddModList_t *DRB_configList = fill_DRB_configList(UE);
- int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, DRB_configList, rrc->e1_inst);
- if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n");
- // the code is very badly organized, it is not possible here to call freeDRBlist()
- ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList,DRB_configList );
-
- // Used to store teids: if monolithic, will simply be NULL
- if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) {
- // intentionally empty
- } else {
- int remote_port = RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd;
- in_addr_t my_addr = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.my_addr);
- instance_t gtpInst = getCxt(instance)->gtpInst;
- // GTP tunnel for DL
- fill_e1ap_bearer_setup_resp(&resp, req, gtpInst, UE->rrc_ue_id, remote_port, my_addr);
- }
- // actually, we should receive the corresponding context setup response
- // message at the RRC and always react to this one. So in the following, we
- // just call the corresponding message handler
- prepare_and_send_ue_context_modification_f1(ue_context_p, &resp);
+ AssertFatal(assoc_id == -1, "illegal assoc_id %d, impossible for integrated CU\n", assoc_id);
+ e1_bearer_context_modif(req);
}
-static void cucp_cuup_bearer_context_mod_direct(e1ap_bearer_setup_req_t *const req, instance_t instance)
+static void cucp_cuup_bearer_context_release_cmd_direct(sctp_assoc_t assoc_id, const e1ap_bearer_release_cmd_t *cmd)
{
- // only update GTP tunnels if it is really a CU
- if (!NODE_IS_CU(RC.nrrrc[0]->node_type))
- return;
- instance_t gtpInst = getCxt(instance)->gtpInst;
- CU_update_UP_DL_tunnel(req, gtpInst, req->gNB_cu_cp_ue_id);
+ AssertFatal(assoc_id == -1, "illegal assoc_id %d, impossible for integrated CU\n", assoc_id);
+ e1_bearer_release_cmd(cmd);
}
void cucp_cuup_message_transfer_direct_init(gNB_RRC_INST *rrc) {
rrc->cucp_cuup.bearer_context_setup = cucp_cuup_bearer_context_setup_direct;
- rrc->cucp_cuup.bearer_context_mod = cucp_cuup_bearer_context_mod_direct;
+ rrc->cucp_cuup.bearer_context_mod = cucp_cuup_bearer_context_modif_direct;
+ rrc->cucp_cuup.bearer_context_release = cucp_cuup_bearer_context_release_cmd_direct;
}
diff --git a/openair2/RRC/NR/cucp_cuup_e1ap.c b/openair2/RRC/NR/cucp_cuup_e1ap.c
index 200729ec11..fb099178d4 100644
--- a/openair2/RRC/NR/cucp_cuup_e1ap.c
+++ b/openair2/RRC/NR/cucp_cuup_e1ap.c
@@ -16,44 +16,49 @@
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
- * conmnc_digit_lengtht@openairinterface.org
+ * contact@openairinterface.org
*/
#include "cucp_cuup_if.h"
-#include
-
-#include "platform_types.h"
#include "nr_rrc_defs.h"
#include "nr_rrc_proto.h"
#include "nr_rrc_extern.h"
#include "cucp_cuup_if.h"
-#include "openair2/COMMON/e1ap_messages_types.h"
-#include "openair3/SECU/secu_defs.h"
-#include
-#include "common/ran_context.h"
-
-extern RAN_CONTEXT_t RC;
-
-static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance)
+static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req)
{
- MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_SETUP_REQ);
+ AssertFatal(assoc_id > 0, "illegal assoc_id %d\n", assoc_id);
+ MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_REQ);
+ msg_p->ittiMsgHeader.originInstance = assoc_id;
e1ap_bearer_setup_req_t *bearer_req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p);
memcpy(bearer_req, req, sizeof(e1ap_bearer_setup_req_t));
- itti_send_msg_to_task (TASK_CUCP_E1, instance, msg_p);
+ itti_send_msg_to_task (TASK_CUCP_E1, 0, msg_p);
}
-static void cucp_cuup_bearer_context_mod_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance)
+static void cucp_cuup_bearer_context_mod_e1ap(sctp_assoc_t assoc_id, const e1ap_bearer_setup_req_t *req)
{
- MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_MODIFICATION_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);
memcpy(req_msg, req, sizeof(*req));
- itti_send_msg_to_task(TASK_CUCP_E1, instance, msg);
+ itti_send_msg_to_task(TASK_CUCP_E1, 0, msg);
+}
+
+static void cucp_cuup_bearer_context_release_cmd_e1ap(sctp_assoc_t assoc_id, const e1ap_bearer_release_cmd_t *cmd)
+{
+ AssertFatal(assoc_id > 0, "illegal assoc_id %d\n", assoc_id);
+ MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_RELEASE_CMD);
+ msg->ittiMsgHeader.originInstance = assoc_id;
+ e1ap_bearer_release_cmd_t *cmd_msg = &E1AP_BEARER_CONTEXT_RELEASE_CMD(msg);
+ memcpy(cmd_msg, cmd, sizeof(*cmd));
+ itti_send_msg_to_task(TASK_CUCP_E1, 0, msg);
}
void cucp_cuup_message_transfer_e1ap_init(gNB_RRC_INST *rrc) {
rrc->cucp_cuup.bearer_context_setup = cucp_cuup_bearer_context_setup_e1ap;
rrc->cucp_cuup.bearer_context_mod = cucp_cuup_bearer_context_mod_e1ap;
+ rrc->cucp_cuup.bearer_context_release = cucp_cuup_bearer_context_release_cmd_e1ap;
}
diff --git a/openair2/RRC/NR/cucp_cuup_if.h b/openair2/RRC/NR/cucp_cuup_if.h
index 079a32e850..cbf84a289e 100644
--- a/openair2/RRC/NR/cucp_cuup_if.h
+++ b/openair2/RRC/NR/cucp_cuup_if.h
@@ -16,27 +16,26 @@
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
- * conmnc_digit_lengtht@openairinterface.org
+ * contact@openairinterface.org
*/
#ifndef CUCP_CUUP_IF_H
#define CUCP_CUUP_IF_H
#include
+#include
+#include
+#include
#include "platform_types.h"
struct e1ap_bearer_setup_req_s;
struct e1ap_bearer_setup_resp_s;
-typedef void (*cucp_cuup_bearer_context_setup_func_t)(struct e1ap_bearer_setup_req_s *const req, instance_t instance);
+struct e1ap_bearer_release_cmd_s;
+typedef void (*cucp_cuup_bearer_context_setup_func_t)(sctp_assoc_t assoc_id, const struct e1ap_bearer_setup_req_s *req);
+typedef void (*cucp_cuup_bearer_context_release_func_t)(sctp_assoc_t assoc_id, const struct e1ap_bearer_release_cmd_s *cmd);
struct gNB_RRC_INST_s;
void cucp_cuup_message_transfer_direct_init(struct gNB_RRC_INST_s *rrc);
void cucp_cuup_message_transfer_e1ap_init(struct gNB_RRC_INST_s *rrc);
-void fill_e1ap_bearer_setup_resp(struct e1ap_bearer_setup_resp_s *resp,
- struct e1ap_bearer_setup_req_s *const req,
- instance_t gtpInst,
- ue_id_t ue_id,
- int remote_port,
- in_addr_t my_addr);
-void CU_update_UP_DL_tunnel(struct e1ap_bearer_setup_req_s *const req, instance_t instance, ue_id_t ue_id);
+
#endif
diff --git a/openair2/RRC/NR/mac_rrc_dl.h b/openair2/RRC/NR/mac_rrc_dl.h
index 9fc75b3073..6e43212f5e 100644
--- a/openair2/RRC/NR/mac_rrc_dl.h
+++ b/openair2/RRC/NR/mac_rrc_dl.h
@@ -16,7 +16,7 @@
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
- * conmnc_digit_lengtht@openairinterface.org
+ * contact@openairinterface.org
*/
#ifndef MAC_RRC_DL_H
diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c
index c18a33954c..ee9a29c6ae 100644
--- a/openair2/RRC/NR/mac_rrc_dl_direct.c
+++ b/openair2/RRC/NR/mac_rrc_dl_direct.c
@@ -16,7 +16,7 @@
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
- * conmnc_digit_lengtht@openairinterface.org
+ * contact@openairinterface.org
*/
#include "nr_rrc_defs.h"
diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c
index 6ead51e3da..951e9639c5 100644
--- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c
+++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c
@@ -16,7 +16,7 @@
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
- * conmnc_digit_lengtht@openairinterface.org
+ * contact@openairinterface.org
*/
#include
diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h
index c37979598a..16b7f040ee 100644
--- a/openair2/RRC/NR/nr_rrc_defs.h
+++ b/openair2/RRC/NR/nr_rrc_defs.h
@@ -330,11 +330,6 @@ typedef struct {
uint8_t *SIB23;
uint8_t sizeof_SIB23;
- NR_SIB2_t *sib2;
- NR_SIB3_t *sib3;
- NR_BCCH_DL_SCH_Message_t systemInformation; // SIB23
- NR_CellGroupConfig_t *secondaryCellGroup[MAX_NR_RRC_UE_CONTEXTS];
-
} rrc_gNB_carrier_data_t;
//---------------------------------------------------
@@ -367,6 +362,7 @@ typedef struct nr_mac_rrc_dl_if_s {
typedef struct cucp_cuup_if_s {
cucp_cuup_bearer_context_setup_func_t bearer_context_setup;
cucp_cuup_bearer_context_setup_func_t bearer_context_mod;
+ cucp_cuup_bearer_context_release_func_t bearer_context_release;
} cucp_cuup_if_t;
typedef struct nr_rrc_du_container_t {
@@ -376,6 +372,14 @@ typedef struct nr_rrc_du_container_t {
NR_SIB1_t *sib1;
} nr_rrc_du_container_t;
+typedef struct nr_rrc_cuup_container_t {
+ /* Tree-related data */
+ RB_ENTRY(nr_rrc_cuup_container_t) entries;
+
+ e1ap_setup_req_t *setup_req;
+ sctp_assoc_t assoc_id;
+} nr_rrc_cuup_container_t;
+
//---NR---(completely change)---------------------
typedef struct gNB_RRC_INST_s {
@@ -396,24 +400,6 @@ typedef struct gNB_RRC_INST_s {
// gNB N3 GTPU instance
instance_t e1_inst;
- // other PLMN parameters
- /// Mobile country code
- int mcc;
- /// Mobile network code
- int mnc;
- /// number of mnc digits
- int mnc_digit_length;
-
- // other RAN parameters
- int srb1_timer_poll_retransmit;
- int srb1_poll_pdu;
- int srb1_poll_byte;
- int srb1_max_retx_threshold;
- int srb1_timer_reordering;
- int srb1_timer_status_prohibit;
- int um_on_default_drb;
- int srs_enable[MAX_NUM_CCs];
-
char *uecap_file;
// security configuration (preferred algorithms)
@@ -423,6 +409,8 @@ typedef struct gNB_RRC_INST_s {
cucp_cuup_if_t cucp_cuup;
nr_rrc_du_container_t *du;
+ RB_HEAD(rrc_cuup_tree, nr_rrc_cuup_container_t) cuups; // CU-UPs, indexed by assoc_id
+ size_t num_cuups;
} gNB_RRC_INST;
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 510e058495..2bbbe5ab36 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -132,6 +132,10 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP);
+sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue);
+sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue, int sst, int sd);
+int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req);
+
void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req,
instance_t instance);
@@ -144,8 +148,6 @@ void ue_cxt_mod_send_e1ap(MessageDef *msg,
void ue_cxt_mod_direct(MessageDef *msg,
instance_t instance);
-NR_DRB_ToAddModList_t *fill_DRB_configList(gNB_RRC_UE_t *ue);
-
void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p,
e1ap_bearer_setup_resp_t *e1ap_resp);
void nr_pdcp_add_srbs(eNB_flag_t enb_flag, ue_id_t rntiMaybeUEid, NR_SRB_ToAddModList_t *const srb2add_list, const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kUPint);
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index b057d023b3..7af9350136 100644
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -93,7 +93,6 @@
#include
#include
#include
-#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
#include "openair2/F1AP/f1ap_common.h"
#include "openair2/F1AP/f1ap_ids.h"
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
@@ -337,6 +336,7 @@ void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *c
rrc_gNB_CU_DU_init(rrc);
uid_linear_allocator_init(&rrc->uid_allocator);
RB_INIT(&rrc->rrc_ue_head);
+ RB_INIT(&rrc->cuups);
rrc->configuration = *configuration;
/// System Information INIT
init_NR_SI(rrc);
@@ -575,7 +575,6 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co
dedicatedNAS_MessageList,
ue_p->masterCellGroup);
AssertFatal(size > 0, "cannot encode RRCReconfiguration in %s()\n", __func__);
- LOG_W(NR_RRC, "do_RRCReconfiguration(): size %d\n", size);
free_defaultMeasConfig(measconfig);
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
@@ -1041,6 +1040,7 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context
}
}
+ // TODO: should send E1 UE Bearer Modification with PDCP Reestablishment flag
nr_pdcp_reestablishment(ue_p->rrc_ue_id);
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id);
@@ -2033,8 +2033,6 @@ static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p)
}
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
- nr_pdcp_remove_UE(UE->rrc_ue_id);
- newGtpuDeleteAllTunnels(instance, UE->rrc_ue_id);
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance, UE->rrc_ue_id);
LOG_I(NR_RRC, "removed UE CU UE ID %u/RNTI %04x \n", UE->rrc_ue_id, UE->rnti);
rrc_delete_ue_data(UE);
@@ -2055,10 +2053,13 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i
if (resp->drbs_to_be_setup_length > 0) {
e1ap_bearer_setup_req_t req = {0};
+ // TODO: bug: we receive the DRBs, but we don't associate to a PDU session
+ // -> we are not sure which PDU session this is, and fill "all"
req.numPDUSessionsMod = UE->nb_of_pdusessions;
req.gNB_cu_cp_ue_id = UE->rrc_ue_id;
req.gNB_cu_up_ue_id = UE->rrc_ue_id;
for (int i = 0; i < req.numPDUSessionsMod; i++) {
+ req.pduSessionMod[i].sessionId = UE->pduSession[i].param.pdusession_id;
req.pduSessionMod[i].numDRB2Modify = resp->drbs_to_be_setup_length;
for (int j = 0; j < resp->drbs_to_be_setup_length; j++) {
f1ap_drb_to_be_setup_t *drb_f1 = resp->drbs_to_be_setup + j;
@@ -2073,7 +2074,8 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i
// send the F1 response message up to update F1-U tunnel info
// it seems the rrc transaction id (xid) is not needed here
- rrc->cucp_cuup.bearer_context_mod(&req, instance);
+ sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE);
+ rrc->cucp_cuup.bearer_context_mod(assoc_id, &req);
}
if (resp->du_to_cu_rrc_information != NULL && resp->du_to_cu_rrc_information->cellGroupConfig != NULL) {
@@ -2314,47 +2316,42 @@ static int get_dl_mimo_layers(const f1ap_served_cell_info_t *cell_info, const NR
return(1);
}
-int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req, instance_t instance) {
-
- AssertFatal(req->supported_plmns <= PLMN_LIST_MAX_SIZE, "Supported PLMNs is more than PLMN_LIST_MAX_SIZE\n");
- gNB_RRC_INST *rrc = RC.nrrrc[0]; //TODO: remove hardcoding of RC index here
- MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, instance, E1AP_SETUP_RESP);
-
- e1ap_setup_resp_t *resp = &E1AP_SETUP_RESP(msg_p);
- resp->transac_id = req->transac_id;
-
- for (int i=0; i < req->supported_plmns; i++) {
- if (rrc->configuration.mcc[i] == req->plmns[i].mcc &&
- rrc->configuration.mnc[i] == req->plmns[i].mnc) {
- LOG_E(NR_RRC, "PLMNs received from CUUP (mcc:%d, mnc:%d) did not match with PLMNs in RRC (mcc:%d, mnc:%d)\n",
- req->plmns[i].mcc, req->plmns[i].mnc, rrc->configuration.mcc[i], rrc->configuration.mnc[i]);
- return -1;
- }
- }
-
- itti_send_msg_to_task(TASK_CUCP_E1, instance, msg_p);
-
- return 0;
-}
-
-void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp)
+void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance)
{
- /* Generate a UE context modification request message towards the DU to
- * instruct the DU for SRB2 and DRB configuration and get the updates on
- * master cell group config from the DU*/
-
gNB_RRC_INST *rrc = RC.nrrrc[0];
+ rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_cu_cp_ue_id);
+ AssertFatal(ue_context_p != NULL, "did not find UE with CU UE ID %d\n", resp->gNB_cu_cp_ue_id);
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
+ // currently: we don't have "infrastructure" to save the CU-UP UE ID, so we
+ // assume (and below check) that CU-UP UE ID == CU-CP UE ID
+ AssertFatal(resp->gNB_cu_cp_ue_id == resp->gNB_cu_up_ue_id,
+ "cannot handle CU-UP UE ID different from CU-CP UE ID (%d vs %d)\n",
+ resp->gNB_cu_cp_ue_id,
+ resp->gNB_cu_up_ue_id);
+
+ // save the tunnel address for the PDU sessions
+ 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) {
+ LOG_W(RRC, "E1: received setup for PDU session %ld, but has not been requested\n", e1_pdu->id);
+ continue;
+ }
+ rrc_pdu->param.gNB_teid_N3 = e1_pdu->teId;
+ memcpy(&rrc_pdu->param.gNB_addr_N3.buffer, &e1_pdu->tlAddress, sizeof(uint8_t) * 4);
+ rrc_pdu->param.gNB_addr_N3.length = sizeof(in_addr_t);
+ }
+
/* Instruction towards the DU for DRB configuration and tunnel creation */
- int nb_drb = e1ap_resp->pduSession[0].numDRBSetup;
+ int nb_drb = resp->pduSession[0].numDRBSetup;
f1ap_drb_to_be_setup_t drbs[nb_drb];
for (int i = 0; i < nb_drb; i++) {
- drbs[i].drb_id = e1ap_resp->pduSession[0].DRBnGRanList[i].id;
- drbs[i].rlc_mode = rrc->um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM;
- drbs[i].up_ul_tnl[0].tl_address = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress;
+ drbs[i].drb_id = resp->pduSession[0].DRBnGRanList[i].id;
+ drbs[i].rlc_mode = rrc->configuration.um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM;
+ drbs[i].up_ul_tnl[0].tl_address = resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress;
drbs[i].up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
- drbs[i].up_ul_tnl[0].teid = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId;
+ drbs[i].up_ul_tnl[0].teid = resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId;
drbs[i].up_ul_tnl_length = 1;
}
@@ -2368,6 +2365,7 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex
srbs[0].lcid = 2;
}
+ /* Gather UE capability if present */
cu_to_du_rrc_information_t cu2du = {0};
cu_to_du_rrc_information_t *cu2du_p = NULL;
if (UE->ue_cap_buffer.len > 0 && UE->ue_cap_buffer.buf != NULL) {
@@ -2394,36 +2392,29 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex
rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req);
}
-void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance) {
- // Find the UE context from UE ID and send ITTI message to F1AP to send UE context modification message to DU
-
- rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], resp->gNB_cu_cp_ue_id);
- AssertFatal(ue_context_p != NULL, "did not find UE with CU UE ID %d\n", resp->gNB_cu_cp_ue_id);
- protocol_ctxt_t ctxt = {0};
- PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, resp->gNB_cu_cp_ue_id, 0, 0, 0);
-
- // currently: we don't have "infrastructure" to save the CU-UP UE ID, so we
- // assume (and below check) that CU-UP UE ID == CU-CP UE ID
- AssertFatal(resp->gNB_cu_cp_ue_id == resp->gNB_cu_up_ue_id,
- "cannot handle CU-UP UE ID different from CU-CP UE ID (%d vs %d)\n",
- resp->gNB_cu_cp_ue_id,
- resp->gNB_cu_up_ue_id);
-
- gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0};
- create_tunnel_resp.num_tunnels = resp->numPDUSessions;
- for (int i=0; i < resp->numPDUSessions; i++) {
- create_tunnel_resp.pdusession_id[i] = resp->pduSession[i].id;
- create_tunnel_resp.gnb_NGu_teid[i] = resp->pduSession[i].teId;
- memcpy(create_tunnel_resp.gnb_addr.buffer,
- &resp->pduSession[i].tlAddress,
- sizeof(in_addr_t));
- create_tunnel_resp.gnb_addr.length = sizeof(in_addr_t); // IPv4 byte length
+void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t *resp)
+{
+ gNB_RRC_INST *rrc = RC.nrrrc[0];
+ rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_cu_cp_ue_id);
+ if (ue_context_p == NULL) {
+ LOG_E(RRC, "no UE with CU-CP UE ID %d found\n", resp->gNB_cu_cp_ue_id);
+ return;
}
- nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(&ctxt, &create_tunnel_resp, 0);
+ // there is not really anything to do here as of now
+ for (int i = 0; i < resp->numPDUSessionsMod; ++i) {
+ const pdu_session_modif_t *pdu = &resp->pduSessionMod[i];
+ LOG_I(RRC, "UE %d: PDU session ID %ld modified %d bearers\n", resp->gNB_cu_cp_ue_id, pdu->id, pdu->numDRBModified);
+ }
+}
- // TODO: SV: combine e1ap_bearer_setup_req_t and e1ap_bearer_setup_resp_t and minimize assignments
- prepare_and_send_ue_context_modification_f1(ue_context_p, resp);
+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
+ // note that we don't check for the UE: it does not exist anymore if the F1
+ // UE context release complete arrived from the DU first, after which we free
+ // the UE context
+ LOG_I(RRC, "UE %d: received bearer release complete\n", cplt->gNB_cu_cp_ue_id);
}
static void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id)
@@ -2698,11 +2689,20 @@ void *rrc_gnb_task(void *args_p) {
break;
case E1AP_SETUP_REQ:
- rrc_gNB_process_e1_setup_req(&E1AP_SETUP_REQ(msg_p), instance);
+ rrc_gNB_process_e1_setup_req(msg_p->ittiMsgHeader.originInstance, &E1AP_SETUP_REQ(msg_p));
break;
case E1AP_BEARER_CONTEXT_SETUP_RESP:
rrc_gNB_process_e1_bearer_context_setup_resp(&E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p), instance);
+ break;
+
+ case E1AP_BEARER_CONTEXT_MODIFICATION_RESP:
+ rrc_gNB_process_e1_bearer_context_modif_resp(&E1AP_BEARER_CONTEXT_MODIFICATION_RESP(msg_p));
+ break;
+
+ case E1AP_BEARER_CONTEXT_RELEASE_CPLT:
+ rrc_gNB_process_e1_bearer_context_release_cplt(&E1AP_BEARER_CONTEXT_RELEASE_CPLT(msg_p));
+ break;
case NGAP_PAGING_IND:
rrc_gNB_process_PAGING_IND(msg_p, instance);
@@ -2855,6 +2855,13 @@ rrc_gNB_generate_RRCRelease(
deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd};
nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data);
+ sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE);
+ e1ap_bearer_release_cmd_t cmd = {
+ .gNB_cu_cp_ue_id = UE->rrc_ue_id,
+ .gNB_cu_up_ue_id = UE->rrc_ue_id,
+ };
+ rrc->cucp_cuup.bearer_context_release(assoc_id, &cmd);
+
/* UE will be freed after UE context release complete */
}
@@ -2936,7 +2943,8 @@ void rrc_gNB_trigger_new_bearer(int rnti)
ue->xids[xid] = RRC_PDUSESSION_MODIFY;
ue->pduSession[0].xid = xid; // hack: fake xid for ongoing PDU session
LOG_W(RRC, "trigger new bearer %ld for UE %04x xid %d\n", drb->id, ue->rnti, xid);
- rrc->cucp_cuup.bearer_context_setup(&bearer_req, 0);
+ sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue);
+ rrc->cucp_cuup.bearer_context_setup(assoc_id, &bearer_req);
}
void rrc_gNB_trigger_release_bearer(int rnti)
diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.c b/openair2/RRC/NR/rrc_gNB_GTPV1U.c
index 3ef3e62d51..6c8627aa09 100644
--- a/openair2/RRC/NR/rrc_gNB_GTPV1U.c
+++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.c
@@ -75,35 +75,3 @@ int rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ctxt_
return 0;
}
-
-int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ctxt_pP, const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, int offset)
-{
- if (!create_tunnel_resp_pP) {
- LOG_E(NR_RRC, "create_tunnel_resp_pP error\n");
- return -1;
- }
-
- LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT " RX CREATE_TUNNEL_RESP num tunnels %u \n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), create_tunnel_resp_pP->num_tunnels);
- /* we look up by CU UE ID! Do NOT change back to RNTI! */
- rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[ctxt_pP->module_id], ctxt_pP->rntiMaybeUEid);
- if (!ue_context_p) {
- LOG_E(NR_RRC, "UE table error\n");
- return -1;
- }
-
- for (int i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) {
- ue_context_p->ue_context.pduSession[i + offset].param.gNB_teid_N3 = create_tunnel_resp_pP->gnb_NGu_teid[i];
- ue_context_p->ue_context.pduSession[i + offset].param.gNB_addr_N3 = create_tunnel_resp_pP->gnb_addr;
- AssertFatal(ue_context_p->ue_context.pduSession[i + offset].param.pdusession_id == create_tunnel_resp_pP->pdusession_id[i], "");
- LOG_I(NR_RRC,
- PROTOCOL_NR_RRC_CTXT_UE_FMT
- " nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u) bearer UE context index %u, id %u, gtp addr len %d \n",
- PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
- create_tunnel_resp_pP->gnb_NGu_teid[i],
- i,
- create_tunnel_resp_pP->pdusession_id[i],
- create_tunnel_resp_pP->gnb_addr.length);
- }
-
- return 0;
-}
diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.h b/openair2/RRC/NR/rrc_gNB_GTPV1U.h
index d538127d76..d7d1013db8 100644
--- a/openair2/RRC/NR/rrc_gNB_GTPV1U.h
+++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.h
@@ -38,6 +38,4 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
uint8_t *inde_list
);
-int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ctxt_pP, const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, int offset_in_rrc);
-
#endif
diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c
index cac6884631..49d3ccad99 100644
--- a/openair2/RRC/NR/rrc_gNB_NGAP.c
+++ b/openair2/RRC/NR/rrc_gNB_NGAP.c
@@ -378,6 +378,9 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
uint8_t nb_pdusessions_tosetup = req->nb_of_pdusessions;
if (nb_pdusessions_tosetup) {
AssertFatal(false, "PDU sessions in Initial context setup request not handled by E1 yet\n");
+ /* this code should pass by E1: commenting here for future reference, but
+ * already handled in E1 for the "normal case" of a separate request for
+ * PDU session setup.
gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0};
for (int i = 0; i < nb_pdusessions_tosetup; i++) {
UE->nb_of_pdusessions++;
@@ -404,6 +407,7 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
}
nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(&ctxt, &create_tunnel_resp, 0);
+ */
}
/* NAS PDU */
@@ -757,6 +761,8 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
UE->amf_ue_ngap_id = msg->amf_ue_ngap_id;
e1ap_bearer_setup_req_t bearer_req = {0};
+
+ e1ap_nssai_t cuup_nssai = {0};
for (int i = 0; i < msg->nb_pdusessions_tosetup; i++) {
rrc_pdu_session_param_t *pduSession = find_pduSession(UE, msg->pdusession_setup_params[i].pdusession_id, true);
pdusession_t *session = &pduSession->param;
@@ -775,7 +781,13 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
pdu_session_to_setup_t *pdu = bearer_req.pduSession + bearer_req.numPDUSessions;
bearer_req.numPDUSessions++;
pdu->sessionId = session->pdusession_id;
- pdu->sst = msg->allowed_nssai[i].sST;
+ ngap_allowed_NSSAI_t *nssai = &msg->allowed_nssai[i];
+ pdu->nssai.sst = nssai->sST;
+ pdu->nssai.sd = 0xffffff;
+ if (nssai->sD_flag)
+ pdu->nssai.sd = nssai->sD[0] << 16 | nssai->sD[1] << 8 | nssai->sD[2];
+ if (cuup_nssai.sst == 0)
+ cuup_nssai = pdu->nssai; /* for CU-UP selection below */
pdu->integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed;
pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed;
@@ -787,7 +799,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
drb->id = i + j + UE->nb_of_pdusessions;
- drb->defaultDRB = E1AP_DefaultDRB_true;
+ drb->defaultDRB = true;
drb->sDAP_Header_UL = !(rrc->configuration.enable_sdap);
drb->sDAP_Header_DL = !(rrc->configuration.enable_sdap);
@@ -823,7 +835,13 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
}
int xid = rrc_gNB_get_next_transaction_identifier(instance);
UE->xids[xid] = RRC_PDUSESSION_ESTABLISH;
- rrc->cucp_cuup.bearer_context_setup(&bearer_req, instance);
+ /* Limitation: we assume one fixed CU-UP per UE. We base the selection on
+ * NSSAI, but the UE might have multiple PDU sessions with differing slices,
+ * in which we might need to select different CU-UPs. In this case, we would
+ * actually need to group the E1 bearer context setup for the different
+ * CU-UPs, and send them to the different CU-UPs. */
+ sctp_assoc_t assoc_id = get_new_cuup_for_ue(rrc, UE, cuup_nssai.sst, cuup_nssai.sd);
+ rrc->cucp_cuup.bearer_context_setup(assoc_id, &bearer_req);
return;
}
diff --git a/openair2/RRC/NR/rrc_gNB_cuup.c b/openair2/RRC/NR/rrc_gNB_cuup.c
new file mode 100644
index 0000000000..3ab6dfe7bb
--- /dev/null
+++ b/openair2/RRC/NR/rrc_gNB_cuup.c
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "common/ran_context.h"
+#include "nr_rrc_defs.h"
+#include "openair2/F1AP/f1ap_ids.h"
+
+static int cuup_compare(const nr_rrc_cuup_container_t *a, const nr_rrc_cuup_container_t *b)
+{
+ if (a->assoc_id > b->assoc_id)
+ return 1;
+ if (a->assoc_id == b->assoc_id)
+ return 0;
+ return -1; /* a->assoc_id < b->assoc_id */
+}
+
+/* Tree management functions */
+RB_GENERATE/*_STATIC*/(rrc_cuup_tree, nr_rrc_cuup_container_t, entries, cuup_compare);
+
+static const nr_rrc_cuup_container_t *select_cuup_slice(const struct rrc_cuup_tree *t, const gNB_RRC_UE_t *ue, int sst, int sd)
+{
+ nr_rrc_cuup_container_t *second_best_match = NULL; /* if no NSSAI matches exactly */
+ nr_rrc_cuup_container_t *cuup = NULL;
+ RB_FOREACH(cuup, rrc_cuup_tree, (struct rrc_cuup_tree *)&t) {
+ e1ap_setup_req_t *sr = cuup->setup_req;
+ for (int p = 0; p < sr->supported_plmns; ++p) {
+ /* actually we should also check that the PLMN selected by the UE matches */
+ for (int s = 0; s < sr->plmn[p].supported_slices; ++s) {
+ e1ap_nssai_t *nssai = &sr->plmn[p].slice[s];
+ if (nssai->sst == sst && nssai->sd == sd) {
+ LOG_I(RRC, "selecting CU-UP ID %ld based on exact NSSAI match (%d:0x%06x)\n", sr->gNB_cu_up_id, sst, sd);
+ return cuup; /* exact match */
+ } else if (nssai->sst == sst && second_best_match == NULL) {
+ LOG_I(RRC, "second best match: CU-UP ID %ld matches SST %d\n", sr->gNB_cu_up_id, sst);
+ second_best_match = cuup; /* only the SST matches -> "good enough" */
+ }
+ }
+ }
+ }
+ return second_best_match;
+}
+
+static const nr_rrc_cuup_container_t *select_cuup_round_robin(size_t n_t, const struct rrc_cuup_tree *t, const gNB_RRC_UE_t *ue)
+{
+ /* pick the CU-UP following a "round-robin" fashion: select CU-UP M = RRC UE
+ * ID % N with N number of CU-UPs */
+ int m = (ue->rrc_ue_id - 1) % n_t;
+ nr_rrc_cuup_container_t *cuup = NULL;
+ RB_FOREACH(cuup, rrc_cuup_tree, (struct rrc_cuup_tree *)&t) {
+ if (m == 0) {
+ LOG_I(RRC, "round-robin match: select CU-UP ID %ld (no NSSAI match)\n", cuup->setup_req->gNB_cu_up_id);
+ return cuup;
+ }
+ m--;
+ }
+ /* this should not happen: no CU-UP available? */
+ return NULL;
+}
+
+sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue)
+{
+ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id);
+ if (ue_data.e1_assoc_id == 0) {
+ LOG_W(RRC, "UE %d should be associated to CU-UP, but is not\n", ue->rrc_ue_id);
+ /* we could possibly check the SST/SD from the PDU session */
+ return get_new_cuup_for_ue(rrc, ue, 0, 0);
+ }
+ LOG_D(RRC, "UE %d using CU-UP assoc_id %d\n", ue->rrc_ue_id, ue_data.e1_assoc_id);
+ return ue_data.e1_assoc_id;
+}
+
+sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue, int sst, int sd)
+{
+ /* check if there is already a UE associated */
+ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id);
+ if (ue_data.e1_assoc_id != 0) {
+ LOG_I(RRC, "UE %d using CU-UP assoc_id %d\n", ue->rrc_ue_id, ue_data.e1_assoc_id);
+ return ue_data.e1_assoc_id;
+ }
+
+ /* it is zero -> no CUUP for this UE yet, get the (only) CU-UP that is
+ * connected */
+ if (RB_EMPTY(&rrc->cuups)) {
+ LOG_W(RRC, "no CU-UPs connected: UE %d cannot have a DRB\n", ue->rrc_ue_id);
+ return 0; /* no CUUP connected */
+ }
+
+ const nr_rrc_cuup_container_t *selected = NULL;
+ if (sst != 0) /* only do if there is slice information */
+ selected = select_cuup_slice(&rrc->cuups, ue, sst, sd);
+ if (selected == NULL) /* nothing found yet */
+ selected = select_cuup_round_robin(rrc->num_cuups, &rrc->cuups, ue);
+ if (selected == NULL) {
+ selected = RB_ROOT(&rrc->cuups);
+ }
+ AssertFatal(selected != NULL, "logic error: could not select CU-UP, is one connected?\n");
+
+ /* update the association for the UE so it will be picked up later */
+ ue_data.e1_assoc_id = selected->assoc_id;
+ cu_remove_f1_ue_data(ue->rrc_ue_id);
+ cu_add_f1_ue_data(ue->rrc_ue_id, &ue_data);
+ LOG_I(RRC, "UE %d associating to CU-UP assoc_id %d out of %ld CU-UPs\n", ue->rrc_ue_id, ue_data.e1_assoc_id, rrc->num_cuups);
+
+ return ue_data.e1_assoc_id;
+}
+
+int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req)
+{
+ AssertFatal(req->supported_plmns <= PLMN_LIST_MAX_SIZE, "Supported PLMNs is more than PLMN_LIST_MAX_SIZE\n");
+ gNB_RRC_INST *rrc = RC.nrrrc[0];
+
+ nr_rrc_cuup_container_t *c = NULL;
+ RB_FOREACH(c, rrc_cuup_tree, &rrc->cuups) {
+ if (req->gNB_cu_up_id == c->setup_req->gNB_cu_up_id) {
+ LOG_E(NR_RRC,
+ "Connecting CU-UP ID %ld name %s (assoc_id %d) has same ID as existing CU-UP ID %ld name %s (assoc_id %d)\n",
+ req->gNB_cu_up_id,
+ req->gNB_cu_up_name,
+ assoc_id,
+ c->setup_req->gNB_cu_up_id,
+ c->setup_req->gNB_cu_up_name,
+ c->assoc_id);
+ return -1;
+ }
+ }
+
+ for (int i = 0; i < req->supported_plmns; i++) {
+ PLMN_ID_t *id = &req->plmn[i].id;
+ if (rrc->configuration.mcc[i] != id->mcc || rrc->configuration.mnc[i] != id->mnc) {
+ LOG_E(NR_RRC,
+ "PLMNs received from CUUP (mcc:%d, mnc:%d) did not match with PLMNs in RRC (mcc:%d, mnc:%d)\n",
+ id->mcc,
+ id->mnc,
+ rrc->configuration.mcc[i],
+ rrc->configuration.mnc[i]);
+ return -1;
+ }
+ }
+
+ LOG_I(RRC, "Accepting new CU-UP ID %ld name %s (assoc_id %d)\n", req->gNB_cu_up_id, req->gNB_cu_up_name, assoc_id);
+ nr_rrc_cuup_container_t *cuup = malloc(sizeof(*cuup));
+ AssertFatal(cuup, "out of memory\n");
+ cuup->setup_req = malloc(sizeof(*cuup->setup_req));
+ *cuup->setup_req = *req;
+ cuup->assoc_id = assoc_id;
+ RB_INSERT(rrc_cuup_tree, &rrc->cuups, cuup);
+ rrc->num_cuups++;
+
+ MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, E1AP_SETUP_RESP);
+ msg_p->ittiMsgHeader.originInstance = assoc_id;
+ e1ap_setup_resp_t *resp = &E1AP_SETUP_RESP(msg_p);
+ resp->transac_id = req->transac_id;
+ itti_send_msg_to_task(TASK_CUCP_E1, 0, msg_p);
+
+ return 0;
+}
diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp
index 4367222404..d542dd4b30 100644
--- a/openair3/ocp-gtpu/gtp_itf.cpp
+++ b/openair3/ocp-gtpu/gtp_itf.cpp
@@ -510,7 +510,7 @@ static int udpServerSocket(openAddr_s addr) {
freeaddrinfo(servinfo); // all done with this structure
- if (strlen(addr.destinationHost)>1) {
+ if (false) {
struct addrinfo hints;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_UNSPEC;
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band78.fr1.106PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band78.fr1.106PRB.usrpx310.conf
index 01259ac5a6..aa3e5de456 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band78.fr1.106PRB.usrpx310.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band78.fr1.106PRB.usrpx310.conf
@@ -6,7 +6,7 @@ gNBs =
(
{
////////// Identification parameters:
- gNB_CU_ID = 0xe00;
+ gNB_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band78.fr1.106PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band78.fr1.106PRB.usrpx310.conf
index c2fa1bb623..65a2a49d50 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band78.fr1.106PRB.usrpx310.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band78.fr1.106PRB.usrpx310.conf
@@ -6,7 +6,7 @@ gNBs =
(
{
////////// Identification parameters:
- gNB_CU_ID = 0xe00;
+ gNB_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";