Commit c19bdb77 authored by Robert Schmidt's avatar Robert Schmidt

add UE Context Setup Req at CU/DU

- add message sender (CU) + handler (CU) and fill with data from ITTI message
- add PLMNID_TO_MCC_MNC and BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4 macros
- correct TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING:
  change name to TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING, make it send 4B, not 5
parent d9661177
...@@ -39,6 +39,7 @@ MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_r ...@@ -39,6 +39,7 @@ MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_r
/* RRC -> F1AP messages */ /* RRC -> F1AP messages */
MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message ) MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message )
//MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_req_t , f1ap_initial_context_setup_req ) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_req_t , f1ap_initial_context_setup_req )
MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_req_t, f1ap_ue_context_setup_req)
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#ifndef F1AP_MESSAGES_TYPES_H_ #ifndef F1AP_MESSAGES_TYPES_H_
#define F1AP_MESSAGES_TYPES_H_ #define F1AP_MESSAGES_TYPES_H_
#include "rlc.h"
//-------------------------------------------------------------------------------------------// //-------------------------------------------------------------------------------------------//
// Defines to access message fields. // Defines to access message fields.
...@@ -33,6 +35,7 @@ ...@@ -33,6 +35,7 @@
#define F1AP_INITIAL_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_initial_ul_rrc_message #define F1AP_INITIAL_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_initial_ul_rrc_message
#define F1AP_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ul_rrc_message #define F1AP_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ul_rrc_message
#define F1AP_UE_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_req
#define F1AP_UE_CONTEXT_RELEASE_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_resp #define F1AP_UE_CONTEXT_RELEASE_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_resp
#define F1AP_UE_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_resp #define F1AP_UE_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_resp
#define F1AP_UE_CONTEXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_fail #define F1AP_UE_CONTEXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_fail
...@@ -249,8 +252,31 @@ typedef struct f1ap_ul_rrc_message_s { ...@@ -249,8 +252,31 @@ typedef struct f1ap_ul_rrc_message_s {
int rrc_container_length; int rrc_container_length;
} f1ap_ul_rrc_message_t; } f1ap_ul_rrc_message_t;
/*typedef struct f1ap_ue_context_setup_req_s { typedef struct f1ap_up_tnl_s {
in_addr_t tl_address; // currently only IPv4 supported
uint32_t gtp_teid;
} f1ap_up_tnl_t;
typedef struct f1ap_drb_to_be_setup_s {
uint8_t drb_id;
f1ap_up_tnl_t up_ul_tnl[2];
uint8_t up_ul_tnl_length;
rlc_mode_t rlc_mode;
} f1ap_drb_to_be_setup_t;
} f1ap_ue_context_setup_req_t;*/ typedef struct f1ap_ue_context_setup_req_s {
uint32_t gNB_CU_ue_id;
uint32_t *gNB_DU_ue_id;
// SpCell Info
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
uint64_t nr_cellid;
uint32_t servCellId;
uint8_t *cu_to_du_rrc_information;
uint8_t cu_to_du_rrc_information_length;
f1ap_drb_to_be_setup_t *drbs_to_be_setup;
uint8_t drbs_to_be_setup_length;
} f1ap_ue_context_setup_req_t;
#endif /* F1AP_MESSAGES_TYPES_H_ */ #endif /* F1AP_MESSAGES_TYPES_H_ */
...@@ -633,12 +633,12 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_ ...@@ -633,12 +633,12 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_
F1AP_CP_TransportLayerAddress_t transportLayerAddress; F1AP_CP_TransportLayerAddress_t transportLayerAddress;
memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address; transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address;
TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address); TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address);
// memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
// transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port; // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port;
// transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t)); // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t));
// TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address); // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address);
gnb_cu_tnl_association_to_add_item.tNLAssociationTransportLayerAddress = transportLayerAddress; gnb_cu_tnl_association_to_add_item.tNLAssociationTransportLayerAddress = transportLayerAddress;
...@@ -680,12 +680,12 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_ ...@@ -680,12 +680,12 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_
F1AP_CP_TransportLayerAddress_t transportLayerAddress; F1AP_CP_TransportLayerAddress_t transportLayerAddress;
memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address; transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address;
TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address); TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address);
// memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
// transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port; // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port;
// transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t)); // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t));
// TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address); // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address);
gnb_cu_tnl_association_to_remove_item.tNLAssociationTransportLayerAddress = transportLayerAddress; gnb_cu_tnl_association_to_remove_item.tNLAssociationTransportLayerAddress = transportLayerAddress;
...@@ -722,12 +722,12 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_ ...@@ -722,12 +722,12 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_
F1AP_CP_TransportLayerAddress_t transportLayerAddress; F1AP_CP_TransportLayerAddress_t transportLayerAddress;
memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address; transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address;
TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address); TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address);
// memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t));
// transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port; // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port;
// transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t)); // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t));
// TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address); // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address);
gnb_cu_tnl_association_to_update_item.tNLAssociationTransportLayerAddress = transportLayerAddress; gnb_cu_tnl_association_to_update_item.tNLAssociationTransportLayerAddress = transportLayerAddress;
......
...@@ -36,20 +36,17 @@ ...@@ -36,20 +36,17 @@
#include "f1ap_itti_messaging.h" #include "f1ap_itti_messaging.h"
#include "f1ap_cu_ue_context_management.h" #include "f1ap_cu_ue_context_management.h"
//void CU_send_UE_CONTEXT_SETUP_REQUEST(F1AP_UEContextSetupRequest_t *UEContextSetupRequest) { extern f1ap_setup_req_t *f1ap_du_data_from_du;
int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance,
f1ap_ue_context_setup_req_t *f1ap_ue_context_setup_req) {
F1AP_F1AP_PDU_t pdu; F1AP_F1AP_PDU_t pdu;
F1AP_UEContextSetupRequest_t *out; F1AP_UEContextSetupRequest_t *out;
F1AP_UEContextSetupRequestIEs_t *ie; F1AP_UEContextSetupRequestIEs_t *ie;
uint8_t *buffer; uint8_t *buffer;
uint32_t len; uint32_t len;
int i = 0; int i = 0, j = 0;
// for test
int mcc = 208;
int mnc = 93;
int mnc_digit_length = 8;
/* Create */ /* Create */
/* 0. Message Type */ /* 0. Message Type */
...@@ -67,17 +64,17 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -67,17 +64,17 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
ie->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; ie->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID;
ie->criticality = F1AP_Criticality_reject; ie->criticality = F1AP_Criticality_reject;
ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID;
ie->value.choice.GNB_CU_UE_F1AP_ID = 126L; ie->value.choice.GNB_CU_UE_F1AP_ID = f1ap_ue_context_setup_req->gNB_CU_ue_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* optional */ /* optional */
/* c2. GNB_DU_UE_F1AP_ID */ /* c2. GNB_DU_UE_F1AP_ID */
if (0) { if (f1ap_ue_context_setup_req->gNB_DU_ue_id) {
ie = (F1AP_UEContextSetupRequestIEs_t *)calloc(1, sizeof(F1AP_UEContextSetupRequestIEs_t)); ie = (F1AP_UEContextSetupRequestIEs_t *)calloc(1, sizeof(F1AP_UEContextSetupRequestIEs_t));
ie->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; ie->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID;
ie->criticality = F1AP_Criticality_ignore; ie->criticality = F1AP_Criticality_ignore;
ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID;
ie->value.choice.GNB_DU_UE_F1AP_ID = 651L; ie->value.choice.GNB_DU_UE_F1AP_ID = *f1ap_ue_context_setup_req->gNB_DU_ue_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
} }
...@@ -89,9 +86,11 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -89,9 +86,11 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_NRCGI; ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_NRCGI;
/* - nRCGI */ /* - nRCGI */
F1AP_NRCGI_t nRCGI; F1AP_NRCGI_t nRCGI;
MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length, MCC_MNC_TO_PLMNID(f1ap_ue_context_setup_req->mcc,
f1ap_ue_context_setup_req->mnc,
f1ap_ue_context_setup_req->mnc_digit_length,
&nRCGI.pLMN_Identity); &nRCGI.pLMN_Identity);
NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity); NR_CELL_ID_TO_BIT_STRING(f1ap_ue_context_setup_req->nr_cellid, &nRCGI.nRCellIdentity);
ie->value.choice.NRCGI = nRCGI; ie->value.choice.NRCGI = nRCGI;
...@@ -141,7 +140,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -141,7 +140,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_Candidate_SpCell_List; ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_Candidate_SpCell_List;
for (i=0; for (i=0;
i<1; i<0;
i++) { i++) {
F1AP_Candidate_SpCell_ItemIEs_t *candidate_spCell_item_ies; F1AP_Candidate_SpCell_ItemIEs_t *candidate_spCell_item_ies;
...@@ -156,9 +155,12 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -156,9 +155,12 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
/* - candidate_SpCell_ID */ /* - candidate_SpCell_ID */
F1AP_NRCGI_t nRCGI; F1AP_NRCGI_t nRCGI;
MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length, /* TODO add correct mcc/mnc */
MCC_MNC_TO_PLMNID(f1ap_ue_context_setup_req->mcc,
f1ap_ue_context_setup_req->mnc,
f1ap_ue_context_setup_req->mnc_digit_length,
&nRCGI.pLMN_Identity); &nRCGI.pLMN_Identity);
NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity); NR_CELL_ID_TO_BIT_STRING(f1ap_ue_context_setup_req->nr_cellid, &nRCGI.nRCellIdentity);
candidate_spCell_item.candidate_SpCell_ID = nRCGI; candidate_spCell_item.candidate_SpCell_ID = nRCGI;
...@@ -198,7 +200,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -198,7 +200,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
ie->value.choice.ResourceCoordinationTransferContainer.buf = malloc(4); ie->value.choice.ResourceCoordinationTransferContainer.buf = malloc(4);
ie->value.choice.ResourceCoordinationTransferContainer.size = 4; ie->value.choice.ResourceCoordinationTransferContainer.size = 4;
*ie->value.choice.ResourceCoordinationTransferContainer.buf = "123"; strncpy(ie->value.choice.ResourceCoordinationTransferContainer.buf, "123", 3);
OCTET_STRING_fromBuf(&ie->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as", OCTET_STRING_fromBuf(&ie->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as",
...@@ -215,7 +217,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -215,7 +217,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SCell_ToBeSetup_List; ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SCell_ToBeSetup_List;
for (i=0; for (i=0;
i<1; i<0;
i++) { i++) {
// //
F1AP_SCell_ToBeSetup_ItemIEs_t *scell_toBeSetup_item_ies; F1AP_SCell_ToBeSetup_ItemIEs_t *scell_toBeSetup_item_ies;
...@@ -230,7 +232,10 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -230,7 +232,10 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
// /* - sCell_ID */ // /* - sCell_ID */
F1AP_NRCGI_t nRCGI; F1AP_NRCGI_t nRCGI;
MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length, /* TODO correct MCC/MNC */
MCC_MNC_TO_PLMNID(f1ap_ue_context_setup_req->mcc,
f1ap_ue_context_setup_req->mnc,
f1ap_ue_context_setup_req->mnc_digit_length,
&nRCGI.pLMN_Identity); &nRCGI.pLMN_Identity);
NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity); NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity);
...@@ -254,7 +259,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -254,7 +259,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List; ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List;
for (i=0; for (i=0;
i<1; i<0;
i++) { i++) {
// //
F1AP_SRBs_ToBeSetup_ItemIEs_t *srbs_toBeSetup_item_ies; F1AP_SRBs_ToBeSetup_ItemIEs_t *srbs_toBeSetup_item_ies;
...@@ -284,9 +289,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -284,9 +289,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
ie->criticality = F1AP_Criticality_reject; ie->criticality = F1AP_Criticality_reject;
ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List; ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List;
for (i=0; for (i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; i++) {
i<1;
i++) {
// //
F1AP_DRBs_ToBeSetup_ItemIEs_t *drbs_toBeSetup_item_ies; F1AP_DRBs_ToBeSetup_ItemIEs_t *drbs_toBeSetup_item_ies;
drbs_toBeSetup_item_ies = (F1AP_DRBs_ToBeSetup_ItemIEs_t *)calloc(1, sizeof(F1AP_DRBs_ToBeSetup_ItemIEs_t)); drbs_toBeSetup_item_ies = (F1AP_DRBs_ToBeSetup_ItemIEs_t *)calloc(1, sizeof(F1AP_DRBs_ToBeSetup_ItemIEs_t));
...@@ -299,7 +302,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -299,7 +302,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
memset((void *)&drbs_toBeSetup_item, 0, sizeof(F1AP_DRBs_ToBeSetup_Item_t)); memset((void *)&drbs_toBeSetup_item, 0, sizeof(F1AP_DRBs_ToBeSetup_Item_t));
/* dRBID */ /* dRBID */
drbs_toBeSetup_item.dRBID = 30L; drbs_toBeSetup_item.dRBID = f1ap_ue_context_setup_req->drbs_to_be_setup[i].drb_id;
/* qoSInformation */ /* qoSInformation */
drbs_toBeSetup_item.qoSInformation.present = F1AP_QoSInformation_PR_eUTRANQoS; drbs_toBeSetup_item.qoSInformation.present = F1AP_QoSInformation_PR_eUTRANQoS;
...@@ -307,22 +310,20 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -307,22 +310,20 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
drbs_toBeSetup_item.qoSInformation.choice.eUTRANQoS->qCI = 254L; drbs_toBeSetup_item.qoSInformation.choice.eUTRANQoS->qCI = 254L;
/* ULTunnels_ToBeSetup_List */ /* ULTunnels_ToBeSetup_List */
int maxnoofULTunnels = 1; // 2; for (j = 0; j < f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) {
for (i=0; f1ap_up_tnl_t *up_tnl = &f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j];
i<maxnoofULTunnels;
i++) {
/* ULTunnels_ToBeSetup_Item */ /* ULTunnels_ToBeSetup_Item */
F1AP_ULUPTNLInformation_ToBeSetup_Item_t *uLUPTNLInformation_ToBeSetup_Item; F1AP_ULUPTNLInformation_ToBeSetup_Item_t *uLUPTNLInformation_ToBeSetup_Item;
// gTPTunnel // gTPTunnel
uLUPTNLInformation_ToBeSetup_Item = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)calloc(1, sizeof(F1AP_ULUPTNLInformation_ToBeSetup_Item_t)); uLUPTNLInformation_ToBeSetup_Item = calloc(1, sizeof(F1AP_ULUPTNLInformation_ToBeSetup_Item_t));
uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present =
F1AP_UPTransportLayerInformation_PR_gTPTunnel;
F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t)); F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t));
TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(up_tnl->tl_address, &gTPTunnel->transportLayerAddress);
OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1234", INT32_TO_OCTET_STRING(up_tnl->gtp_teid, &gTPTunnel->gTP_TEID);
strlen("1234"));
uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel = gTPTunnel; uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel = gTPTunnel;
...@@ -330,7 +331,14 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) { ...@@ -330,7 +331,14 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance) {
} }
/* rLCMode */ /* rLCMode */
drbs_toBeSetup_item.rLCMode = F1AP_RLCMode_rlc_um; // enum /* TODO use rlc_mode from f1ap_drb_to_be_setup */
switch (f1ap_ue_context_setup_req->drbs_to_be_setup[i].rlc_mode) {
case RLC_MODE_AM:
drbs_toBeSetup_item.rLCMode = F1AP_RLCMode_rlc_am;
break;
default:
drbs_toBeSetup_item.rLCMode = F1AP_RLCMode_rlc_um;
}
/* OPTIONAL */ /* OPTIONAL */
/* ULConfiguration */ /* ULConfiguration */
...@@ -445,7 +453,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { ...@@ -445,7 +453,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) {
/* optional */ /* optional */
/* c3. NRCGI */ /* c3. NRCGI */
if (1) { if (0) {
ie = (F1AP_UEContextModificationRequestIEs_t *)calloc(1, sizeof(F1AP_UEContextModificationRequestIEs_t)); ie = (F1AP_UEContextModificationRequestIEs_t *)calloc(1, sizeof(F1AP_UEContextModificationRequestIEs_t));
ie->id = F1AP_ProtocolIE_ID_id_SpCell_ID; ie->id = F1AP_ProtocolIE_ID_id_SpCell_ID;
ie->criticality = F1AP_Criticality_ignore; ie->criticality = F1AP_Criticality_ignore;
...@@ -703,7 +711,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { ...@@ -703,7 +711,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) {
uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel;
F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t)); F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t));
TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "4567", OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "4567",
strlen("4567")); strlen("4567"));
...@@ -771,7 +779,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { ...@@ -771,7 +779,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) {
uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel;
F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t)); F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t));
TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204", OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204",
strlen("1204")); strlen("1204"));
......
...@@ -36,7 +36,8 @@ ...@@ -36,7 +36,8 @@
/* /*
* UE Context Setup * UE Context Setup
*/ */
int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance); int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance,
f1ap_ue_context_setup_req_t *f1ap_ue_context_setup_req);
int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance,
uint32_t assoc_id, uint32_t assoc_id,
......
...@@ -41,8 +41,91 @@ extern f1ap_setup_req_t *f1ap_du_data; ...@@ -41,8 +41,91 @@ extern f1ap_setup_req_t *f1ap_du_data;
int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance,
uint32_t assoc_id, uint32_t assoc_id,
uint32_t stream, uint32_t stream,
F1AP_F1AP_PDU_t *pdu) { F1AP_F1AP_PDU_t *pdu)
AssertFatal(1==0,"Not implemented yet\n"); {
MessageDef *msg_p; // message to RRC
F1AP_UEContextSetupRequest_t *container;
F1AP_UEContextSetupRequestIEs_t *ie;
int i;
DevAssert(pdu);
msg_p = itti_alloc_new_message(TASK_DU_F1, F1AP_UE_CONTEXT_SETUP_REQ);
f1ap_ue_context_setup_req_t *f1ap_ue_context_setup_req;
f1ap_ue_context_setup_req = &F1AP_UE_CONTEXT_SETUP_REQ(msg_p);
container = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest;
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container,
F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true);
f1ap_ue_context_setup_req->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container,
F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, false);
if (ie) {
f1ap_ue_context_setup_req->gNB_DU_ue_id = malloc(sizeof(uint32_t));
if (f1ap_ue_context_setup_req->gNB_DU_ue_id)
*f1ap_ue_context_setup_req->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID;
} else {
f1ap_ue_context_setup_req->gNB_DU_ue_id = NULL;
}
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container,
F1AP_ProtocolIE_ID_id_SpCell_ID, true);
PLMNID_TO_MCC_MNC(&ie->value.choice.NRCGI.pLMN_Identity,
f1ap_ue_context_setup_req->mcc,
f1ap_ue_context_setup_req->mnc,
f1ap_ue_context_setup_req->mnc_digit_length);
BIT_STRING_TO_NR_CELL_IDENTITY(&ie->value.choice.NRCGI.nRCellIdentity, f1ap_ue_context_setup_req->nr_cellid);
/* TODO: decode candidate SpCell */
/* TODO: decode CUtoDURRCInformation */
/* TODO: Candidate_SpCell_List */
/* TODO: SCell_ToBeSetup_List */
/* TODO: SRBs_ToBeSetup_List */
/* Decode DRBs_ToBeSetup_List */
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container,
F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List, true);
f1ap_ue_context_setup_req->drbs_to_be_setup_length = ie->value.choice.DRBs_ToBeSetup_List.list.count;
f1ap_ue_context_setup_req->drbs_to_be_setup = calloc(f1ap_ue_context_setup_req->drbs_to_be_setup_length,
sizeof(f1ap_drb_to_be_setup_t));
AssertFatal(f1ap_ue_context_setup_req->drbs_to_be_setup,
"could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n");
for (i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; ++i) {
f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_setup_req->drbs_to_be_setup[i];
F1AP_DRBs_ToBeSetup_Item_t *drbs_tobesetup_item_p;
drbs_tobesetup_item_p = &((F1AP_DRBs_ToBeSetup_ItemIEs_t *)ie->value.choice.DRBs_ToBeSetup_List.list.array[i])->value.choice.DRBs_ToBeSetup_Item;
drb_p->drb_id = drbs_tobesetup_item_p->dRBID;
/* TODO in the following, assume only one UP UL TNL is present.
* this matches/assumes OAI CU implementation, can be up to 2! */
drb_p->up_ul_tnl_length = 1;
AssertFatal(drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0,
"no UL UP TNL Information in DRBs to be Setup list\n");
F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0];
F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address);
OCTET_STRING_TO_INT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].gtp_teid);
switch (drbs_tobesetup_item_p->rLCMode) {
case F1AP_RLCMode_rlc_am:
drb_p->rlc_mode = RLC_MODE_AM;
break;
default:
drb_p->rlc_mode = RLC_MODE_TM;
break;
}
}
AssertFatal(0, "check configuration, send to appropriate handler\n");
return 0;
} }
//void DU_send_UE_CONTEXT_SETUP_RESPONSE(F1AP_UEContextSetupResponse_t *UEContextSetupResponse) { //void DU_send_UE_CONTEXT_SETUP_RESPONSE(F1AP_UEContextSetupResponse_t *UEContextSetupResponse) {
...@@ -153,7 +236,7 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(instance_t instance) { ...@@ -153,7 +236,7 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(instance_t instance) {
// *transportLayerAddress.buf = 123; // *transportLayerAddress.buf = 123;
// dLUPTNLInformation_ToBeSetup_Item.dL_GTP_Tunnel_EndPoint.transportLayerAddress = transportLayerAddress; // dLUPTNLInformation_ToBeSetup_Item.dL_GTP_Tunnel_EndPoint.transportLayerAddress = transportLayerAddress;
TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204", OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204",
strlen("1204")); strlen("1204"));
...@@ -441,7 +524,7 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) { ...@@ -441,7 +524,7 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) {
dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel;
F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t)); F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t));
TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204", OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204",
strlen("1204")); strlen("1204"));
...@@ -495,7 +578,7 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) { ...@@ -495,7 +578,7 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) {
dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel;
F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t)); F1AP_GTPTunnel_t *gTPTunnel = (F1AP_GTPTunnel_t *)calloc(1, sizeof(F1AP_GTPTunnel_t));
TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress);
OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204", OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204",
strlen("1204")); strlen("1204"));
......
...@@ -196,6 +196,17 @@ do { \ ...@@ -196,6 +196,17 @@ do { \
(oCTETsTRING)->size = 3; \ (oCTETsTRING)->size = 3; \
} while(0) } while(0)
#define PLMNID_TO_MCC_MNC(oCTETsTRING, mCC, mNC, mNCdIGITlENGTH) \
do { \
mCC = ((oCTETsTRING)->buf[0] & 0x0F) * 100 + \
((oCTETsTRING)->buf[0] >> 4 & 0x0F) * 10 + \
((oCTETsTRING)->buf[1] & 0x0F); \
mNCdIGITlENGTH = ((oCTETsTRING)->buf[1] >> 4 & 0x0F) == 0xF ? 2 : 3; \
mNC = (mNCdIGITlENGTH == 2 ? 0 : ((oCTETsTRING)->buf[1] >> 4 & 0x0F) * 100) + \
((oCTETsTRING)->buf[2] & 0x0F) * 10 + \
((oCTETsTRING)->buf[2] >> 4 & 0x0F); \
} while (0)
#define MCC_MNC_TO_TBCD(mCC, mNC, mNCdIGITlENGTH, tBCDsTRING) \ #define MCC_MNC_TO_TBCD(mCC, mNC, mNCdIGITlENGTH, tBCDsTRING) \
do { \ do { \
char _buf[3]; \ char _buf[3]; \
...@@ -260,7 +271,7 @@ do { \ ...@@ -260,7 +271,7 @@ do { \
/* TS 38.473 v15.2.1 section 9.3.1.32: /* TS 38.473 v15.2.1 section 9.3.1.32:
* C RNTI * C RNTI is BIT_STRING(16)
*/ */
#define C_RNTI_TO_BIT_STRING(mACRO, bITsTRING) \ #define C_RNTI_TO_BIT_STRING(mACRO, bITsTRING) \
do { \ do { \
...@@ -272,21 +283,31 @@ do { \ ...@@ -272,21 +283,31 @@ do { \
} while(0) } while(0)
/* TS 38.473 v15.1.1 section 9.3.2.1: /* TS 38.473 v15.1.1 section 9.3.2.3:
* TRANSPORT LAYER ADDRESS * TRANSPORT LAYER ADDRESS for IPv4 is 32bit (TS 38.414)
*/ */
#define TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(mACRO, bITsTRING) \ #define TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(mACRO, bITsTRING) \
do { \ do { \
(bITsTRING)->buf = calloc(5, sizeof(uint8_t)); \ (bITsTRING)->buf = calloc(4, sizeof(uint8_t)); \
(bITsTRING)->buf[0] = (mACRO) >> 28; \ (bITsTRING)->buf[0] = (mACRO) >> 24 & 0xFF; \
(bITsTRING)->buf[1] = (mACRO) >> 20; \ (bITsTRING)->buf[1] = (mACRO) >> 16 & 0xFF; \
(bITsTRING)->buf[2] = (mACRO) >> 12; \ (bITsTRING)->buf[2] = (mACRO) >> 8 & 0xFF; \
(bITsTRING)->buf[3] = (mACRO) >> 4; \ (bITsTRING)->buf[3] = (mACRO) >> 4 & 0xFF; \
(bITsTRING)->buf[4] = ((mACRO) & 0x0f) << 4; \ (bITsTRING)->size = 4; \
(bITsTRING)->size = 5; \ (bITsTRING)->bits_unused = 0; \
(bITsTRING)->bits_unused = 4; \
} while(0) } while(0)
#define BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(bITsTRING, mACRO) \
do { \
DevCheck((bITsTRING)->size == 4, (bITsTRING)->size, 4, 0); \
DevCheck((bITsTRING)->bits_unused == 0, (bITsTRING)->bits_unused, 0, 0); \
mACRO = ((bITsTRING)->buf[0] << 24) + \
((bITsTRING)->buf[1] << 16) + \
((bITsTRING)->buf[2] << 8) + \
((bITsTRING)->buf[3]); \
} while (0)
/* TS 38.473 v15.1.1 section 9.3.1.12: /* TS 38.473 v15.1.1 section 9.3.1.12:
* NR CELL ID * NR CELL ID
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment