From b5e2c76d930d5621f602714308764d9854043469 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 20 Nov 2023 18:07:54 +0100 Subject: [PATCH 01/17] UE_iterator is a for_each macro, add to clang-format --- .clang-format | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-format b/.clang-format index aa8f087091..a7248821a9 100644 --- a/.clang-format +++ b/.clang-format @@ -61,6 +61,7 @@ ForEachMacros: - Q_FOREACH - BOOST_FOREACH - RB_FOREACH + - UE_iterator IncludeBlocks: Preserve IncludeCategories: - Regex: '^' From 6a91f49e9f740f85f70003b3a00c3a73b22e4b98 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 22 Nov 2023 14:10:31 +0100 Subject: [PATCH 02/17] Fix non-compiling lte-softmodem agent config --- openair2/ENB_APP/enb_config.c | 1 - 1 file changed, 1 deletion(-) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 250b84a710..c57f5205f9 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2944,7 +2944,6 @@ e2_agent_args_t RCconfig_E2agent(void) } return (e2_agent_args_t) { .ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr, - .port = *e2agent_params[E2AGENT_CONFIG_PORT_IDX].u16ptr, .sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr, }; } From 463115bf1968c90fea5aec7ea9eaa415831d4ff5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 23 Nov 2023 07:55:00 +0100 Subject: [PATCH 03/17] Remove redundant config code block --- openair2/GNB_APP/gnb_config.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 4355a12303..5d73b00e8b 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1252,7 +1252,8 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_RRC") == 0) { // check number of instances is same as RRC/PDCP - } else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) { + } else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0 + || strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "cudu") == 0) { printf("Configuring F1 interfaces for MACRLC\n"); RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr)); RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr)); @@ -1264,16 +1265,6 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) ; RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE; macrlc_has_f1 = 1; - } else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "cudu") == 0) { - RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr)); - RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr)); - RC.nrmac[j]->eth_params_n.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr)); - RC.nrmac[j]->eth_params_n.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTC_IDX].iptr); - RC.nrmac[j]->eth_params_n.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr); - RC.nrmac[j]->eth_params_n.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr); - RC.nrmac[j]->eth_params_n.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr); - ; - RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE; } else { // other midhaul AssertFatal(1 == 0, "MACRLC %d: %s unknown northbound midhaul\n", j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr)); } From ec24b9c3e92851c74a52214ab2e19f585765eafe Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 20 Nov 2023 18:38:32 +0100 Subject: [PATCH 04/17] Add License headers to all E2 RAN function files --- .../RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c | 21 +++++++++++++++++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h | 21 +++++++++++++++++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c | 21 +++++++++++++++++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h | 21 +++++++++++++++++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c | 21 +++++++++++++++++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h | 21 +++++++++++++++++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c | 21 +++++++++++++++++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h | 21 +++++++++++++++++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c | 21 +++++++++++++++++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h | 21 +++++++++++++++++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c | 21 +++++++++++++++++++ .../RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h | 21 +++++++++++++++++++ .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 21 +++++++++++++++++++ .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h | 21 +++++++++++++++++++ .../E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c | 21 +++++++++++++++++++ .../E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h | 21 +++++++++++++++++++ openair2/E2AP/RAN_FUNCTION/init_ran_func.c | 21 +++++++++++++++++++ 17 files changed, 357 insertions(+) diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c index 0a14dfe915..ac02a85c05 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c @@ -1,3 +1,24 @@ +/* + * 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 "ran_func_gtp.h" #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h index 0f12aa703a..b69fb7e462 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h @@ -1,3 +1,24 @@ +/* + * 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 RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H #define RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c index 0f690f64c8..099c1bad1c 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c @@ -1,3 +1,24 @@ +/* + * 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 "ran_func_mac.h" #include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_mac.h" #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h index f81c9bc4ef..c32d84433d 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h @@ -1,3 +1,24 @@ +/* + * 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 SM_MAC_READ_WRITE_AGENT_H #define SM_MAC_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c index aa3cb39431..a340c6f499 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c @@ -1,3 +1,24 @@ +/* + * 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 "ran_func_pdcp.h" #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h index 01d70e8250..951cd7373d 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h @@ -1,3 +1,24 @@ +/* + * 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 RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H #define RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c index cb884b03ab..bc9bac5916 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c @@ -1,3 +1,24 @@ +/* + * 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 #include #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h index d49e56e9d3..b2f518e7f6 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h @@ -1,3 +1,24 @@ +/* + * 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 RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H #define RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c index 764cddf28f..b0f81136b0 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c @@ -1,3 +1,24 @@ +/* + * 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 "ran_func_slice.h" #include "../../flexric/test/rnd/fill_rnd_data_slice.h" #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h index 6cbe466bbc..d01f7f2cf2 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h @@ -1,3 +1,24 @@ +/* + * 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 RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H #define RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c index ca3997da7b..6d420fa183 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c @@ -1,3 +1,24 @@ +/* + * 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 "ran_func_tc.h" #include "../../flexric/test/rnd/fill_rnd_data_tc.h" #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h index ab5cc4ba6e..19d655301b 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h @@ -1,3 +1,24 @@ +/* + * 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 RAN_FUNC_SM_TC_READ_WRITE_AGENT_H #define RAN_FUNC_SM_TC_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index dc173cc52f..aa140c8cce 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -1,3 +1,24 @@ +/* + * 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 "ran_func_kpm.h" #include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_kpm.h" #include "openair2/E2AP/flexric/src/util/time_now_us.h" diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h index a8505a1671..9ef9207819 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h @@ -1,3 +1,24 @@ +/* + * 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 RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H #define RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c index d482cfffb6..e05bb3fd7b 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c @@ -1,3 +1,24 @@ +/* + * 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 "ran_func_rc.h" #include "../../flexric/test/rnd/fill_rnd_data_rc.h" #include "../../flexric/src/sm/rc_sm/ie/ir/lst_ran_param.h" diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h index fa8638650f..c7f252971c 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h @@ -1,3 +1,24 @@ +/* + * 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 RAN_FUNC_SM_RAN_CTRL_READ_WRITE_AGENT_H #define RAN_FUNC_SM_RAN_CTRL_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/init_ran_func.c b/openair2/E2AP/RAN_FUNCTION/init_ran_func.c index e7883e1337..abf503c62c 100644 --- a/openair2/E2AP/RAN_FUNCTION/init_ran_func.c +++ b/openair2/E2AP/RAN_FUNCTION/init_ran_func.c @@ -1,3 +1,24 @@ +/* + * 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 "init_ran_func.h" #include "read_setup_ran.h" #include "../flexric/src/agent/e2_agent_api.h" From 6f14b11847057fe0e5206ddad448891160a33879 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 22 Nov 2023 10:43:25 +0100 Subject: [PATCH 05/17] Introduce separate gNB-DU ID in configuration 3GPP has the concept of a gNB-DU ID and a (separate) gNB ID (for gNB, CU). This commit introduces the gNB-DU as a separate ID that has to be set in the configuration file. It is necessary, as some entities, e.g., the e2 agent, need to signal both IDs, e.g., to reconcile a CU and (multiple) DU(s) belonging together. --- .../gnb-du.band78.106prb.rfsim.conf | 1 + .../gnb-du.sa.band78.106prb.rfsim.conf | 1 + .../gnb-du.sa.band78.106prb.usrpb200.conf | 1 + .../5g_f1_rfsimulator/docker-compose.yaml | 4 +-- openair2/GNB_APP/gnb_config.c | 30 +++++++++++++++---- openair2/GNB_APP/gnb_paramdef.h | 10 ++++++- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + .../PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf | 1 + 8 files changed, 40 insertions(+), 9 deletions(-) diff --git a/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf index 94474b86bf..919c1d219f 100644 --- a/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf @@ -7,6 +7,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_DU_ID = 0xe00; # cell_type = "CELL_MACRO_GNB"; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf index 105530c0ba..75d2beed6d 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf @@ -7,6 +7,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_DU_ID = 0xe00; # cell_type = "CELL_MACRO_GNB"; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index f7891902db..f773b2dd33 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -7,6 +7,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_DU_ID = 0xe00; # cell_type = "CELL_MACRO_GNB"; diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index e2c6d7ed0d..1e3b820fa2 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -203,7 +203,7 @@ services: privileged: true container_name: rfsim5g-oai-du2 environment: - USE_ADDITIONAL_OPTIONS: --sa --rfsim --gNBs.[0].gNB_ID 0xe01 --gNBs.[0].nr_cellid 87654321 --gNBs.[0].servingCellConfigCommon.[0].physCellId 1 --MACRLCs.[0].local_n_address 192.168.71.143 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim --gNBs.[0].gNB_DU_ID 0xe01 --gNBs.[0].nr_cellid 87654321 --gNBs.[0].servingCellConfigCommon.[0].physCellId 1 --MACRLCs.[0].local_n_address 192.168.71.143 --log_config.global_log_options level,nocolor,time depends_on: - oai-cu networks: @@ -221,7 +221,7 @@ services: privileged: true container_name: rfsim5g-oai-du3 environment: - USE_ADDITIONAL_OPTIONS: --sa --rfsim --gNBs.[0].gNB_ID 0xe02 --gNBs.[0].nr_cellid 11111111 --gNBs.[0].servingCellConfigCommon.[0].physCellId 2 --MACRLCs.[0].local_n_address 192.168.71.144 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim --gNBs.[0].gNB_DU_ID 0xe02 --gNBs.[0].nr_cellid 11111111 --gNBs.[0].servingCellConfigCommon.[0].physCellId 2 --MACRLCs.[0].local_n_address 192.168.71.144 --log_config.global_log_options level,nocolor,time depends_on: - oai-cu networks: diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 5d73b00e8b..24b2e639b8 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1034,7 +1034,9 @@ static NR_ServingCellConfig_t *get_scd_config(configmodule_interface_t *cfg) } static int read_du_cell_info(configmodule_interface_t *cfg, - uint64_t *id, + bool separate_du, + uint32_t *gnb_id, + uint64_t *gnb_du_id, char **name, f1ap_served_cell_info_t *info, int max_cell_info) @@ -1051,7 +1053,11 @@ static int read_du_cell_info(configmodule_interface_t *cfg, // Output a list of all eNBs. config_getlist(cfg, &GNBParamList, GNBParams, sizeof(GNBParams) / sizeof(paramdef_t), NULL); - AssertFatal(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr != NULL, "gNB id %u is not defined in configuration file\n", 0); + + // read the gNB-ID. The DU itself only needs the gNB-DU ID, but some (e.g., + // E2 agent) need the gNB-ID as well if it is running in a separate process + AssertFatal(config_isparamset(GNBParamList.paramarray[0], GNB_GNB_ID_IDX), "%s is not defined in configuration file\n", GNB_CONFIG_STRING_GNB_ID); + *gnb_id = *GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr; AssertFatal(strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[0], *GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr) == 0, "no active gNB found/mismatch of gNBs: %s vs %s\n", @@ -1068,7 +1074,17 @@ static int read_du_cell_info(configmodule_interface_t *cfg, paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0}; config_getlist(cfg, &PLMNParamList, PLMNParams, sizeof(PLMNParams) / sizeof(paramdef_t), aprefix); - *id = *(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr); + // if fronthaul is F1, require gNB_DU_ID, else use gNB_ID + if (separate_du) { + AssertFatal(config_isparamset(GNBParamList.paramarray[0], GNB_GNB_DU_ID_IDX), "%s is not defined in configuration file\n", GNB_CONFIG_STRING_GNB_DU_ID); + *gnb_du_id = *GNBParamList.paramarray[0][GNB_GNB_DU_ID_IDX].u64ptr; + } else { + AssertFatal(!config_isparamset(GNBParamList.paramarray[0], GNB_GNB_DU_ID_IDX), + "%s should not be defined in configuration file for monolithic gNB\n", + GNB_CONFIG_STRING_GNB_DU_ID); + *gnb_du_id = *gnb_id; // the gNB-DU ID is equal to the gNB ID, since the config has no gNB-DU ID + } + *name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr)); info->tac = malloc(sizeof(*info->tac)); AssertFatal(info->tac != NULL, "out of memory\n"); @@ -1305,10 +1321,11 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) memcpy(RC.nrmac[j]->ulprbbl, prbbl, 275 * sizeof(prbbl[0])); } // for (j=0;jsa) nr_mac_configure_sib1(RC.nrmac[0], &info.plmn, info.nr_cellid, *info.tac); @@ -1317,9 +1334,10 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) // and store it at MAC for sending later NR_BCCH_BCH_Message_t *mib = RC.nrmac[0]->common_channels[0].mib; const NR_BCCH_DL_SCH_Message_t *sib1 = RC.nrmac[0]->common_channels[0].sib1; - f1ap_setup_req_t *req = RC_read_F1Setup(id, name, &info, scc, mib, sib1); + f1ap_setup_req_t *req = RC_read_F1Setup(gnb_du_id, name, &info, scc, mib, sib1); AssertFatal(req != NULL, "could not read F1 Setup information\n"); RC.nrmac[0]->f1_config.setup_req = req; + RC.nrmac[0]->f1_config.gnb_id = gnb_id; free(name); /* read_du_cell_info() allocated memory */ diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index dac12ce70e..faac41fbee 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -127,15 +127,19 @@ typedef enum { #define GNB_CONFIG_STRING_UMONDEFAULTDRB "um_on_default_drb" #define GNB_CONFIG_STRING_FORCE256QAMOFF "force_256qam_off" #define GNB_CONFIG_STRING_ENABLE_SDAP "enable_sdap" +#define GNB_CONFIG_STRING_DRBS "drbs" +#define GNB_CONFIG_STRING_GNB_DU_ID "gNB_DU_ID" + #define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n" #define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support" -#define GNB_CONFIG_STRING_DRBS "drbs" #define GNB_CONFIG_HLP_STRING_DRBS "Number of total DRBs to establish, including the mandatory for PDU SEssion (default=1)\n" +#define GNB_CONFIG_HLP_GNB_DU_ID "defines the gNB-DU ID (only applicable for DU)" /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* cell configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*-----------------------------------------------------------------------------------------------------------------------------------------*/ +// clang-format off #define GNBPARAMS_DESC {\ {GNB_CONFIG_STRING_GNB_ID, NULL, 0, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_CELL_TYPE, NULL, 0, .strptr=NULL, .defstrval="CELL_MACRO_GNB", TYPE_STRING, 0}, \ @@ -165,7 +169,10 @@ typedef enum { {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}, \ +{GNB_CONFIG_STRING_GNB_DU_ID, GNB_CONFIG_HLP_GNB_DU_ID, 0, .u64ptr=NULL, .defint64val=1, TYPE_UINT64, 0}, \ } +// clang-format on + #define GNB_GNB_ID_IDX 0 #define GNB_CELL_TYPE_IDX 1 @@ -195,6 +202,7 @@ typedef enum { #define GNB_FORCE256QAMOFF_IDX 25 #define GNB_ENABLE_SDAP_IDX 26 #define GNB_DRBS 27 +#define GNB_GNB_DU_ID_IDX 28 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define GNBPARAMS_CHECK { \ diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index b205abafd0..26a24c203e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -730,6 +730,7 @@ typedef bool (*nr_pp_impl_ul)(module_id_t mod_id, typedef struct f1_config_t { f1ap_setup_req_t *setup_req; f1ap_setup_resp_t *setup_resp; + uint32_t gnb_id; // associated gNB's ID, not used in DU itself } f1_config_t; /*! \brief top level eNB MAC structure */ diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf index 67fa7726dc..f3c95f1bc7 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf @@ -7,6 +7,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_DU_ID = 0xe00; # cell_type = "CELL_MACRO_GNB"; From 79c920cd811ce992ab7d9e5ddf6b26228a24ba80 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 22 Nov 2023 17:33:31 +0100 Subject: [PATCH 06/17] Introduce separate gNB-CU-UP ID in configuration 3GPP has the concept of a gNB-CU-UP ID and a (separate) gNB ID (for gNB, CU-CP). This commit introduces the gNB-CU-UP as a separate ID that has to be set in the configuration file when running as a CU-UP. For the CU/monolithic gNB, it is optional (but needs to be the same as the gNB-ID if specified). The CU-UP ID is necessary, as some entities, e.g., the e2 agent, need to signal both IDs, e.g., to reconcile a CU-CP and (multiple) CU-UP(s) belonging together. --- ci-scripts/conf_files/gnb-cuup.sa.f1.conf | 1 + .../conf_files/gnb-cuup.sa.f1.quectel.conf | 1 + executables/nr-cuup.c | 3 +- executables/nr-softmodem.c | 4 +-- openair2/COMMON/e1ap_messages_types.h | 1 + openair2/E1AP/e1ap.c | 4 +-- openair2/E1AP/e1ap_common.c | 3 +- openair2/E1AP/e1ap_common.h | 3 +- openair2/E1AP/e1ap_setup.c | 34 +++++++++++++++---- openair2/GNB_APP/gnb_app.c | 3 +- openair2/GNB_APP/gnb_config.h | 2 +- openair2/GNB_APP/gnb_paramdef.h | 4 +++ 12 files changed, 47 insertions(+), 16 deletions(-) diff --git a/ci-scripts/conf_files/gnb-cuup.sa.f1.conf b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf index 357518bcf2..d6c54f0b9a 100644 --- a/ci-scripts/conf_files/gnb-cuup.sa.f1.conf +++ b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf @@ -8,6 +8,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_CU_UP_ID = 0xe00; # cell_type = "CELL_MACRO_GNB"; 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 4e65547db9..7a2fc7db21 100644 --- a/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf +++ b/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf @@ -8,6 +8,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_CU_UP_ID = 0xe00; # cell_type = "CELL_MACRO_GNB"; diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 1e6c22a337..5fb66bc73a 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -130,7 +130,8 @@ int main(int argc, char **argv) AssertFatal(rc >= 0, "Create task for CUUP E1 failed\n"); 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); + E1_t e1type = UPtype; + MessageDef *msg = RCconfig_NR_CU_E1(&e1type); AssertFatal(msg != NULL, "Send init to task for E1AP UP failed\n"); itti_send_msg_to_task(TASK_CUUP_E1, 0, msg); diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index edead47430..d97ec3a10d 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -402,9 +402,9 @@ static int create_gNB_tasks(ngran_node_t node_type, configmodule_interface_t *cf // If CU if (node_type == ngran_gNB_CU || node_type == ngran_gNB) { - MessageDef *msg = RCconfig_NR_CU_E1(false); + MessageDef *msg = RCconfig_NR_CU_E1(NULL); instance_t inst = 0; - createE1inst(UPtype, inst, &E1AP_REGISTER_REQ(msg).net_config, NULL); + createE1inst(UPtype, inst, E1AP_REGISTER_REQ(msg).gnb_id, &E1AP_REGISTER_REQ(msg).net_config, NULL); cuup_init_n3(inst); RC.nrrrc[gnb_id_start]->e1_inst = inst; // stupid instance !!!*/ diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index c50efd337f..dba73dd8b9 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -87,6 +87,7 @@ typedef struct e1ap_setup_req_s { typedef struct e1ap_register_req_t { e1ap_setup_req_t setup_req; e1ap_net_config_t net_config; + uint32_t gnb_id; // unused in CU-UP, but might be necessary for some functionality, e.g., E2 agent } e1ap_register_req_t; typedef struct e1ap_setup_resp_s { diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 077c67ca98..2aeb873c71 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -1801,7 +1801,7 @@ 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)) - createE1inst(type, instance, NULL, NULL); + createE1inst(type, instance, 0, NULL, NULL); e1ap_upcp_inst_t *inst = getCxtE1(instance); inst->sockState = SCTP_STATE_ESTABLISHED; if (type == UPtype) @@ -1897,7 +1897,7 @@ void *E1AP_CUUP_task(void *arg) { switch (msgType) { case E1AP_REGISTER_REQ: { e1ap_register_req_t *reg_req = &E1AP_REGISTER_REQ(msg); - createE1inst(UPtype, myInstance, ®_req->net_config, ®_req->setup_req); + createE1inst(UPtype, myInstance, reg_req->gnb_id, ®_req->net_config, ®_req->setup_req); e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, ®_req->net_config); } break; diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c index cf8982339d..984c3de887 100644 --- a/openair2/E1AP/e1ap_common.c +++ b/openair2/E1AP/e1ap_common.c @@ -37,12 +37,13 @@ e1ap_upcp_inst_t *getCxtE1(instance_t instance) return e1ap_inst[instance]; } -void createE1inst(E1_t type, instance_t instance, e1ap_net_config_t *nc, e1ap_setup_req_t *req) +void createE1inst(E1_t type, instance_t instance, uint64_t gnb_id, 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; + e1ap_inst[instance]->gnb_id = gnb_id; e1ap_inst[instance]->cuup.assoc_id = -1; if (nc) memcpy(&e1ap_inst[instance]->net_config, nc, sizeof(*nc)); diff --git a/openair2/E1AP/e1ap_common.h b/openair2/E1AP/e1ap_common.h index e0aea6990f..4acc606bec 100644 --- a/openair2/E1AP/e1ap_common.h +++ b/openair2/E1AP/e1ap_common.h @@ -29,6 +29,7 @@ typedef struct e1ap_upcp_inst_s { instance_t instance; + uint32_t gnb_id; // associated gNB's ID, unused in E1 but necessary for e.g. E2 agent E1_t type; enum sctp_state_e sockState; struct { @@ -52,7 +53,7 @@ e1ap_upcp_inst_t *getCxtE1(instance_t instance); long E1AP_get_next_transaction_identifier(); void E1AP_free_transaction_identifier(long id); -void createE1inst(E1_t type, instance_t instance, e1ap_net_config_t *nc, e1ap_setup_req_t *req); +void createE1inst(E1_t type, instance_t instance, uint64_t gnb_id, e1ap_net_config_t *nc, e1ap_setup_req_t *req); int e1ap_encode_send(E1_t type, sctp_assoc_t assoc_id, struct E1AP_E1AP_PDU *pdu, uint16_t stream, const char *func); diff --git a/openair2/E1AP/e1ap_setup.c b/openair2/E1AP/e1ap_setup.c index f80a3962a6..70f90b9a56 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) return; } -MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process) +MessageDef *RCconfig_NR_CU_E1(const E1_t *entity) { MessageDef *msgConfig = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_REGISTER_REQ); if (!msgConfig) @@ -82,14 +82,12 @@ MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process) sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; AssertFatal(num_gnbs == 1, "Support only one gNB per process\n"); + config_getlist(config_get_if(), &GNBParamList, GNBParams, sizeofArray(GNBParams), NULL); + paramdef_t *gnbParms = GNBParamList.paramarray[0]; + e1ap_setup_req_t *e1Setup = &E1AP_REGISTER_REQ(msgConfig).setup_req; if (num_gnbs > 0) { - config_getlist(config_get_if(), &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_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); @@ -132,7 +130,11 @@ MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process) get_NGU_S1U_addr(&e1ap_nc->localAddressN3, &e1ap_nc->localPortN3); e1ap_nc->remotePortN3 = e1ap_nc->localPortN3 ; - if (separate_CUUP_process) { + AssertFatal(config_isparamset(gnbParms, GNB_GNB_ID_IDX), "%s is not defined in configuration file\n", GNB_CONFIG_STRING_GNB_ID); + uint32_t gnb_id = *gnbParms[GNB_GNB_ID_IDX].uptr; + E1AP_REGISTER_REQ(msgConfig).gnb_id = gnb_id; + + if (entity != NULL) { paramlist_def_t GNBE1ParamList = {GNB_CONFIG_STRING_E1_PARAMETERS, NULL, 0}; paramdef_t GNBE1Params[] = GNBE1PARAMS_DESC; config_getlist(config_get_if(), &GNBE1ParamList, GNBE1Params, sizeofArray(GNBE1Params), aprefix); @@ -141,6 +143,24 @@ MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process) 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; + if (*entity == CPtype) { + // CP needs gNB_ID (although not used, but other parts check it as + // well), and gNB-CU-UP ID should NOT be present as it comes through E1! + AssertFatal(!config_isparamset(gnbParms, GNB_GNB_CU_UP_ID_IDX), "%s must not be defined in configuration file\n", GNB_CONFIG_STRING_GNB_CU_UP_ID); + } else { // UPtype + AssertFatal(config_isparamset(gnbParms, GNB_GNB_CU_UP_ID_IDX), "%s is not be defined in configuration file\n", GNB_CONFIG_STRING_GNB_CU_UP_ID); + e1Setup->gNB_cu_up_id = *gnbParms[GNB_GNB_CU_UP_ID_IDX].u64ptr; + } + } else { + // integrated CU-CP/UP. We don't care about the gNB-CU-UP ID that much, + // but if it's there, check it's the same as gNB ID + uint64_t *gnb_cu_up_id = gnbParms[GNB_GNB_CU_UP_ID_IDX].u64ptr; + AssertFatal(!config_isparamset(gnbParms, GNB_GNB_CU_UP_ID_IDX) || *gnb_cu_up_id == gnb_id, + "%s is different of %s: they need to match or remove %s from config\n", + GNB_CONFIG_STRING_GNB_CU_UP_ID, + GNB_CONFIG_STRING_GNB_ID, + GNB_CONFIG_STRING_GNB_CU_UP_ID); + e1Setup->gNB_cu_up_id = gnb_id; } } return msgConfig; diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 74a8a997bd..e2c0b48bd4 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -146,7 +146,8 @@ void *gNB_app_task(void *args_p) if (node_type == ngran_gNB_CUCP) { 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); + E1_t e1type = CPtype; + MessageDef *msg = RCconfig_NR_CU_E1(&e1type); 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 diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index 1238296045..d02b5eb4f5 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -107,7 +107,7 @@ int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i); int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i); void wait_f1_setup_response(void); int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update); -MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process); +MessageDef *RCconfig_NR_CU_E1(const E1_t *entity); ngran_node_t get_node_type(void); #ifdef E2_AGENT diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index faac41fbee..e07a89d305 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -129,11 +129,13 @@ typedef enum { #define GNB_CONFIG_STRING_ENABLE_SDAP "enable_sdap" #define GNB_CONFIG_STRING_DRBS "drbs" #define GNB_CONFIG_STRING_GNB_DU_ID "gNB_DU_ID" +#define GNB_CONFIG_STRING_GNB_CU_UP_ID "gNB_CU_UP_ID" #define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n" #define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support" #define GNB_CONFIG_HLP_STRING_DRBS "Number of total DRBs to establish, including the mandatory for PDU SEssion (default=1)\n" #define GNB_CONFIG_HLP_GNB_DU_ID "defines the gNB-DU ID (only applicable for DU)" +#define GNB_CONFIG_HLP_GNB_CU_UP_ID "defines the gNB-CU-UP ID (only applicable for CU-UP)" /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* cell configuration parameters */ @@ -170,6 +172,7 @@ typedef enum { {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}, \ {GNB_CONFIG_STRING_GNB_DU_ID, GNB_CONFIG_HLP_GNB_DU_ID, 0, .u64ptr=NULL, .defint64val=1, TYPE_UINT64, 0}, \ +{GNB_CONFIG_STRING_GNB_CU_UP_ID, GNB_CONFIG_HLP_GNB_CU_UP_ID, 0, .u64ptr=NULL, .defint64val=1, TYPE_UINT64, 0}, \ } // clang-format on @@ -203,6 +206,7 @@ typedef enum { #define GNB_ENABLE_SDAP_IDX 26 #define GNB_DRBS 27 #define GNB_GNB_DU_ID_IDX 28 +#define GNB_GNB_CU_UP_ID_IDX 29 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define GNBPARAMS_CHECK { \ From 7c6c4fc7d351b9d4e6edd2e68905bebc15387a3d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 20 Nov 2023 16:54:10 +0100 Subject: [PATCH 07/17] Start E2 agent only if configuration present This commit introduces an additional (implicit) option that signals if the E2 agent is to be activated or not. When reading the configuration, we now check if all fields are set, and activate the E2 agent only if this is the case. If not, we only print a warning and start the gNB without the agent. Note that previously, if not all fields are set correctly, the gNB stopped. To implement this behavior, it is necessary to change the defaults of the RIC IP and the directory for SMs to a (non-NULL) default value. Otherwise, the configuration system would not consider the field to be set to the default, and wrongly assumes the field is set, even though it is not; at least, this change is necessary to make config_isparamset() return NULL if the configuration is not set. --- executables/nr-softmodem.c | 84 ++++++++++++++++++--------------- openair2/E2AP/e2_agent_arg.h | 1 + openair2/ENB_APP/enb_config.c | 11 +++++ openair2/ENB_APP/enb_paramdef.h | 5 +- openair2/GNB_APP/gnb_config.c | 9 +++- 5 files changed, 68 insertions(+), 42 deletions(-) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index d97ec3a10d..29cb7caeda 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -571,6 +571,50 @@ void init_pdcp(void) { } } +#ifdef E2_AGENT +static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args) +{ + AssertFatal(oai_args.sm_dir != NULL , "Please, specify the directory where the SMs are located in the config file, i.e., add in config file the next line: e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\");} "); + AssertFatal(oai_args.ip != NULL , "Please, specify the IP address of the nearRT-RIC in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\""); + + printf("After RCconfig_NR_E2agent %s %s \n",oai_args.sm_dir, oai_args.ip ); + + fr_args_t args = { .ip = oai_args.ip }; // init_fr_args(0, NULL); + memcpy(args.libs_dir, oai_args.sm_dir, 128); + + sleep(1); + const gNB_RRC_INST* rrc = RC.nrrrc[0]; + assert(rrc != NULL && "rrc cannot be NULL"); + + const int mcc = rrc->configuration.mcc[0]; + const int mnc = rrc->configuration.mnc[0]; + const int mnc_digit_len = rrc->configuration.mnc_digit_length[0]; + // const ngran_node_t node_type = rrc->node_type; + int nb_id = 0; + int cu_du_id = 0; + if (node_type == ngran_gNB) { + nb_id = rrc->nr_cellid; + } else if (node_type == ngran_gNB_DU) { + AssertFatal(rrc->node_id != 0, "cannot handle node ID 0, please change gNB_ID\n"); + cu_du_id = rrc->node_id; + nb_id = rrc->nr_cellid; + } else if (node_type == ngran_gNB_CU) { + AssertFatal(rrc->node_id != 0, "cannot handle node ID 0, please change gNB_ID\n"); + cu_du_id = rrc->node_id; + nb_id = rrc->nr_cellid; + } else { + LOG_E(NR_RRC, "not supported ran type detect\n"); + } + + printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nb_id = %d \n", mcc, mnc, mnc_digit_len, nb_id); + + printf("[E2 NODE]: Args %s %s \n", args.ip, args.libs_dir); + + sm_io_ag_ran_t io = init_ran_func_ag(); + init_agent_api(mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args); +} +#endif + configmodule_interface_t *uniqCfg = NULL; int main( int argc, char **argv ) { int ru_id, CC_id = 0; @@ -689,54 +733,18 @@ int main( int argc, char **argv ) { config_sync_var=0; - - #ifdef E2_AGENT ////////////////////////////////// ////////////////////////////////// //// Init the E2 Agent - sm_io_ag_ran_t io = init_ran_func_ag(); - // OAI Wrapper e2_agent_args_t oai_args = RCconfig_NR_E2agent(); - AssertFatal(oai_args.sm_dir != NULL , "Please, specify the directory where the SMs are located in the config file, i.e., add in config file the next line: e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\");} "); - AssertFatal(oai_args.ip != NULL , "Please, specify the IP address of the nearRT-RIC in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\""); - - printf("After RCconfig_NR_E2agent %s %s \n",oai_args.sm_dir, oai_args.ip ); - - fr_args_t args = { .ip = oai_args.ip }; // init_fr_args(0, NULL); - memcpy(args.libs_dir, oai_args.sm_dir, 128); - - sleep(1); - const gNB_RRC_INST* rrc = RC.nrrrc[0]; - assert(rrc != NULL && "rrc cannot be NULL"); - - const int mcc = rrc->configuration.mcc[0]; - const int mnc = rrc->configuration.mnc[0]; - const int mnc_digit_len = rrc->configuration.mnc_digit_length[0]; - // const ngran_node_t node_type = rrc->node_type; - int nb_id = 0; - int cu_du_id = 0; - if (node_type == ngran_gNB) { - nb_id = rrc->configuration.cell_identity; - } else if (node_type == ngran_gNB_DU) { - cu_du_id = rrc->node_id + 1; // Hack to avoid been 0 - nb_id = rrc->configuration.cell_identity; - } else if (node_type == ngran_gNB_CU) { - cu_du_id = rrc->node_id + 1; - nb_id = rrc->configuration.cell_identity; - } else { - LOG_E(NR_RRC, "not supported ran type detect\n"); + if (oai_args.enabled) { + initialize_agent(node_type, oai_args); } - - printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nb_id = %d \n", mcc, mnc, mnc_digit_len, nb_id); - - printf("[E2 NODE]: Args %s %s \n", args.ip, args.libs_dir); - init_agent_api(mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args); -// } #endif // E2_AGENT diff --git a/openair2/E2AP/e2_agent_arg.h b/openair2/E2AP/e2_agent_arg.h index b719c32d97..30f1ce4750 100644 --- a/openair2/E2AP/e2_agent_arg.h +++ b/openair2/E2AP/e2_agent_arg.h @@ -28,6 +28,7 @@ typedef struct{ const char *ip; const char *sm_dir; + const bool enabled; } e2_agent_args_t; #endif diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index c57f5205f9..a360369c94 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2942,7 +2942,18 @@ e2_agent_args_t RCconfig_E2agent(void) LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters\n", CONFIG_STRING_E2AGENT); return (e2_agent_args_t) {0}; } + + bool enabled = config_isparamset(e2agent_params, E2AGENT_CONFIG_SMDIR_IDX) + && config_isparamset(e2agent_params, E2AGENT_CONFIG_IP_IDX); + if (!enabled) { + LOG_W(GNB_APP, "E2 agent is DISABLED (for activation, define .%s.{%s,%s} parameters)\n", CONFIG_STRING_E2AGENT, E2AGENT_CONFIG_IP, E2AGENT_CONFIG_SMDIR); + return (e2_agent_args_t) { + .enabled = false, + }; + } + return (e2_agent_args_t) { + .enabled = true, .ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr, .sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr, }; diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index 6417d3cb75..626705317b 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -1330,9 +1330,8 @@ typedef struct srb1_params_s { //#define E2AGENT_CONFIG_PORT "port" #define E2AGENT_CONFIG_SMDIR "sm_dir" -static const char* const e2agent_config_ip_default = NULL; -static const char* const e2agent_config_smdir_default = NULL; -//static const uint16_t e2agent_config_port_default = 36421; +static const char* const e2agent_config_ip_default = "127.0.0.1"; +static const char* const e2agent_config_smdir_default = "."; #define E2AGENT_PARAMS_DESC { \ {E2AGENT_CONFIG_IP, "RIC IP address", 0, strptr:NULL, defstrval:(char*)e2agent_config_ip_default, TYPE_STRING, 0}, \ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 24b2e639b8..17e74f4608 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -2281,7 +2281,14 @@ e2_agent_args_t RCconfig_NR_E2agent(void) LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters from FlexRIC\n", CONFIG_STRING_E2AGENT); return (e2_agent_args_t) { 0 }; } - e2_agent_args_t dst = {0}; + + bool enabled = config_isparamset(e2agent_params, E2AGENT_CONFIG_SMDIR_IDX) + && config_isparamset(e2agent_params, E2AGENT_CONFIG_IP_IDX); + e2_agent_args_t dst = {.enabled = enabled}; + if (!enabled) { + LOG_W(GNB_APP, "E2 agent is DISABLED (for activation, define .%s.{%s,%s} parameters)\n", CONFIG_STRING_E2AGENT, E2AGENT_CONFIG_IP, E2AGENT_CONFIG_SMDIR); + return dst; + } if (e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL) dst.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr; From deac180224bb82e96d5051ab99cf8b3e770d84fd Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 22 Nov 2023 18:53:47 +0100 Subject: [PATCH 08/17] Set correct gNB/gnB-DU/gNB-CU-UP ID for agent start --- executables/nr-softmodem.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 29cb7caeda..aa8dd6025e 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -572,6 +572,7 @@ void init_pdcp(void) { } #ifdef E2_AGENT +#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" // need to get info from MAC static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args) { AssertFatal(oai_args.sm_dir != NULL , "Please, specify the directory where the SMs are located in the config file, i.e., add in config file the next line: e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\");} "); @@ -593,15 +594,17 @@ static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args) int nb_id = 0; int cu_du_id = 0; if (node_type == ngran_gNB) { - nb_id = rrc->nr_cellid; + nb_id = rrc->node_id; } else if (node_type == ngran_gNB_DU) { - AssertFatal(rrc->node_id != 0, "cannot handle node ID 0, please change gNB_ID\n"); - cu_du_id = rrc->node_id; - nb_id = rrc->nr_cellid; + const gNB_MAC_INST* mac = RC.nrmac[0]; + AssertFatal(mac != NULL, "MAC not initialized\n"); + cu_du_id = mac->f1_config.gnb_id; + nb_id = mac->f1_config.setup_req->gNB_DU_id; } else if (node_type == ngran_gNB_CU) { - AssertFatal(rrc->node_id != 0, "cannot handle node ID 0, please change gNB_ID\n"); + // agent buggy: the CU has no second ID, it is the CU-UP ID + // however, that is not a problem her for us, so put the same ID twice + nb_id = rrc->node_id; cu_du_id = rrc->node_id; - nb_id = rrc->nr_cellid; } else { LOG_E(NR_RRC, "not supported ran type detect\n"); } From 5168ef72d9a77a7ce1604fb5a78fea89ca0e0e9d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 21 Nov 2023 11:29:00 +0100 Subject: [PATCH 09/17] E2 agent: remove broken NSSAI filtering, simplify code Filtering UEs by NSSAI is broken, so remove it. A later commit will reestablish this functionality. Simplify the code: we only handle one condition, so we can check for it upfront. --- .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 51 +++---------------- 1 file changed, 7 insertions(+), 44 deletions(-) diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index aa140c8cce..275e1a6d82 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -48,37 +48,12 @@ matched_ues_mac_t filter_ues_by_s_nssai_in_du_or_monolithic(test_cond_e const co /* IMPORTANT: in the case of gNB-DU, it is not possible to filter UEs by S-NSSAI as the ngap context is stored in gNB-CU instead, we take all connected UEs*/ + AssertFatal(condition == EQUAL_TEST_COND, "Condition %d not yet implemented", condition); // Take MAC info - UE_iterator(RC.nrmac[0]->UE_info.list, ue) - { - if (ue) - { - ngap_gNB_ue_context_t *ngap_ue_context_list = NULL; - - // Filter connected UEs by S-NSSAI test condition to get list of matched UEs - // note: not possible to filter - switch (condition) - { - case EQUAL_TEST_COND: - { - if (NODE_IS_MONOLITHIC(RC.nrrrc[0]->node_type)) - { - rrc_gNB_ue_context_t *rrc_ue_context_list = rrc_gNB_get_ue_context_by_rnti_any_du(RC.nrrrc[0], ue->rnti); - ngap_ue_context_list = ngap_get_ue_context(rrc_ue_context_list->ue_context.rrc_ue_id); - assert(ngap_ue_context_list->gNB_instance[0].s_nssai[0][0].sST == value && "Please, check the condition for S-NSSAI. At the moment, OAI supports eMBB"); - } - matched_ues.ue_list[matched_ues.num_ues] = *ue; - matched_ues.num_ues++; - break; - } - - - default: - assert(false && "Condition not yet implemented"); - } - - } + UE_iterator (RC.nrmac[0]->UE_info.list, ue) { + matched_ues.ue_list[matched_ues.num_ues] = *ue; + matched_ues.num_ues++; } assert(matched_ues.num_ues >= 1 && "The number of filtered UEs must be at least equal to 1"); @@ -99,24 +74,12 @@ matched_ues_rrc_t filter_ues_by_s_nssai_in_cu(test_cond_e const condition, int64 matched_ues_rrc_t matched_ues = {.num_ues = 0, .rrc_ue_id_list = calloc(MAX_MOBILES_PER_GNB, sizeof(f1_ue_data_t)) }; assert(matched_ues.rrc_ue_id_list != NULL && "Memory exhausted"); + AssertFatal(condition == EQUAL_TEST_COND, "Condition %d not yet implemented\n", condition); struct rrc_gNB_ue_context_s *ue_context_p1 = NULL; RB_FOREACH(ue_context_p1, rrc_nr_ue_tree_s, &RC.nrrrc[0]->rrc_ue_head) { - - ngap_gNB_ue_context_t *ngap_ue_context_list = ngap_get_ue_context(ue_context_p1->ue_context.rrc_ue_id); - - // Filter connected UEs by S-NSSAI test condition to get list of matched UEs - switch (condition) - { - case EQUAL_TEST_COND: - assert(ngap_ue_context_list->gNB_instance[0].s_nssai[0][0].sST == value && "Please, check the condition for S-NSSAI. At the moment, OAI supports eMBB"); - matched_ues.rrc_ue_id_list[matched_ues.num_ues].secondary_ue = ue_context_p1->ue_context.rrc_ue_id; - matched_ues.num_ues++; - break; - - default: - assert(false && "Condition not yet implemented"); - } + matched_ues.rrc_ue_id_list[matched_ues.num_ues].secondary_ue = ue_context_p1->ue_context.rrc_ue_id; + matched_ues.num_ues++; } assert(matched_ues.num_ues >= 1 && "The number of filtered UEs must be at least equal to 1"); From 89b776925de8788a64af0890765a092e4d472cf9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 21 Nov 2023 13:02:21 +0100 Subject: [PATCH 10/17] E2 agent: fix memory leak by not allocating memory Prior to this commit, the RAN function for KPM is leaking memory: it allocates using calloc() but never frees it. The fix consists of not allocating this memory on the heap in the first place, but on the stack. Therefore, there are changes to pass in a pointer to various functions to the structure on the stack, instead of passing the "container" for the heap memory by value. Further, the MAC was allocating an excessive amount of memory (N times sizeof(NR_UE_info_t)). Instead of copying the entire struct, the present code stores a pointer to the MAC UE container (NR_UE_info_t *). For the RRC, there is a similar simplification that consists in not storing the entire struct f1_ue_data_t (which is not required), but only the RRC UE ID. Note that both MAC and RRC might suffer from race conditions. For the MAC, we should lock the scheduler for the time we read statistics. For the RRC, the problem is more delicate as no mutex exists; the RRC assumes everything is executed synchronously in the ITTI task loop. In both cases, this commit does not address this problem --- .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index 275e1a6d82..6ddd7560b1 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -35,56 +35,51 @@ typedef struct { - NR_UE_info_t *ue_list; - size_t num_ues; + NR_UE_info_t* ue_list[MAX_MOBILES_PER_GNB]; + size_t num_ues; } matched_ues_mac_t; - -static -matched_ues_mac_t filter_ues_by_s_nssai_in_du_or_monolithic(test_cond_e const condition, int64_t const value) +static size_t filter_ues_by_s_nssai_in_du_or_monolithic(test_cond_e const condition, + int64_t const value, + matched_ues_mac_t* matches) { - matched_ues_mac_t matched_ues = {.num_ues = 0, .ue_list = calloc(MAX_MOBILES_PER_GNB, sizeof(NR_UE_info_t)) }; - assert(matched_ues.ue_list != NULL && "Memory exhausted"); - - /* IMPORTANT: in the case of gNB-DU, it is not possible to filter UEs by S-NSSAI as the ngap context is stored in gNB-CU - instead, we take all connected UEs*/ + DevAssert(matches != NULL); AssertFatal(condition == EQUAL_TEST_COND, "Condition %d not yet implemented", condition); // Take MAC info + size_t i = 0; UE_iterator (RC.nrmac[0]->UE_info.list, ue) { - matched_ues.ue_list[matched_ues.num_ues] = *ue; - matched_ues.num_ues++; + matches->ue_list[i++] = ue; + AssertFatal(i < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n"); } - assert(matched_ues.num_ues >= 1 && "The number of filtered UEs must be at least equal to 1"); - - return matched_ues; + matches->num_ues = i; + assert(matches->num_ues >= 1 && "The number of filtered UEs must be at least equal to 1"); + return i; } typedef struct { - f1_ue_data_t * rrc_ue_id_list; // list of matched UEs on RRC level containing only rrc_ue_id (gNB CU UE ID) + uint32_t rrc_ue_id_list[MAX_MOBILES_PER_GNB]; // list of matched UEs on RRC level containing only rrc_ue_id (gNB CU UE ID) size_t num_ues; } matched_ues_rrc_t; -static -matched_ues_rrc_t filter_ues_by_s_nssai_in_cu(test_cond_e const condition, int64_t const value) +static size_t filter_ues_by_s_nssai_in_cu(test_cond_e const condition, int64_t const value, matched_ues_rrc_t* matches) { - matched_ues_rrc_t matched_ues = {.num_ues = 0, .rrc_ue_id_list = calloc(MAX_MOBILES_PER_GNB, sizeof(f1_ue_data_t)) }; - assert(matched_ues.rrc_ue_id_list != NULL && "Memory exhausted"); - + DevAssert(matches != NULL); AssertFatal(condition == EQUAL_TEST_COND, "Condition %d not yet implemented\n", condition); struct rrc_gNB_ue_context_s *ue_context_p1 = NULL; + size_t i = 0; RB_FOREACH(ue_context_p1, rrc_nr_ue_tree_s, &RC.nrrrc[0]->rrc_ue_head) { - matched_ues.rrc_ue_id_list[matched_ues.num_ues].secondary_ue = ue_context_p1->ue_context.rrc_ue_id; - matched_ues.num_ues++; + matches->rrc_ue_id_list[i++] = ue_context_p1->ue_context.rrc_ue_id; + AssertFatal(i < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n"); } - - assert(matched_ues.num_ues >= 1 && "The number of filtered UEs must be at least equal to 1"); - - return matched_ues; + + matches->num_ues = i; + assert(matches->num_ues >= 1 && "The number of filtered UEs must be at least equal to 1"); + return i; } static @@ -382,8 +377,8 @@ kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1_in_du(const NR_UE_info_t* UE, cons return msg_frm_1; } -static -kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_du(const matched_ues_mac_t matched_ues, const kpm_act_def_format_1_t * act_def_fr_1) +static kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_du(const matched_ues_mac_t* matched_ues, + const kpm_act_def_format_1_t* act_def_fr_1) { assert(act_def_fr_1 != NULL); @@ -391,20 +386,20 @@ kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_du(const matched_ues_mac_t matc kpm_ind_msg_format_3_t msg_frm_3 = {0}; // Fill UE Measurement Reports - - msg_frm_3.ue_meas_report_lst_len = matched_ues.num_ues; + + msg_frm_3.ue_meas_report_lst_len = matched_ues->num_ues; msg_frm_3.meas_report_per_ue = calloc(msg_frm_3.ue_meas_report_lst_len, sizeof(meas_report_per_ue_t)); assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted"); for (size_t i = 0; iue_list[i]->rnti); // get gNB CU UE ID as rrc_ue_id msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.type = GNB_DU_UE_ID_E2SM; msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.gnb_du = fill_gnb_du_data(&rrc_ue_id); // Fill UE related info - msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1_in_du(&matched_ues.ue_list[i], i, act_def_fr_1); + msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1_in_du(matched_ues->ue_list[i], i, act_def_fr_1); } @@ -465,8 +460,8 @@ kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1_in_cu(const uint32_t rrc_ue_id, co return msg_frm_1; } -static -kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_cu(const matched_ues_rrc_t matched_ues, const kpm_act_def_format_1_t * act_def_fr_1) +static kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_cu(const matched_ues_rrc_t* matched_ues, + const kpm_act_def_format_1_t* act_def_fr_1) { assert(act_def_fr_1 != NULL); @@ -474,20 +469,21 @@ kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_cu(const matched_ues_rrc_t matc kpm_ind_msg_format_3_t msg_frm_3 = {0}; // Fill UE Measurement Reports - - msg_frm_3.ue_meas_report_lst_len = matched_ues.num_ues; + + msg_frm_3.ue_meas_report_lst_len = matched_ues->num_ues; msg_frm_3.meas_report_per_ue = calloc(msg_frm_3.ue_meas_report_lst_len, sizeof(meas_report_per_ue_t)); assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted"); for (size_t i = 0; irrc_ue_id_list[i]); msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.type = GNB_UE_ID_E2SM; msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.gnb = fill_gnb_data(rrc_ue_context_list); // Fill UE related info - msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1_in_cu(matched_ues.rrc_ue_id_list[i].secondary_ue, i, act_def_fr_1); + msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = + fill_kpm_ind_msg_frm_1_in_cu(matched_ues->rrc_ue_id_list[i], i, act_def_fr_1); } return msg_frm_3; @@ -555,8 +551,8 @@ kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1_in_monolithic(const NR_UE_info_t* return msg_frm_1; } -static -kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_monolithic(const matched_ues_mac_t matched_ues, const kpm_act_def_format_1_t * act_def_fr_1) +static kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_monolithic(const matched_ues_mac_t* matched_ues, + const kpm_act_def_format_1_t* act_def_fr_1) { assert(act_def_fr_1 != NULL); @@ -564,8 +560,8 @@ kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_monolithic(const matched_ues_ma kpm_ind_msg_format_3_t msg_frm_3 = {0}; // Fill UE Measurement Reports - - msg_frm_3.ue_meas_report_lst_len = matched_ues.num_ues; + + msg_frm_3.ue_meas_report_lst_len = matched_ues->num_ues; msg_frm_3.meas_report_per_ue = calloc(msg_frm_3.ue_meas_report_lst_len, sizeof(meas_report_per_ue_t)); assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted"); @@ -573,12 +569,13 @@ kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_monolithic(const matched_ues_ma for (size_t i = 0; iue_list[i]->rnti); msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.type = GNB_UE_ID_E2SM; msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.gnb = fill_gnb_data(rrc_ue_context_list); // Fill UE related info - msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1_in_monolithic(&matched_ues.ue_list[i], i, rrc_ue_context_list->ue_context.rrc_ue_id, act_def_fr_1); + msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = + fill_kpm_ind_msg_frm_1_in_monolithic(matched_ues->ue_list[i], i, rrc_ue_context_list->ue_context.rrc_ue_id, act_def_fr_1); } return msg_frm_3; @@ -736,14 +733,17 @@ void read_kpm_sm(void* data) int64_t const value = *frm_4->matching_cond_lst[i].test_info_lst.int_value; // Check E2 Node NG-RAN Type if (NODE_IS_DU(RC.nrrrc[0]->node_type)) { - matched_ues_mac_t matched_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, value); - kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_du(matched_ues, &frm_4->action_def_format_1); + matched_ues_mac_t matched_ues = {0}; + matched_ues.num_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, value, &matched_ues); + kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_du(&matched_ues, &frm_4->action_def_format_1); } else if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { - matched_ues_rrc_t matched_ues = filter_ues_by_s_nssai_in_cu(test_cond, value); - kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_cu(matched_ues, &frm_4->action_def_format_1); + matched_ues_rrc_t matched_ues = {0}; + matched_ues.num_ues = filter_ues_by_s_nssai_in_cu(test_cond, value, &matched_ues); + kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_cu(&matched_ues, &frm_4->action_def_format_1); } else if (NODE_IS_MONOLITHIC(RC.nrrrc[0]->node_type)) { - matched_ues_mac_t matched_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, value); - kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_monolithic(matched_ues, &frm_4->action_def_format_1); + matched_ues_mac_t matched_ues = {0}; + matched_ues.num_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, value, &matched_ues); + kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_monolithic(&matched_ues, &frm_4->action_def_format_1); } else { assert(false && "NG-RAN Type not implemented"); } From e13a4813ee54dfdd567f902323611397657fb653 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 21 Nov 2023 14:52:43 +0100 Subject: [PATCH 11/17] E2 Agent: Match UEs based on NSSAI Correctly match UEs based on the NSSAI in MAC and RRC. There is a convenience function capture_sst_sd() that extracts SST and SD (which form the NSSAI). Because a previous version used integers to convey the slice identifier, this function gracefully handles this case, although it is not spec-compliant. --- .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 78 +++++++++++++++++-- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index 6ddd7560b1..562cc715d8 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -39,8 +39,19 @@ typedef struct { size_t num_ues; } matched_ues_mac_t; +static bool nssai_matches(nssai_t a_nssai, uint8_t b_sst, const uint32_t *b_sd) +{ + AssertFatal(b_sd == NULL || *b_sd <= 0xffffff, "illegal SD %d\n", *b_sd); + if (b_sd == NULL) { + return a_nssai.sst == b_sst && a_nssai.sd == 0xffffff; + } else { + return a_nssai.sst == b_sst && a_nssai.sd == *b_sd; + } +} + static size_t filter_ues_by_s_nssai_in_du_or_monolithic(test_cond_e const condition, - int64_t const value, + uint8_t sst, + const uint32_t *sd, matched_ues_mac_t* matches) { DevAssert(matches != NULL); @@ -49,7 +60,15 @@ static size_t filter_ues_by_s_nssai_in_du_or_monolithic(test_cond_e const condit // Take MAC info size_t i = 0; UE_iterator (RC.nrmac[0]->UE_info.list, ue) { - matches->ue_list[i++] = ue; + NR_UE_sched_ctrl_t *sched_ctrl = &ue->UE_sched_ctrl; + // UE matches if any of its DRBs matches + for (int l = 0; l < sched_ctrl->dl_lc_num; ++l) { + long lcid = sched_ctrl->dl_lc_ids[l]; + if (nssai_matches(sched_ctrl->dl_lc_nssai[lcid], sst, sd)) { + matches->ue_list[i++] = ue; + break; + } + } AssertFatal(i < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n"); } @@ -65,7 +84,7 @@ typedef struct { } matched_ues_rrc_t; -static size_t filter_ues_by_s_nssai_in_cu(test_cond_e const condition, int64_t const value, matched_ues_rrc_t* matches) +static size_t filter_ues_by_s_nssai_in_cu(test_cond_e const condition, uint8_t sst, const uint32_t *sd, matched_ues_rrc_t* matches) { DevAssert(matches != NULL); AssertFatal(condition == EQUAL_TEST_COND, "Condition %d not yet implemented\n", condition); @@ -73,7 +92,14 @@ static size_t filter_ues_by_s_nssai_in_cu(test_cond_e const condition, int64_t c struct rrc_gNB_ue_context_s *ue_context_p1 = NULL; size_t i = 0; RB_FOREACH(ue_context_p1, rrc_nr_ue_tree_s, &RC.nrrrc[0]->rrc_ue_head) { - matches->rrc_ue_id_list[i++] = ue_context_p1->ue_context.rrc_ue_id; + gNB_RRC_UE_t *ue = &ue_context_p1->ue_context; + for (int p = 0; p < ue->nb_of_pdusessions; ++p) { + pdusession_t *pdu = &ue->pduSession[0].param; + if (nssai_matches(pdu->nssai, sst, sd)) { + matches->rrc_ue_id_list[i++] = ue_context_p1->ue_context.rrc_ue_id; + break; + } + } AssertFatal(i < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n"); } @@ -655,6 +681,39 @@ kpm_ind_hdr_t kpm_ind_hdr(void) return hdr; } +static void capture_sst_sd(test_info_lst_t* test, uint8_t *sst, uint32_t **sd) +{ + DevAssert(test != NULL && test->test_cond_value != NULL); + DevAssert(sst != NULL); + DevAssert(sd != NULL); + + // we made a mistake in the past: NSSAI is supposed to be an OCTET_STRING, + // but earlier version of the RAN function and the xApp used integer, so + // handle this gracefully by accepting integer as well + switch (*test->test_cond_value) { + case INTEGER_TEST_COND_VALUE: + AssertFatal(*test->int_value <= 0xff, "illegal SST %ld\n", *test->int_value); + *sst = *test->int_value; + *sd = NULL; + break; + case OCTET_STRING_TEST_COND_VALUE: + if (test->octet_string_value->len == 1) { + *sst = test->octet_string_value->buf[0]; + *sd = NULL; + } else { + DevAssert(test->octet_string_value->len == 4); + uint8_t *buf = test->octet_string_value->buf; + *sst = buf[0]; + *sd = malloc(**sd); + **sd = buf[1] << 16 | buf[2] << 8 | buf[3]; + } + break; + default: + AssertFatal(false, "test condition value %d impossible\n", *test->test_cond_value); + break; + } +} + void read_kpm_sm(void* data) { assert(data != NULL); @@ -730,23 +789,26 @@ void read_kpm_sm(void* data) assert(frm_4->matching_cond_lst[i].test_info_lst.int_value != NULL && "Even though is optional.."); test_cond_e const test_cond = *frm_4->matching_cond_lst[i].test_info_lst.test_cond; - int64_t const value = *frm_4->matching_cond_lst[i].test_info_lst.int_value; + uint8_t sst = 0; + uint32_t *sd = NULL; + capture_sst_sd(&frm_4->matching_cond_lst[i].test_info_lst, &sst, &sd); // Check E2 Node NG-RAN Type if (NODE_IS_DU(RC.nrrrc[0]->node_type)) { matched_ues_mac_t matched_ues = {0}; - matched_ues.num_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, value, &matched_ues); + matched_ues.num_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, sst, sd, &matched_ues); kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_du(&matched_ues, &frm_4->action_def_format_1); } else if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { matched_ues_rrc_t matched_ues = {0}; - matched_ues.num_ues = filter_ues_by_s_nssai_in_cu(test_cond, value, &matched_ues); + matched_ues.num_ues = filter_ues_by_s_nssai_in_cu(test_cond, sst, sd, &matched_ues); kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_cu(&matched_ues, &frm_4->action_def_format_1); } else if (NODE_IS_MONOLITHIC(RC.nrrrc[0]->node_type)) { matched_ues_mac_t matched_ues = {0}; - matched_ues.num_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, value, &matched_ues); + matched_ues.num_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, sst, sd, &matched_ues); kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_monolithic(&matched_ues, &frm_4->action_def_format_1); } else { assert(false && "NG-RAN Type not implemented"); } + free(sd); // if NULL, nothing happens break; } From 107c0c8d651f911c9553a0245ea57f7f31d005ac Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 21 Nov 2023 17:45:50 +0100 Subject: [PATCH 12/17] Reformat Dockerfile.build.ubuntu20 --- docker/Dockerfile.build.ubuntu20 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile.build.ubuntu20 b/docker/Dockerfile.build.ubuntu20 index 807b7d258a..e0de481e38 100644 --- a/docker/Dockerfile.build.ubuntu20 +++ b/docker/Dockerfile.build.ubuntu20 @@ -35,4 +35,9 @@ COPY . . RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ - ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope nrqtscope" -w USRP -t Ethernet --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror + ./build_oai -c --ninja \ + --eNB --gNB --RU --UE --nrUE \ + --build-lib "telnetsrv enbscope uescope nrscope nrqtscope" \ + -w USRP -t Ethernet \ + --noavx512 \ + --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror From 41c491a0fa4a24df554a4e2827c42f2371f05f0e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 21 Nov 2023 17:49:13 +0100 Subject: [PATCH 13/17] Update E2 Agent submodule: use special FlexRIC commit before v2 --- openair2/E2AP/README.md | 2 +- openair2/E2AP/flexric | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md index 9042e5ed79..c496605f2f 100644 --- a/openair2/E2AP/README.md +++ b/openair2/E2AP/README.md @@ -89,7 +89,7 @@ git submodule update ```bash git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric cd flexric/ -git checkout 035fd2e8f9a9d2c16df8d44c9e8c13ccddf9ff19 +git checkout 93961d2480b2c7a5721e03435cb34cf9446d1ad1 ``` ### 2.2.2 Build FlexRIC diff --git a/openair2/E2AP/flexric b/openair2/E2AP/flexric index 035fd2e8f9..93961d2480 160000 --- a/openair2/E2AP/flexric +++ b/openair2/E2AP/flexric @@ -1 +1 @@ -Subproject commit 035fd2e8f9a9d2c16df8d44c9e8c13ccddf9ff19 +Subproject commit 93961d2480b2c7a5721e03435cb34cf9446d1ad1 From aec6170df492363e574b5315596e7a93046ef4d5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 21 Nov 2023 18:07:24 +0100 Subject: [PATCH 14/17] Build E2 agent in Ubuntu images --- docker/Dockerfile.build.ubuntu20 | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/Dockerfile.build.ubuntu20 b/docker/Dockerfile.build.ubuntu20 index e0de481e38..1579bab6f7 100644 --- a/docker/Dockerfile.build.ubuntu20 +++ b/docker/Dockerfile.build.ubuntu20 @@ -39,5 +39,6 @@ RUN /bin/sh oaienv && \ --eNB --gNB --RU --UE --nrUE \ --build-lib "telnetsrv enbscope uescope nrscope nrqtscope" \ -w USRP -t Ethernet \ + --build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF \ --noavx512 \ --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror From 39df275fa47feec2e0a8d3ebec01c7813980258b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 29 Nov 2023 19:23:16 +0100 Subject: [PATCH 15/17] Remove confusing macrlc_has_f1 variable The macrlc_has_f1 (static) variable was introduced to signal when we use F1 in the configuration. It is superfluous: the node_type already passes this information in a unique manner; hence, remove. --- openair2/GNB_APP/gnb_config.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 17e74f4608..3f7e06bc3d 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -93,7 +93,6 @@ #include "nfapi/oai_integration/vendor_ext.h" extern uint16_t sf_ahead; -int macrlc_has_f1 = 0; // synchronization raster per band tables (Rel.15) // (38.101-1 Table 5.4.3.3-1 and 38.101-2 Table 5.4.3.3-1) @@ -1278,9 +1277,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) RC.nrmac[j]->eth_params_n.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr); RC.nrmac[j]->eth_params_n.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr); RC.nrmac[j]->eth_params_n.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr); - ; RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE; - macrlc_has_f1 = 1; } else { // other midhaul AssertFatal(1 == 0, "MACRLC %d: %s unknown northbound midhaul\n", j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr)); } @@ -1325,7 +1322,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) uint32_t gnb_id = 0; char *name = NULL; f1ap_served_cell_info_t info; - read_du_cell_info(cfg, macrlc_has_f1, &gnb_id, &gnb_du_id, &name, &info, 1); + read_du_cell_info(cfg, NODE_IS_DU(node_type), &gnb_id, &gnb_du_id, &name, &info, 1); if (get_softmodem_params()->sa) nr_mac_configure_sib1(RC.nrmac[0], &info.plmn, info.nr_cellid, *info.tac); @@ -2251,7 +2248,7 @@ ngran_node_t get_node_type(void) RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt; for (int j = 0; j < RC.nb_nr_macrlc_inst; j++) { if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) { - macrlc_has_f1 = 1; + return ngran_gNB_DU; // MACRLCs present in config: it must be a DU } } } @@ -2265,10 +2262,9 @@ ngran_node_t get_node_type(void) return ngran_gNB_CUUP; else return ngran_gNB_CU; - } else if (macrlc_has_f1 == 0) + } else { return ngran_gNB; - else - return ngran_gNB_DU; + } } #ifdef E2_AGENT From 6104dbc7498740f3249f97f24eb0de9510b321c9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 29 Nov 2023 19:23:25 +0100 Subject: [PATCH 16/17] Documentation: add description when it is DU, CU, gNB --- doc/F1-design.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/F1-design.md b/doc/F1-design.md index 2666856a42..916c1a2edf 100644 --- a/doc/F1-design.md +++ b/doc/F1-design.md @@ -116,6 +116,14 @@ sudo cmake_targets/ran_build/build/nr-softmodem --sa -O ci-scripts/conf_files/gn These files are tested in the CI, and are configured for use in docker, see [this `docker-compose` file](../ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml). +The rules to decide if a config triggers a start of a DU, CU, or monolithic +gNB, are, in order: +1. If the `MACRLCs` section lists `f1` as northbound transport preference + (`tr_n_preference`), it is a DU. +2. If the `gNBs` section lists `f1` as a southound transport preference + (`tr_s_preference`), it is a CU. +3. It is a (monolithic) gNB. + ## Configuration of F1 IP/port information For a local deployment, you should update the following fields. From 8e990850c3a4763c4d6891f028c5b5aa534f1703 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 30 Nov 2023 17:10:08 +0100 Subject: [PATCH 17/17] Correctly read node_id (gNB ID) for RRC The node ID (which corresponds to the gNB ID) should be read in all cases of execution, not only CU. --- openair2/GNB_APP/gnb_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 3f7e06bc3d..de0373e37a 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1556,12 +1556,12 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc) printf("NRRRC %u: Southbound Transport %s\n",i,*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr)); rrc->node_type = get_node_type(); + rrc->node_id = gnb_id; if (NODE_IS_CU(rrc->node_type)) { paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC; 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(config_get_if(), SCTPParams, sizeofArray(SCTPParams), aprefix); - 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);