Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenXG
OpenXG-RAN
Commits
5dcc1bf5
Commit
5dcc1bf5
authored
Sep 01, 2022
by
Sakthivel Velumani
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allocate stack where ever possible
Free memory after ASN encode
parent
793a5379
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
40 additions
and
43 deletions
+40
-43
openair2/E1AP/e1ap.c
openair2/E1AP/e1ap.c
+20
-21
openair2/E1AP/e1ap_api.c
openair2/E1AP/e1ap_api.c
+6
-8
openair2/E1AP/e1ap_common.c
openair2/E1AP/e1ap_common.c
+1
-0
openair2/GNB_APP/gnb_config.c
openair2/GNB_APP/gnb_config.c
+1
-1
openair2/RRC/NR/rrc_gNB.c
openair2/RRC/NR/rrc_gNB.c
+0
-1
openair2/RRC/NR/rrc_gNB_NGAP.c
openair2/RRC/NR/rrc_gNB_NGAP.c
+12
-12
No files found.
openair2/E1AP/e1ap.c
View file @
5dcc1bf5
...
...
@@ -774,7 +774,6 @@ int e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(instance_t instance,
}
}
e1ap_encode_send
(
UPtype
,
instance
,
&
pdu
,
0
,
__func__
);
free
(
resp
);
return
0
;
}
...
...
@@ -804,7 +803,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
E1AP_BearerContextSetupRequest_t
*
in
=
&
pdu
->
choice
.
initiatingMessage
->
value
.
choice
.
BearerContextSetupRequest
;
E1AP_BearerContextSetupRequestIEs_t
*
ie
;
e1ap_bearer_setup_req_t
*
bearerCxt
=
calloc
(
1
,
sizeof
(
e1ap_bearer_setup_req_t
))
;
e1ap_bearer_setup_req_t
bearerCxt
=
{
0
}
;
LOG_I
(
E1AP
,
"Bearer context setup number of IEs %d
\n
"
,
in
->
protocolIEs
.
list
.
count
);
for
(
int
i
=
0
;
i
<
in
->
protocolIEs
.
list
.
count
;
i
++
)
{
...
...
@@ -816,7 +815,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
"ie->criticality != E1AP_Criticality_reject
\n
"
);
AssertFatal
(
ie
->
value
.
present
==
E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID
,
"ie->value.present != E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID
\n
"
);
bearerCxt
->
gNB_cu_cp_ue_id
=
ie
->
value
.
choice
.
GNB_CU_CP_UE_E1AP_ID
;
bearerCxt
.
gNB_cu_cp_ue_id
=
ie
->
value
.
choice
.
GNB_CU_CP_UE_E1AP_ID
;
break
;
case
E1AP_ProtocolIE_ID_id_SecurityInformation
:
...
...
@@ -824,15 +823,15 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
"ie->criticality != E1AP_Criticality_reject
\n
"
);
AssertFatal
(
ie
->
value
.
present
==
E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation
,
"ie->value.present != E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation
\n
"
);
bearerCxt
->
cipheringAlgorithm
=
ie
->
value
.
choice
.
SecurityInformation
.
securityAlgorithm
.
cipheringAlgorithm
;
memcpy
(
bearerCxt
->
encryptionKey
,
bearerCxt
.
cipheringAlgorithm
=
ie
->
value
.
choice
.
SecurityInformation
.
securityAlgorithm
.
cipheringAlgorithm
;
memcpy
(
bearerCxt
.
encryptionKey
,
ie
->
value
.
choice
.
SecurityInformation
.
uPSecuritykey
.
encryptionKey
.
buf
,
ie
->
value
.
choice
.
SecurityInformation
.
uPSecuritykey
.
encryptionKey
.
size
);
if
(
ie
->
value
.
choice
.
SecurityInformation
.
securityAlgorithm
.
integrityProtectionAlgorithm
)
{
bearerCxt
->
integrityProtectionAlgorithm
=
*
ie
->
value
.
choice
.
SecurityInformation
.
securityAlgorithm
.
integrityProtectionAlgorithm
;
bearerCxt
.
integrityProtectionAlgorithm
=
*
ie
->
value
.
choice
.
SecurityInformation
.
securityAlgorithm
.
integrityProtectionAlgorithm
;
}
if
(
ie
->
value
.
choice
.
SecurityInformation
.
uPSecuritykey
.
integrityProtectionKey
)
{
memcpy
(
bearerCxt
->
integrityProtectionKey
,
memcpy
(
bearerCxt
.
integrityProtectionKey
,
ie
->
value
.
choice
.
SecurityInformation
.
uPSecuritykey
.
integrityProtectionKey
->
buf
,
ie
->
value
.
choice
.
SecurityInformation
.
uPSecuritykey
.
integrityProtectionKey
->
size
);
}
...
...
@@ -843,7 +842,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
"ie->criticality != E1AP_Criticality_reject
\n
"
);
AssertFatal
(
ie
->
value
.
present
==
E1AP_BearerContextSetupRequestIEs__value_PR_BitRate
,
"ie->value.present != E1AP_BearerContextSetupRequestIEs__value_PR_BitRate
\n
"
);
asn_INTEGER2long
(
&
ie
->
value
.
choice
.
BitRate
,
&
bearerCxt
->
ueDlAggMaxBitRate
);
asn_INTEGER2long
(
&
ie
->
value
.
choice
.
BitRate
,
&
bearerCxt
.
ueDlAggMaxBitRate
);
break
;
case
E1AP_ProtocolIE_ID_id_Serving_PLMN
:
...
...
@@ -852,9 +851,9 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
AssertFatal
(
ie
->
value
.
present
==
E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity
,
"ie->value.present != E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity
\n
"
);
PLMNID_TO_MCC_MNC
(
&
ie
->
value
.
choice
.
PLMN_Identity
,
bearerCxt
->
servingPLMNid
.
mcc
,
bearerCxt
->
servingPLMNid
.
mnc
,
bearerCxt
->
servingPLMNid
.
mnc_digit_length
);
bearerCxt
.
servingPLMNid
.
mcc
,
bearerCxt
.
servingPLMNid
.
mnc
,
bearerCxt
.
servingPLMNid
.
mnc_digit_length
);
break
;
case
E1AP_ProtocolIE_ID_id_ActivityNotificationLevel
:
...
...
@@ -862,7 +861,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
"ie->criticality != E1AP_Criticality_reject
\n
"
);
AssertFatal
(
ie
->
value
.
present
==
E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel
,
"ie->value.present != E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel
\n
"
);
bearerCxt
->
activityNotificationLevel
=
ie
->
value
.
choice
.
ActivityNotificationLevel
;
bearerCxt
.
activityNotificationLevel
=
ie
->
value
.
choice
.
ActivityNotificationLevel
;
break
;
case
E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest
:
...
...
@@ -886,9 +885,9 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
"msgNGRAN->value.present != E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List
\n
"
);
E1AP_PDU_Session_Resource_To_Setup_List_t
*
pdu2SetupList
=
&
msgNGRAN
->
value
.
choice
.
PDU_Session_Resource_To_Setup_List
;
bearerCxt
->
numPDUSessions
=
pdu2SetupList
->
list
.
count
;
bearerCxt
.
numPDUSessions
=
pdu2SetupList
->
list
.
count
;
for
(
int
i
=
0
;
i
<
pdu2SetupList
->
list
.
count
;
i
++
)
{
pdu_session_to_setup_t
*
pdu
=
bearerCxt
->
pduSession
+
i
;
pdu_session_to_setup_t
*
pdu
=
bearerCxt
.
pduSession
+
i
;
E1AP_PDU_Session_Resource_To_Setup_Item_t
*
pdu2Setup
=
pdu2SetupList
->
list
.
array
[
i
];
pdu
->
sessionId
=
pdu2Setup
->
pDU_Session_ID
;
...
...
@@ -975,7 +974,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
}
}
CUUP_process_e1_bearer_context_setup_req
(
bearerCxt
,
instance
);
CUUP_process_e1_bearer_context_setup_req
(
&
bearerCxt
,
instance
);
return
0
;
}
...
...
@@ -1209,7 +1208,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
E1AP_BearerContextModificationRequest_t
*
in
=
&
pdu
->
choice
.
initiatingMessage
->
value
.
choice
.
BearerContextModificationRequest
;
E1AP_BearerContextModificationRequestIEs_t
*
ie
;
e1ap_bearer_setup_req_t
*
bearerCxt
=
calloc
(
1
,
sizeof
(
e1ap_bearer_setup_req_t
))
;
e1ap_bearer_setup_req_t
bearerCxt
=
{
0
}
;
LOG_I
(
E1AP
,
"Bearer context setup number of IEs %d
\n
"
,
in
->
protocolIEs
.
list
.
count
);
for
(
int
i
=
0
;
i
<
in
->
protocolIEs
.
list
.
count
;
i
++
)
{
...
...
@@ -1221,7 +1220,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
"ie->criticality != E1AP_Criticality_reject
\n
"
);
AssertFatal
(
ie
->
value
.
present
==
E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID
,
"ie->value.present != E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID
\n
"
);
bearerCxt
->
gNB_cu_cp_ue_id
=
ie
->
value
.
choice
.
GNB_CU_CP_UE_E1AP_ID
;
bearerCxt
.
gNB_cu_cp_ue_id
=
ie
->
value
.
choice
.
GNB_CU_CP_UE_E1AP_ID
;
break
;
case
E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID
:
...
...
@@ -1229,7 +1228,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
"ie->criticality != E1AP_Criticality_reject
\n
"
);
AssertFatal
(
ie
->
value
.
present
==
E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID
,
"ie->value.present != E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID
\n
"
);
bearerCxt
->
gNB_cu_up_ue_id
=
ie
->
value
.
choice
.
GNB_CU_UP_UE_E1AP_ID
;
bearerCxt
.
gNB_cu_up_ue_id
=
ie
->
value
.
choice
.
GNB_CU_UP_UE_E1AP_ID
;
break
;
case
E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest
:
...
...
@@ -1253,9 +1252,9 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
"msgNGRAN->value.present != E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List
\n
"
);
E1AP_PDU_Session_Resource_To_Modify_List_t
*
pdu2ModList
=
&
msgNGRAN
->
value
.
choice
.
PDU_Session_Resource_To_Modify_List
;
bearerCxt
->
numPDUSessionsMod
=
pdu2ModList
->
list
.
count
;
bearerCxt
.
numPDUSessionsMod
=
pdu2ModList
->
list
.
count
;
for
(
int
i
=
0
;
i
<
pdu2ModList
->
list
.
count
;
i
++
)
{
pdu_session_to_setup_t
*
pdu
=
bearerCxt
->
pduSessionMod
+
i
;
pdu_session_to_setup_t
*
pdu
=
bearerCxt
.
pduSessionMod
+
i
;
E1AP_PDU_Session_Resource_To_Modify_Item_t
*
pdu2Mod
=
pdu2ModList
->
list
.
array
[
i
];
pdu
->
sessionId
=
pdu2Mod
->
pDU_Session_ID
;
...
...
@@ -1294,7 +1293,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
}
}
CUUP_process_bearer_context_mod_req
(
bearerCxt
,
instance
);
CUUP_process_bearer_context_mod_req
(
&
bearerCxt
,
instance
);
return
0
;
}
...
...
openair2/E1AP/e1ap_api.c
View file @
5dcc1bf5
...
...
@@ -191,7 +191,7 @@ void CUUP_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, inst
instance_t
gtpInst
=
getCxtE1
(
UPtype
,
instance
)
->
gtpInstN3
;
drb_config_N3gtpu_create
(
req
,
&
create_tunnel_resp_N3
,
gtpInst
);
e1ap_bearer_setup_resp_t
*
resp
=
calloc
(
1
,
sizeof
(
e1ap_bearer_setup_resp_t
))
;
e1ap_bearer_setup_resp_t
resp
=
{
0
}
;
int
remote_port
=
getCxtE1
(
UPtype
,
instance
)
->
setupReq
.
remoteDUPort
;
in_addr_t
my_addr
;
...
...
@@ -200,12 +200,12 @@ void CUUP_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, inst
&
my_addr
);
gtpInst
=
getCxtE1
(
UPtype
,
instance
)
->
gtpInstF1U
;
gNB_CU_create_up_ul_tunnel
(
resp
,
req
,
gtpInst
,
req
->
gNB_cu_cp_ue_id
,
remote_port
,
my_addr
);
gNB_CU_create_up_ul_tunnel
(
&
resp
,
req
,
gtpInst
,
req
->
gNB_cu_cp_ue_id
,
remote_port
,
my_addr
);
resp
->
gNB_cu_cp_ue_id
=
req
->
gNB_cu_cp_ue_id
;
resp
->
numPDUSessions
=
req
->
numPDUSessions
;
resp
.
gNB_cu_cp_ue_id
=
req
->
gNB_cu_cp_ue_id
;
resp
.
numPDUSessions
=
req
->
numPDUSessions
;
for
(
int
i
=
0
;
i
<
req
->
numPDUSessions
;
i
++
)
{
pdu_session_setup_t
*
pduSetup
=
resp
->
pduSession
+
i
;
pdu_session_setup_t
*
pduSetup
=
resp
.
pduSession
+
i
;
pdu_session_to_setup_t
*
pdu2Setup
=
req
->
pduSession
+
i
;
pduSetup
->
id
=
pdu2Setup
->
sessionId
;
...
...
@@ -221,8 +221,7 @@ void CUUP_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, inst
pduSetup
->
numDRBFailed
=
0
;
}
e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE
(
instance
,
resp
);
free
(
req
);
e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE
(
instance
,
&
resp
);
}
void
update_UL_UP_tunnel_info
(
e1ap_bearer_setup_req_t
*
req
,
instance_t
instance
,
ue_id_t
ue_id
)
{
...
...
@@ -248,7 +247,6 @@ void update_UL_UP_tunnel_info(e1ap_bearer_setup_req_t *req, instance_t instance,
void
CUUP_process_bearer_context_mod_req
(
e1ap_bearer_setup_req_t
*
req
,
instance_t
instance
)
{
instance_t
gtpInst
=
getCxtE1
(
UPtype
,
instance
)
->
gtpInstF1U
;
update_UL_UP_tunnel_info
(
req
,
gtpInst
,
req
->
gNB_cu_cp_ue_id
);
free
(
req
);
// TODO: send bearer cxt mod response
}
openair2/E1AP/e1ap_common.c
View file @
5dcc1bf5
...
...
@@ -223,6 +223,7 @@ int e1ap_encode_send(E1_t type, instance_t instance, E1AP_E1AP_PDU_t *pdu, uint1
void
*
buffer
=
NULL
;
ssize_t
encoded
=
aper_encode_to_new_buffer
(
&
asn_DEF_E1AP_E1AP_PDU
,
0
,
pdu
,
&
buffer
);
ASN_STRUCT_FREE_CONTENTS_ONLY
(
asn_DEF_E1AP_E1AP_PDU
,
pdu
);
if
(
encoded
<
0
)
{
LOG_E
(
E1AP
,
"%s: Failed to encode E1AP message
\n
"
,
func
);
...
...
openair2/GNB_APP/gnb_config.c
View file @
5dcc1bf5
...
...
@@ -1304,7 +1304,7 @@ instance_t RCconfig_nr_gtpu(void) {
ret_inst
=
gtpv1Init
(
tmp
);
}
else
LOG_E
(
GTPU
,
"invalid address for NGU or S1U
\n
"
);
return
ret_inst
;
}
...
...
openair2/RRC/NR/rrc_gNB.c
View file @
5dcc1bf5
...
...
@@ -4074,7 +4074,6 @@ void bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *req, instance_t instance
MessageDef
*
msg_p
=
itti_alloc_new_message
(
TASK_CUCP_E1
,
instance
,
E1AP_BEARER_CONTEXT_SETUP_REQ
);
e1ap_bearer_setup_req_t
*
bearer_req
=
&
E1AP_BEARER_CONTEXT_SETUP_REQ
(
msg_p
);
memcpy
(
bearer_req
,
req
,
sizeof
(
e1ap_bearer_setup_req_t
));
free
(
req
);
itti_send_msg_to_task
(
TASK_CUCP_E1
,
instance
,
msg_p
);
...
...
openair2/RRC/NR/rrc_gNB_NGAP.c
View file @
5dcc1bf5
...
...
@@ -991,22 +991,22 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(
At CU-CP we configure the E1 bearer context setup parameters (PDU sessions, DRBs and
QoS flows) same as in these functions. At CU-UP we create PDU Sessions and allocate DRBs.
*/
e1ap_bearer_setup_req_t
*
bearer_req
=
calloc
(
1
,
sizeof
(
e1ap_bearer_setup_req_t
))
;
e1ap_bearer_setup_req_t
bearer_req
;
bearer_req
->
gNB_cu_cp_ue_id
=
gNB_ue_ngap_id
;
bearer_req
->
rnti
=
ue_context_p
->
ue_context
.
rnti
;
bearer_req
->
cipheringAlgorithm
=
ue_context_p
->
ue_context
.
ciphering_algorithm
;
memcpy
(
bearer_req
->
encryptionKey
,
ue_context_p
->
ue_context
.
kgnb
,
sizeof
(
ue_context_p
->
ue_context
.
kgnb
));
bearer_req
->
integrityProtectionAlgorithm
=
ue_context_p
->
ue_context
.
integrity_algorithm
;
memcpy
(
bearer_req
->
integrityProtectionKey
,
ue_context_p
->
ue_context
.
kgnb
,
sizeof
(
ue_context_p
->
ue_context
.
kgnb
));
bearer_req
->
ueDlAggMaxBitRate
=
msg
->
ueAggMaxBitRateDownlink
;
bearer_req
.
gNB_cu_cp_ue_id
=
gNB_ue_ngap_id
;
bearer_req
.
rnti
=
ue_context_p
->
ue_context
.
rnti
;
bearer_req
.
cipheringAlgorithm
=
ue_context_p
->
ue_context
.
ciphering_algorithm
;
memcpy
(
bearer_req
.
encryptionKey
,
ue_context_p
->
ue_context
.
kgnb
,
sizeof
(
ue_context_p
->
ue_context
.
kgnb
));
bearer_req
.
integrityProtectionAlgorithm
=
ue_context_p
->
ue_context
.
integrity_algorithm
;
memcpy
(
bearer_req
.
integrityProtectionKey
,
ue_context_p
->
ue_context
.
kgnb
,
sizeof
(
ue_context_p
->
ue_context
.
kgnb
));
bearer_req
.
ueDlAggMaxBitRate
=
msg
->
ueAggMaxBitRateDownlink
;
bearer_req
->
numPDUSessions
=
msg
->
nb_pdusessions_tosetup
;
bearer_req
.
numPDUSessions
=
msg
->
nb_pdusessions_tosetup
;
for
(
int
i
=
0
;
i
<
bearer_req
->
numPDUSessions
;
i
++
)
{
for
(
int
i
=
0
;
i
<
bearer_req
.
numPDUSessions
;
i
++
)
{
ue_context_p
->
ue_context
.
pduSession
[
i
].
param
=
msg
->
pdusession_setup_params
[
i
];
pdu_session_to_setup_t
*
pdu
=
bearer_req
->
pduSession
+
i
;
pdu_session_to_setup_t
*
pdu
=
bearer_req
.
pduSession
+
i
;
pdu
->
sessionId
=
msg
->
pdusession_setup_params
[
i
].
pdusession_id
;
pdu
->
sessionType
=
msg
->
pdusession_setup_params
[
i
].
upf_addr
.
pdu_session_type
;
pdu
->
sst
=
msg
->
allowed_nssai
[
i
].
sST
;
...
...
@@ -1072,7 +1072,7 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(
}
}
rrc
->
mac_rrc
.
nr_e1_bearer_cxt_msg_transfer
(
bearer_req
,
instance
);
rrc
->
mac_rrc
.
nr_e1_bearer_cxt_msg_transfer
(
&
bearer_req
,
instance
);
return
;
}
...
...
FANG WANG
@wf
mentioned in commit
553f1d1a
·
Feb 11, 2023
mentioned in commit
553f1d1a
mentioned in commit 553f1d1a52845911be4ba61ec2bcc5c60ad42ae7
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment