diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index e91df060a3..c5ffe0f738 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -152,7 +152,10 @@ typedef struct f1ap_setup_req_s { // F1_Setup_Req payload uint64_t gNB_DU_id; char *gNB_DU_name; - + + /// rrc version + uint8_t rrc_ver[3]; + /// number of DU cells available uint16_t num_cells_available; //0< num_cells_available <= 512; struct { @@ -188,6 +191,10 @@ typedef struct f1ap_setup_resp_s { /// number of DU cells to activate uint16_t num_cells_to_activate; //0< num_cells_to_activate <= 512; served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS]; + + /// rrc version + uint8_t rrc_ver[3]; + } f1ap_setup_resp_t; typedef struct f1ap_gnb_cu_configuration_update_s { diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 509953f3aa..41c783a2db 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -204,6 +204,22 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint3 } } + /* Handle RRC Version */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupRequestIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version, true); + // Latest RRC Version: "This IE is not used in this release." + // BIT_STRING_to_uint8(&ie->value.choice.RRC_Version.latest_RRC_Version); + if (ie->value.choice.RRC_Version.iE_Extensions) { + F1AP_ProtocolExtensionContainer_10696P228_t *ext = + (F1AP_ProtocolExtensionContainer_10696P228_t *)ie->value.choice.RRC_Version.iE_Extensions; + if (ext->list.count > 0) { + F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0]; + OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_; + DevAssert(os->size == 3); + for (int i = 0; i < 3; ++i) + req->rrc_ver[i] = os->buf[i]; + } + } itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p); return 0; @@ -300,6 +316,36 @@ int CU_send_F1_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_setup_resp_t *f1ap_set } } + /* c5. RRC VERSION */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_F1SetupResponseIEs__value_PR_RRC_Version; + // RRC Version: "This IE is not used in this release." + // we put one bit for each byte in rrc_ver that is != 0 + uint8_t bits = 0; + for (int i = 0; i < 3; ++i) + bits |= (f1ap_setup_resp->rrc_ver[i] != 0) << i; + BIT_STRING_t *bs = &ie4->value.choice.RRC_Version.latest_RRC_Version; + bs->buf = calloc(1, sizeof(char)); + AssertFatal(bs->buf != NULL, "out of memory\n"); + bs->buf[0] = bits; + bs->size = 1; + bs->bits_unused = 5; + + F1AP_ProtocolExtensionContainer_10696P228_t *p = (F1AP_ProtocolExtensionContainer_10696P228_t*)calloc(1, sizeof(F1AP_ProtocolExtensionContainer_10696P228_t)); + asn1cSequenceAdd(p->list, F1AP_RRC_Version_ExtIEs_t, rrcv_ext); + rrcv_ext->id = F1AP_ProtocolIE_ID_id_latest_RRC_Version_Enhanced; + rrcv_ext->criticality = F1AP_Criticality_ignore; + rrcv_ext->extensionValue.present = F1AP_RRC_Version_ExtIEs__extensionValue_PR_OCTET_STRING_SIZE_3_; + OCTET_STRING_t *os = &rrcv_ext->extensionValue.choice.OCTET_STRING_SIZE_3_; + os->size = 3; + os->buf = malloc(3 * sizeof(*os->buf)); + AssertFatal(os->buf != NULL, "out of memory\n"); + for (int i = 0; i < 3; ++i) + os->buf[i] = f1ap_setup_resp->rrc_ver[i]; + ie4->value.choice.RRC_Version.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 setup response\n"); diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 322c31e61b..3fa2c1b65d 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -289,14 +289,34 @@ int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_setup_req_t *setup_req) /* mandatory */ /* c5. RRC VERSION */ asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_F1SetupRequestIEs__value_PR_RRC_Version; - ie2->value.choice.RRC_Version.latest_RRC_Version.buf=calloc(1,sizeof(char)); - ie2->value.choice.RRC_Version.latest_RRC_Version.buf[0] = 0xe0; - ie2->value.choice.RRC_Version.latest_RRC_Version.size = 1; - ie2->value.choice.RRC_Version.latest_RRC_Version.bits_unused = 5; + ie2->id = F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_F1SetupRequestIEs__value_PR_RRC_Version; + // RRC Version: "This IE is not used in this release." + // we put one bit for each byte in rrc_ver that is != 0 + uint8_t bits = 0; + for (int i = 0; i < 3; ++i) + bits |= (setup_req->rrc_ver[i] != 0) << i; + BIT_STRING_t *bs = &ie2->value.choice.RRC_Version.latest_RRC_Version; + bs->buf = calloc(1, sizeof(char)); + AssertFatal(bs->buf != NULL, "out of memory\n"); + bs->buf[0] = bits; + bs->size = 1; + bs->bits_unused = 5; + F1AP_ProtocolExtensionContainer_10696P228_t *p = calloc(1, sizeof(F1AP_ProtocolExtensionContainer_10696P228_t)); + asn1cSequenceAdd(p->list, F1AP_RRC_Version_ExtIEs_t, rrcv_ext); + rrcv_ext->id = F1AP_ProtocolIE_ID_id_latest_RRC_Version_Enhanced; + rrcv_ext->criticality = F1AP_Criticality_ignore; + rrcv_ext->extensionValue.present = F1AP_RRC_Version_ExtIEs__extensionValue_PR_OCTET_STRING_SIZE_3_; + OCTET_STRING_t *os = &rrcv_ext->extensionValue.choice.OCTET_STRING_SIZE_3_; + os->size = 3; + os->buf = malloc(3 * sizeof(*os->buf)); + AssertFatal(os->buf != NULL, "out of memory\n"); + for (int i = 0; i < 3; ++i) + os->buf[i] = setup_req->rrc_ver[i]; + ie2->value.choice.RRC_Version.iE_Extensions = (struct F1AP_ProtocolExtensionContainer*)p; + /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 setup request\n"); @@ -343,7 +363,7 @@ int DU_handle_F1_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint AssertFatal(ie->criticality == F1AP_Criticality_ignore, "ie->criticality != F1AP_Criticality_ignore\n"); AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_TransactionID\n"); + "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name\n"); resp.gNB_CU_name = malloc(ie->value.choice.GNB_CU_Name.size+1); memcpy(resp.gNB_CU_name, ie->value.choice.GNB_CU_Name.buf, ie->value.choice.GNB_CU_Name.size); resp.gNB_CU_name[ie->value.choice.GNB_CU_Name.size] = '\0'; @@ -351,7 +371,21 @@ int DU_handle_F1_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint break; case F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version: - LOG_D(F1AP, "F1AP: Received GNB-CU-RRC-Version, ignoring\n"); + AssertFatal(ie->criticality == F1AP_Criticality_reject, + "ie->criticality != F1AP_Criticality_reject\n"); + AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_RRC_Version, + "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_RRC_Version\n"); + // RRC Version: "This IE is not used in this release." + if(ie->value.choice.RRC_Version.iE_Extensions) { + F1AP_ProtocolExtensionContainer_10696P228_t *ext = + (F1AP_ProtocolExtensionContainer_10696P228_t *)ie->value.choice.RRC_Version.iE_Extensions; + if(ext->list.count > 0){ + F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0]; + OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_; + for (int i = 0; i < 3; i++) + resp.rrc_ver[i] = os->buf[i]; + } + } break; case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: { diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 7e102e2a5e..a738012731 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1175,6 +1175,9 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id, sys_info->sib1_length = (enc_rval.encoded + 7) / 8; } + int num = read_version(TO_STRING(NR_RRC_VERSION), &req->rrc_ver[0], &req->rrc_ver[1], &req->rrc_ver[2]); + AssertFatal(num == 3, "could not read RRC version string %s\n", TO_STRING(NR_RRC_VERSION)); + return req; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index ab7977d4dc..c764ece582 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -52,6 +52,7 @@ static bool check_plmn_identity(const f1ap_plmn_t *check_plmn, const f1ap_plmn_t void f1_setup_response(const f1ap_setup_resp_t *resp) { LOG_I(MAC, "received F1 Setup Response from CU %s\n", resp->gNB_CU_name); + LOG_I(MAC, "CU uses RRC version %d.%d.%d\n", resp->rrc_ver[0], resp->rrc_ver[1], resp->rrc_ver[2]); if (resp->num_cells_to_activate == 0) { LOG_W(NR_MAC, "no cell to activate: cell remains blocked\n"); 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 19289597e3..b9ca19300a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -61,6 +61,7 @@ static void f1_setup_request_direct(const f1ap_setup_req_t *req) } } } + memcpy(f1ap_msg->rrc_ver, req->rrc_ver, sizeof(req->rrc_ver)); itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } 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 8ee2913e0c..8e0a04cac8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -93,6 +93,7 @@ static void f1_setup_request_f1ap(const f1ap_setup_req_t *req) } } } + memcpy(f1ap_setup->rrc_ver, req->rrc_ver, sizeof(req->rrc_ver)); F1AP_DU_REGISTER_REQ(msg).net_config = read_DU_IP_config(&RC.nrmac[0]->eth_params_n); diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index a44ca4d6cf..dc78d534e4 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -141,6 +141,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) } } LOG_I(RRC, "Accepting DU %ld (%s), sending F1 Setup Response\n", req->gNB_DU_id, req->gNB_DU_name); + LOG_I(RRC, "DU uses RRC version %u.%u.%u\n", req->rrc_ver[0], req->rrc_ver[1], req->rrc_ver[2]); // we accept the DU nr_rrc_du_container_t *du = calloc(1, sizeof(*du)); @@ -167,8 +168,13 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) .nr_cellid = cell_info->nr_cellid, .nrpci = cell_info->nr_pci, .num_SI = 0, - }; - f1ap_setup_resp_t resp = {.transaction_id = req->transaction_id, .num_cells_to_activate = 1, .cells_to_activate[0] = cell}; + }; + + f1ap_setup_resp_t resp = {.transaction_id = req->transaction_id, + .num_cells_to_activate = 1, + .cells_to_activate[0] = cell}; + int num = read_version(TO_STRING(NR_RRC_VERSION), &resp.rrc_ver[0], &resp.rrc_ver[1], &resp.rrc_ver[2]); + AssertFatal(num == 3, "could not read RRC version string %s\n", TO_STRING(NR_RRC_VERSION)); if (rrc->node_name != NULL) resp.gNB_CU_name = strdup(rrc->node_name); rrc->mac_rrc.f1_setup_response(assoc_id, &resp);