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
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
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
alex037yang
OpenXG-RAN
Commits
e7d6f360
Commit
e7d6f360
authored
Jan 19, 2016
by
Rohit Gupta
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into feature-34-test_framework
parents
4843f4de
96365966
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
221 additions
and
75 deletions
+221
-75
openair2/COMMON/platform_types.h
openair2/COMMON/platform_types.h
+6
-0
openair2/RRC/LITE/MESSAGES/asn1_msg.c
openair2/RRC/LITE/MESSAGES/asn1_msg.c
+61
-0
openair2/RRC/LITE/MESSAGES/asn1_msg.h
openair2/RRC/LITE/MESSAGES/asn1_msg.h
+10
-0
openair2/RRC/LITE/defs.h
openair2/RRC/LITE/defs.h
+3
-3
openair2/RRC/LITE/rrc_eNB.c
openair2/RRC/LITE/rrc_eNB.c
+118
-59
openair2/RRC/LITE/rrc_eNB_S1AP.c
openair2/RRC/LITE/rrc_eNB_S1AP.c
+17
-7
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf
...NERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf
+6
-6
No files found.
openair2/COMMON/platform_types.h
View file @
e7d6f360
...
...
@@ -163,7 +163,13 @@ typedef uint32_t mbms_session_id_t;
typedef
uint16_t
mbms_service_id_t
;
typedef
uint16_t
rnti_t
;
typedef
uint8_t
rrc_enb_index_t
;
typedef
uint8_t
mme_code_t
;
typedef
uint32_t
m_tmsi_t
;
//Random UE identity length = 40 bits
#if ! defined(NOT_A_RANDOM_UE_IDENTITY)
#define NOT_A_RANDOM_UE_IDENTITY (uint64_t)0xFFFFFFFF
#endif
#if ! defined(NOT_A_RNTI)
#define NOT_A_RNTI (rnti_t)0
#endif
...
...
openair2/RRC/LITE/MESSAGES/asn1_msg.c
View file @
e7d6f360
...
...
@@ -2110,6 +2110,67 @@ do_RRCConnectionReestablishmentReject(
return
((
enc_rval
.
encoded
+
7
)
/
8
);
}
//------------------------------------------------------------------------------
uint8_t
do_RRCConnectionReject
(
uint8_t
Mod_id
,
uint8_t
*
const
buffer
)
//------------------------------------------------------------------------------
{
asn_enc_rval_t
enc_rval
;
DL_CCCH_Message_t
dl_ccch_msg
;
RRCConnectionReject_t
*
rrcConnectionReject
;
memset
((
void
*
)
&
dl_ccch_msg
,
0
,
sizeof
(
DL_CCCH_Message_t
));
dl_ccch_msg
.
message
.
present
=
DL_CCCH_MessageType_PR_c1
;
dl_ccch_msg
.
message
.
choice
.
c1
.
present
=
DL_CCCH_MessageType__c1_PR_rrcConnectionReject
;
rrcConnectionReject
=
&
dl_ccch_msg
.
message
.
choice
.
c1
.
choice
.
rrcConnectionReject
;
// RRCConnectionReject
rrcConnectionReject
->
criticalExtensions
.
present
=
RRCConnectionReject__criticalExtensions_PR_c1
;
rrcConnectionReject
->
criticalExtensions
.
choice
.
c1
.
present
=
RRCConnectionReject__criticalExtensions__c1_PR_rrcConnectionReject_r8
;
/* let's put a wait time of 1s for the moment */
rrcConnectionReject
->
criticalExtensions
.
choice
.
c1
.
choice
.
rrcConnectionReject_r8
.
waitTime
=
1
;
#ifdef XER_PRINT
xer_fprint
(
stdout
,
&
asn_DEF_DL_CCCH_Message
,
(
void
*
)
&
dl_ccch_msg
);
#endif
enc_rval
=
uper_encode_to_buffer
(
&
asn_DEF_DL_CCCH_Message
,
(
void
*
)
&
dl_ccch_msg
,
buffer
,
100
);
AssertFatal
(
enc_rval
.
encoded
>
0
,
"ASN1 message encoding failed (%s, %ld)!
\n
"
,
enc_rval
.
failed_type
->
name
,
enc_rval
.
encoded
);
#if defined(ENABLE_ITTI)
# if !defined(DISABLE_XER_SPRINT)
{
char
message_string
[
20000
];
size_t
message_string_size
;
if
((
message_string_size
=
xer_sprint
(
message_string
,
sizeof
(
message_string
),
&
asn_DEF_DL_CCCH_Message
,
(
void
*
)
&
dl_ccch_msg
))
>
0
)
{
MessageDef
*
msg_p
;
msg_p
=
itti_alloc_new_message_sized
(
TASK_RRC_ENB
,
RRC_DL_CCCH
,
message_string_size
+
sizeof
(
IttiMsgText
));
msg_p
->
ittiMsg
.
rrc_dl_ccch
.
size
=
message_string_size
;
memcpy
(
&
msg_p
->
ittiMsg
.
rrc_dl_ccch
.
text
,
message_string
,
message_string_size
);
itti_send_msg_to_task
(
TASK_UNKNOWN
,
Mod_id
,
msg_p
);
}
}
# endif
#endif
#ifdef USER_MODE
LOG_D
(
RRC
,
"RRCConnectionReject Encoded %d bits (%d bytes)
\n
"
,
enc_rval
.
encoded
,(
enc_rval
.
encoded
+
7
)
/
8
);
#endif
return
((
enc_rval
.
encoded
+
7
)
/
8
);
}
uint8_t
do_RRCConnectionRelease
(
uint8_t
Mod_id
,
uint8_t
*
buffer
,
...
...
openair2/RRC/LITE/MESSAGES/asn1_msg.h
View file @
e7d6f360
...
...
@@ -218,6 +218,16 @@ do_RRCConnectionReestablishmentReject(
uint8_t
Mod_id
,
uint8_t
*
const
buffer
);
/**
\brief Generate an RRCConnectionReject DL-CCCH-Message (eNB).
@param Mod_id Module ID of eNB
@param buffer Pointer to PER-encoded ASN.1 description of DL-CCCH-Message PDU
@returns Size of encoded bit stream in bytes*/
uint8_t
do_RRCConnectionReject
(
uint8_t
Mod_id
,
uint8_t
*
const
buffer
);
/**
\brief Generate an RRCConnectionRequest UL-CCCH-Message (UE) based on random string or S-TMSI. This
routine only generates an mo-data establishment cause.
...
...
openair2/RRC/LITE/defs.h
View file @
e7d6f360
...
...
@@ -212,9 +212,9 @@ typedef struct UE_RRC_INFO_s {
}
__attribute__
((
__packed__
))
UE_RRC_INFO
;
typedef
struct
UE_S_TMSI_s
{
uint8
_t
presence
;
uint8_t
mme_code
;
uint32_t
m_tmsi
;
boolean
_t
presence
;
mme_code_t
mme_code
;
m_tmsi_t
m_tmsi
;
}
__attribute__
((
__packed__
))
UE_S_TMSI
;
#if defined(ENABLE_ITTI)
...
...
openair2/RRC/LITE/rrc_eNB.c
View file @
e7d6f360
...
...
@@ -540,8 +540,8 @@ rrc_eNB_get_next_transaction_identifier(
//-----------------------------------------------------------------------------
// return
1 if there is already an UE with ue_identityP, 0
otherwise
static
int
// return
the ue context if there is already an UE with ue_identityP, NULL
otherwise
static
struct
rrc_eNB_ue_context_s
*
rrc_eNB_ue_context_random_exist
(
const
protocol_ctxt_t
*
const
ctxt_pP
,
const
uint64_t
ue_identityP
...
...
@@ -551,9 +551,28 @@ rrc_eNB_ue_context_random_exist(
struct
rrc_eNB_ue_context_s
*
ue_context_p
=
NULL
;
RB_FOREACH
(
ue_context_p
,
rrc_ue_tree_s
,
&
(
eNB_rrc_inst
[
ctxt_pP
->
module_id
].
rrc_ue_head
))
{
if
(
ue_context_p
->
ue_context
.
random_ue_identity
==
ue_identityP
)
return
1
;
return
ue_context_p
;
}
return
0
;
return
NULL
;
}
//-----------------------------------------------------------------------------
// return the ue context if there is already an UE with the same S-TMSI(MMEC+M-TMSI), NULL otherwise
static
struct
rrc_eNB_ue_context_s
*
rrc_eNB_ue_context_stmsi_exist
(
const
protocol_ctxt_t
*
const
ctxt_pP
,
const
mme_code_t
mme_codeP
,
const
m_tmsi_t
m_tmsiP
)
//-----------------------------------------------------------------------------
{
struct
rrc_eNB_ue_context_s
*
ue_context_p
=
NULL
;
RB_FOREACH
(
ue_context_p
,
rrc_ue_tree_s
,
&
(
eNB_rrc_inst
[
ctxt_pP
->
module_id
].
rrc_ue_head
))
{
if
(
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
presence
==
TRUE
)
if
(
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
m_tmsi
==
m_tmsiP
)
if
(
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
mme_code
==
mme_codeP
)
return
ue_context_p
;
}
return
NULL
;
}
//-----------------------------------------------------------------------------
...
...
@@ -963,6 +982,49 @@ rrc_eNB_generate_UECapabilityEnquiry(
}
//-----------------------------------------------------------------------------
void
rrc_eNB_generate_RRCConnectionReject
(
const
protocol_ctxt_t
*
const
ctxt_pP
,
rrc_eNB_ue_context_t
*
const
ue_context_pP
,
const
int
CC_id
)
//-----------------------------------------------------------------------------
{
#ifdef RRC_MSG_PRINT
int
cnt
;
#endif
eNB_rrc_inst
[
ctxt_pP
->
module_id
].
carrier
[
CC_id
].
Srb0
.
Tx_buffer
.
payload_size
=
do_RRCConnectionReject
(
ctxt_pP
->
module_id
,
(
uint8_t
*
)
eNB_rrc_inst
[
ctxt_pP
->
module_id
].
carrier
[
CC_id
].
Srb0
.
Tx_buffer
.
Payload
);
#ifdef RRC_MSG_PRINT
LOG_F
(
RRC
,
"[MSG] RRCConnectionReject
\n
"
);
for
(
cnt
=
0
;
cnt
<
eNB_rrc_inst
[
ctxt_pP
->
module_id
].
carrier
[
CC_id
].
Srb0
.
Tx_buffer
.
payload_size
;
cnt
++
)
{
LOG_F
(
RRC
,
"%02x "
,
((
uint8_t
*
)
eNB_rrc_inst
[
ctxt_pP
->
module_id
].
Srb0
.
Tx_buffer
.
Payload
)[
cnt
]);
}
LOG_F
(
RRC
,
"
\n
"
);
#endif
MSC_LOG_TX_MESSAGE
(
MSC_RRC_ENB
,
MSC_RRC_UE
,
eNB_rrc_inst
[
ctxt_pP
->
module_id
].
carrier
[
CC_id
].
Srb0
.
Tx_buffer
.
Header
,
eNB_rrc_inst
[
ctxt_pP
->
module_id
].
carrier
[
CC_id
].
Srb0
.
Tx_buffer
.
payload_size
,
MSC_AS_TIME_FMT
" RRCConnectionReject UE %x size %u"
,
MSC_AS_TIME_ARGS
(
ctxt_pP
),
ue_context_pP
==
NULL
?
-
1
:
ue_context_pP
->
ue_context
.
rnti
,
eNB_rrc_inst
[
ctxt_pP
->
module_id
].
carrier
[
CC_id
].
Srb0
.
Tx_buffer
.
payload_size
);
LOG_I
(
RRC
,
PROTOCOL_RRC_CTXT_UE_FMT
" [RAPROC] Logical Channel DL-CCCH, Generating RRCConnectionReject (bytes %d)
\n
"
,
PROTOCOL_RRC_CTXT_UE_ARGS
(
ctxt_pP
),
eNB_rrc_inst
[
ctxt_pP
->
module_id
].
carrier
[
CC_id
].
Srb0
.
Tx_buffer
.
payload_size
);
}
//-----------------------------------------------------------------------------
void
rrc_eNB_generate_RRCConnectionReestablishmentReject
(
...
...
@@ -3627,8 +3689,7 @@ rrc_eNB_decode_ccch(
}
else
{
rrcConnectionRequest
=
&
ul_ccch_msg
->
message
.
choice
.
c1
.
choice
.
rrcConnectionRequest
.
criticalExtensions
.
choice
.
rrcConnectionRequest_r8
;
{
AssertFatal
(
rrcConnectionRequest
->
ue_Identity
.
present
==
InitialUE_Identity_PR_randomValue
,
"unsupported InitialUE-Identity in RRCConnectionRequest"
);
if
(
InitialUE_Identity_PR_randomValue
==
rrcConnectionRequest
->
ue_Identity
.
present
)
{
AssertFatal
(
rrcConnectionRequest
->
ue_Identity
.
choice
.
randomValue
.
size
==
5
,
"wrong InitialUE-Identity randomValue size, expected 5, provided %d"
,
rrcConnectionRequest
->
ue_Identity
.
choice
.
randomValue
.
size
);
...
...
@@ -3638,36 +3699,29 @@ rrc_eNB_decode_ccch(
/* if there is already a registered UE (with another RNTI) with this random_value,
* the current one must be removed from MAC/PHY (zombie UE)
*/
if
(
rrc_eNB_ue_context_random_exist
(
ctxt_pP
,
random_value
))
{
AssertFatal
(
0
==
1
,
"TODO: remove UE fro
MAC/PHY (how?)"
);
if
((
ue_context_p
=
rrc_eNB_ue_context_random_exist
(
ctxt_pP
,
random_value
)
))
{
AssertFatal
(
0
==
1
,
"TODO: remove UE from
MAC/PHY (how?)"
);
ue_context_p
=
NULL
;
}
else
{
ue_context_p
=
rrc_eNB_get_next_free_ue_context
(
ctxt_pP
,
random_value
);
}
}
LOG_D
(
RRC
,
PROTOCOL_RRC_CTXT_UE_FMT
" UE context: %X
\n
"
,
PROTOCOL_RRC_CTXT_UE_ARGS
(
ctxt_pP
),
ue_context_p
);
if
(
ue_context_p
!=
NULL
)
{
#if defined(ENABLE_ITTI)
/* Check s-TMSI presence in message */
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
presence
=
(
rrcConnectionRequest
->
ue_Identity
.
present
==
InitialUE_Identity_PR_s_TMSI
);
if
(
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
presence
)
{
}
else
if
(
InitialUE_Identity_PR_s_TMSI
==
rrcConnectionRequest
->
ue_Identity
.
present
)
{
/* Save s-TMSI */
S_TMSI_t
s_TMSI
=
rrcConnectionRequest
->
ue_Identity
.
choice
.
s_TMSI
;
mme_code_t
mme_code
=
BIT_STRING_to_uint8
(
&
s_TMSI
.
mmec
);
m_tmsi_t
m_tmsi
=
BIT_STRING_to_uint32
(
&
s_TMSI
.
m_TMSI
);
random_value
=
(((
uint64_t
)
mme_code
)
<<
32
)
|
m_tmsi
;
if
((
ue_context_p
=
rrc_eNB_ue_context_stmsi_exist
(
ctxt_pP
,
mme_code
,
m_tmsi
)))
{
AssertFatal
(
0
==
1
,
"TODO: remove UE from MAC/PHY (how?)"
);
ue_context_p
=
NULL
;
}
else
{
ue_context_p
=
rrc_eNB_get_next_free_ue_context
(
ctxt_pP
,
NOT_A_RANDOM_UE_IDENTITY
);
}
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
presence
=
TRUE
;
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
mme_code
=
mme_code
;
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
m_tmsi
=
m_tmsi
;
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
mme_code
=
BIT_STRING_to_uint8
(
&
s_TMSI
.
mmec
);
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
m_tmsi
=
BIT_STRING_to_uint32
(
&
s_TMSI
.
m_TMSI
);
MSC_LOG_RX_DISCARDED_MESSAGE
(
MSC_LOG_RX_MESSAGE
(
MSC_RRC_ENB
,
MSC_RRC_UE
,
Srb_info
->
Rx_buffer
.
Payload
,
...
...
@@ -3676,25 +3730,30 @@ rrc_eNB_decode_ccch(
MSC_AS_TIME_ARGS
(
ctxt_pP
),
ue_context_p
->
ue_context
.
rnti
,
dec_rval
.
consumed
,
s_TMSI
.
mmec
,
s_TMSI
.
m_TMSI
,
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
mme_code
,
ue_context_p
->
ue_context
.
Initialue_identity_s_TMSI
.
m_tmsi
,
ue_context_p
->
ue_context
.
random_ue_identity
);
}
else
{
MSC_LOG_RX_DISCARDED_MESSAGE
(
MSC_RRC_ENB
,
MSC_RRC_UE
,
Srb_info
->
Rx_buffer
.
Payload
,
dec_rval
.
consumed
,
MSC_AS_TIME_FMT
" RRCConnectionRequest UE %x size %u random UE id (0x%"
PRIx64
")"
,
MSC_AS_TIME_ARGS
(
ctxt_pP
),
ue_context_p
->
ue_context
.
rnti
,
dec_rval
.
consumed
,
ue_context_p
->
ue_context
.
random_ue_identity
);
LOG_E
(
RRC
,
PROTOCOL_RRC_CTXT_UE_FMT
" RRCConnectionRequest without random UE identity or S-TMSI not supported, let's reject the UE
\n
"
,
PROTOCOL_RRC_CTXT_UE_ARGS
(
ctxt_pP
));
rrc_eNB_generate_RRCConnectionReject
(
ctxt_pP
,
rrc_eNB_get_ue_context
(
&
eNB_rrc_inst
[
ctxt_pP
->
module_id
],
ctxt_pP
->
rnti
),
CC_id
);
break
;
}
}
LOG_D
(
RRC
,
PROTOCOL_RRC_CTXT_UE_FMT
" UE context: %X
\n
"
,
PROTOCOL_RRC_CTXT_UE_ARGS
(
ctxt_pP
),
ue_context_p
);
if
(
ue_context_p
!=
NULL
)
{
ue_context_p
->
ue_context
.
establishment_cause
=
rrcConnectionRequest
->
establishmentCause
;
#if defined(ENABLE_ITTI)
ue_context_p
->
ue_context
.
establishment_cause
=
rrcConnectionRequest
->
establishmentCause
;
LOG_I
(
RRC
,
PROTOCOL_RRC_CTXT_UE_FMT
" Accept new connection from UE random UE identity (0x%"
PRIx64
") MME code %u TMSI %u cause %u
\n
"
,
PROTOCOL_RRC_CTXT_UE_ARGS
(
ctxt_pP
),
ue_context_p
->
ue_context
.
random_ue_identity
,
...
...
openair2/RRC/LITE/rrc_eNB_S1AP.c
View file @
e7d6f360
...
...
@@ -43,6 +43,7 @@
# include "RRC/LITE/defs.h"
# include "rrc_eNB_UE_context.h"
# include "rrc_eNB_S1AP.h"
# include "enb_config.h"
# if defined(ENABLE_ITTI)
# include "asn1_conversions.h"
...
...
@@ -670,6 +671,7 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
if
(
rrcConnectionSetupComplete
->
registeredMME
!=
NULL
)
{
/* Fill GUMMEI */
struct
RegisteredMME
*
r_mme
=
rrcConnectionSetupComplete
->
registeredMME
;
int
selected_plmn_identity
=
rrcConnectionSetupComplete
->
selectedPLMN_Identity
;
S1AP_NAS_FIRST_REQ
(
message_p
).
ue_identity
.
presenceMask
|=
UE_IDENTITIES_gummei
;
...
...
@@ -691,6 +693,14 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
S1AP_NAS_FIRST_REQ
(
message_p
).
ue_identity
.
gummei
.
mnc
,
ue_context_pP
->
ue_context
.
rnti
);
}
}
else
{
const
Enb_properties_array_t
*
enb_properties_p
=
NULL
;
enb_properties_p
=
enb_config_get
();
// actually the eNB configuration contains only one PLMN (can be up to 6)
S1AP_NAS_FIRST_REQ
(
message_p
).
ue_identity
.
gummei
.
mcc
=
enb_properties_p
->
properties
[
ctxt_pP
->
module_id
]
->
mcc
;
S1AP_NAS_FIRST_REQ
(
message_p
).
ue_identity
.
gummei
.
mnc
=
enb_properties_p
->
properties
[
ctxt_pP
->
module_id
]
->
mnc
;
S1AP_NAS_FIRST_REQ
(
message_p
).
ue_identity
.
gummei
.
mnc_len
=
enb_properties_p
->
properties
[
ctxt_pP
->
module_id
]
->
mnc_digit_length
;
}
S1AP_NAS_FIRST_REQ
(
message_p
).
ue_identity
.
gummei
.
mme_code
=
BIT_STRING_to_uint8
(
&
r_mme
->
mmec
);
...
...
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf
View file @
e7d6f360
...
...
@@ -16,7 +16,7 @@ eNBs =
tracking_area_code
=
"1"
;
mobile_country_code
=
"208"
;
mobile_network_code
=
"9
2
"
;
mobile_network_code
=
"9
5
"
;
//////////
Physical
parameters
:
...
...
@@ -130,18 +130,18 @@ eNBs =
};
//////////
MME
parameters
:
mme_ip_address
= ( {
ipv4
=
"192.168.12.
26
"
;
mme_ip_address
= ( {
ipv4
=
"192.168.12.
17
"
;
ipv6
=
"192:168:30::17"
;
active
=
"yes"
;
preference
=
"ipv4"
;});
NETWORK_INTERFACES
:
{
ENB_INTERFACE_NAME_FOR_S1_MME
=
"eth
1
"
;
ENB_IPV4_ADDRESS_FOR_S1_MME
=
"192.168.12.
82
/24"
;
ENB_INTERFACE_NAME_FOR_S1_MME
=
"eth
0
"
;
ENB_IPV4_ADDRESS_FOR_S1_MME
=
"192.168.12.
213
/24"
;
ENB_INTERFACE_NAME_FOR_S1U
=
"eth
1
"
;
ENB_IPV4_ADDRESS_FOR_S1U
=
"192.168.12.
82
/24"
;
ENB_INTERFACE_NAME_FOR_S1U
=
"eth
0
"
;
ENB_IPV4_ADDRESS_FOR_S1U
=
"192.168.12.
213
/24"
;
ENB_PORT_FOR_S1U
=
2152
;
# Spec 2152
};
...
...
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