Implement F1AP RRC Version encoding/decoding in CU&DU
RRC Version is a required IE. Hence, implement the encoder and decoder for this message. At the DU and CU, read the RRC Version we use and fill the corresponding field. Co-authored-by: Robert Schmidt <robert.schmidt@openairinterface.org>
This commit is contained in:
committed by
Robert Schmidt
co-authored by
Robert Schmidt
parent
e379291ffd
commit
20710c9a91
@@ -152,7 +152,10 @@ typedef struct f1ap_setup_req_s {
|
|||||||
// F1_Setup_Req payload
|
// F1_Setup_Req payload
|
||||||
uint64_t gNB_DU_id;
|
uint64_t gNB_DU_id;
|
||||||
char *gNB_DU_name;
|
char *gNB_DU_name;
|
||||||
|
|
||||||
|
/// rrc version
|
||||||
|
uint8_t rrc_ver[3];
|
||||||
|
|
||||||
/// number of DU cells available
|
/// number of DU cells available
|
||||||
uint16_t num_cells_available; //0< num_cells_available <= 512;
|
uint16_t num_cells_available; //0< num_cells_available <= 512;
|
||||||
struct {
|
struct {
|
||||||
@@ -188,6 +191,10 @@ typedef struct f1ap_setup_resp_s {
|
|||||||
/// number of DU cells to activate
|
/// number of DU cells to activate
|
||||||
uint16_t num_cells_to_activate; //0< num_cells_to_activate <= 512;
|
uint16_t num_cells_to_activate; //0< num_cells_to_activate <= 512;
|
||||||
served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS];
|
served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS];
|
||||||
|
|
||||||
|
/// rrc version
|
||||||
|
uint8_t rrc_ver[3];
|
||||||
|
|
||||||
} f1ap_setup_resp_t;
|
} f1ap_setup_resp_t;
|
||||||
|
|
||||||
typedef struct f1ap_gnb_cu_configuration_update_s {
|
typedef struct f1ap_gnb_cu_configuration_update_s {
|
||||||
|
|||||||
@@ -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);
|
itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p);
|
||||||
|
|
||||||
return 0;
|
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 */
|
/* encode */
|
||||||
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
|
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||||
LOG_E(F1AP, "Failed to encode F1 setup response\n");
|
LOG_E(F1AP, "Failed to encode F1 setup response\n");
|
||||||
|
|||||||
@@ -289,14 +289,34 @@ int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_setup_req_t *setup_req)
|
|||||||
/* mandatory */
|
/* mandatory */
|
||||||
/* c5. RRC VERSION */
|
/* c5. RRC VERSION */
|
||||||
asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ie2);
|
asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ie2);
|
||||||
ie2->id = F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version;
|
ie2->id = F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version;
|
||||||
ie2->criticality = F1AP_Criticality_reject;
|
ie2->criticality = F1AP_Criticality_reject;
|
||||||
ie2->value.present = F1AP_F1SetupRequestIEs__value_PR_RRC_Version;
|
ie2->value.present = F1AP_F1SetupRequestIEs__value_PR_RRC_Version;
|
||||||
ie2->value.choice.RRC_Version.latest_RRC_Version.buf=calloc(1,sizeof(char));
|
// RRC Version: "This IE is not used in this release."
|
||||||
ie2->value.choice.RRC_Version.latest_RRC_Version.buf[0] = 0xe0;
|
// we put one bit for each byte in rrc_ver that is != 0
|
||||||
ie2->value.choice.RRC_Version.latest_RRC_Version.size = 1;
|
uint8_t bits = 0;
|
||||||
ie2->value.choice.RRC_Version.latest_RRC_Version.bits_unused = 5;
|
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 */
|
/* encode */
|
||||||
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
|
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||||
LOG_E(F1AP, "Failed to encode F1 setup request\n");
|
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,
|
AssertFatal(ie->criticality == F1AP_Criticality_ignore,
|
||||||
"ie->criticality != F1AP_Criticality_ignore\n");
|
"ie->criticality != F1AP_Criticality_ignore\n");
|
||||||
AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name,
|
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);
|
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);
|
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';
|
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;
|
break;
|
||||||
|
|
||||||
case F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version:
|
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;
|
break;
|
||||||
|
|
||||||
case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: {
|
case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: {
|
||||||
|
|||||||
@@ -1175,6 +1175,9 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
|
|||||||
sys_info->sib1_length = (enc_rval.encoded + 7) / 8;
|
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;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
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, "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) {
|
if (resp->num_cells_to_activate == 0) {
|
||||||
LOG_W(NR_MAC, "no cell to activate: cell remains blocked\n");
|
LOG_W(NR_MAC, "no cell to activate: cell remains blocked\n");
|
||||||
|
|||||||
@@ -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);
|
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
F1AP_DU_REGISTER_REQ(msg).net_config = read_DU_IP_config(&RC.nrmac[0]->eth_params_n);
|
||||||
|
|
||||||
|
|||||||
@@ -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, "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
|
// we accept the DU
|
||||||
nr_rrc_du_container_t *du = calloc(1, sizeof(*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,
|
.nr_cellid = cell_info->nr_cellid,
|
||||||
.nrpci = cell_info->nr_pci,
|
.nrpci = cell_info->nr_pci,
|
||||||
.num_SI = 0,
|
.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)
|
if (rrc->node_name != NULL)
|
||||||
resp.gNB_CU_name = strdup(rrc->node_name);
|
resp.gNB_CU_name = strdup(rrc->node_name);
|
||||||
rrc->mac_rrc.f1_setup_response(assoc_id, &resp);
|
rrc->mac_rrc.f1_setup_response(assoc_id, &resp);
|
||||||
|
|||||||
Reference in New Issue
Block a user