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
spbro
OpenXG-RAN
Commits
b90c0680
Commit
b90c0680
authored
Mar 17, 2021
by
David Kim
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
adding x2c setting with epc
parent
2948a244
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
344 additions
and
77 deletions
+344
-77
ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf
ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf
+9
-10
ci-scripts/conf_files/ue.nfapi.conf
ci-scripts/conf_files/ue.nfapi.conf
+3
-3
openair3/NAS/TOOLS/display.c
openair3/NAS/TOOLS/display.c
+2
-4
openair3/S1AP/s1ap_eNB_handlers.c
openair3/S1AP/s1ap_eNB_handlers.c
+310
-54
targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf
...CTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf
+20
-6
No files found.
ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf
View file @
b90c0680
...
...
@@ -13,9 +13,9 @@ eNBs =
eNB_name
=
"eNB-Eurecom-LTEBox"
;
//
Tracking
area
code
,
0
x0000
and
0
xfffe
are
reserved
values
tracking_area_code
=
1
;
tracking_area_code
=
5
;
plmn_list
= ( {
mcc
=
208
;
mnc
=
93
;
mnc_length
=
2
; } );
plmn_list
= ( {
mcc
=
320
;
mnc
=
230
;
mnc_length
=
3
; } );
tr_s_preference
=
"local_mac"
...
...
@@ -172,7 +172,7 @@ eNBs =
//////////
MME
parameters
:
mme_ip_address
= ( {
ipv4
=
"
CI_MME_IP_ADDR
"
;
mme_ip_address
= ( {
ipv4
=
"
192.168.61.3
"
;
ipv6
=
"192:168:30::17"
;
port
=
36412
;
active
=
"yes"
;
...
...
@@ -183,7 +183,7 @@ eNBs =
enable_measurement_reports
=
"no"
;
///
X2
enable_x2
=
"
no
"
;
enable_x2
=
"
yes
"
;
t_reloc_prep
=
1000
; /*
unit
:
millisecond
*/
tx2_reloc_overall
=
2000
; /*
unit
:
millisecond
*/
t_dc_prep
=
1000
; /*
unit
:
millisecond
*/
...
...
@@ -191,12 +191,12 @@ eNBs =
NETWORK_INTERFACES
:
{
ENB_INTERFACE_NAME_FOR_S1_MME
=
"en
s3
"
;
ENB_IPV4_ADDRESS_FOR_S1_MME
=
"
CI_ENB_IP_ADDR
"
;
ENB_INTERFACE_NAME_FOR_S1U
=
"en
s3
"
;
ENB_IPV4_ADDRESS_FOR_S1U
=
"
CI_ENB_IP_ADDR
"
;
ENB_INTERFACE_NAME_FOR_S1_MME
=
"en
p68s0
"
;
ENB_IPV4_ADDRESS_FOR_S1_MME
=
"
10.1.1.68
"
;
ENB_INTERFACE_NAME_FOR_S1U
=
"en
p68s0
"
;
ENB_IPV4_ADDRESS_FOR_S1U
=
"
10.1.1.68
"
;
ENB_PORT_FOR_S1U
=
2152
;
# Spec 2152
ENB_IPV4_ADDRESS_FOR_X2C
=
"
CI_ENB_IP_ADDR
"
;
ENB_IPV4_ADDRESS_FOR_X2C
=
"
127.0.0.1
"
;
ENB_PORT_FOR_X2C
=
36422
;
# Spec 36422
};
...
...
@@ -215,7 +215,6 @@ MACRLCs = (
remote_s_portd
=
50010
;
tr_s_preference
=
"nfapi"
;
tr_n_preference
=
"local_RRC"
;
scheduler_mode
=
"fairRR"
;
}
);
...
...
ci-scripts/conf_files/ue.nfapi.conf
View file @
b90c0680
...
...
@@ -20,9 +20,9 @@ L1s = (
{
num_cc
=
1
;
tr_n_preference
=
"nfapi"
;
local_n_if_name
=
"
ens3
"
;
remote_n_address
=
"
CI_ENB_IP_ADDR
"
;
local_n_address
=
"
CI_UE_IP_ADDR
"
;
local_n_if_name
=
"
lo
"
;
remote_n_address
=
"
127.0.0.1
"
;
local_n_address
=
"
127.0.0.1
"
;
local_n_portc
=
50000
;
remote_n_portc
=
50001
;
local_n_portd
=
50010
;
...
...
openair3/NAS/TOOLS/display.c
View file @
b90c0680
...
...
@@ -262,12 +262,10 @@ void display_usim_data(const char *filename) {
kasme
[
USIM_K_ASME_SIZE
]
=
'\0'
;
memcpy
(
kasme
,
data
.
securityctx
.
Kasme
.
value
,
USIM_K_ASME_SIZE
);
printf
(
"
\t
Kasme
\t
:
\"
%s
\"\n
"
,
kasme
);
#if 0 //This doesn't compile anymore due to compiler warnings about pointers
printf("\tulNAScount\t: 0x%.8x\n",
/*printf("\tulNAScount\t: 0x%.8x\n",
*(uint32_t*) data.securityctx.ulNAScount.value);
printf("\tdlNAScount\t: 0x%.8x\n",
*(uint32_t*) data.securityctx.dlNAScount.value);
#endif
*(uint32_t*) data.securityctx.dlNAScount.value);*/
printf
(
"
\t
algorithmID
\t
: 0x%.2x
\n\n
"
,
data
.
securityctx
.
algorithmID
.
value
[
0
]);
...
...
openair3/S1AP/s1ap_eNB_handlers.c
View file @
b90c0680
...
...
@@ -38,6 +38,9 @@
#include "s1ap_eNB_defs.h"
#include "s1ap_eNB_handlers.h"
#include "s1ap_eNB_decoder.h"
#include "s1ap_eNB_encoder.h"
#include "s1ap_eNB_itti_messaging.h"
#include "s1ap_eNB_ue_context.h"
#include "s1ap_eNB_trace.h"
...
...
@@ -109,6 +112,20 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t as
uint32_t
stream
,
S1AP_S1AP_PDU_t
*
pdu
);
static
int
s1ap_eNB_snd_s1_setup_request
(
s1ap_eNB_instance_t
*
instance_p
,
s1ap_eNB_mme_data_t
*
s1ap_mme_data_p
);
int
s1ap_timer_setup
(
uint32_t
interval_sec
,
uint32_t
interval_us
,
task_id_t
task_id
,
int32_t
instance
,
uint32_t
timer_kind
,
timer_type_t
type
,
void
*
timer_arg
,
long
*
timer_id
);
/* Handlers matrix. Only eNB related procedure present here */
s1ap_message_decoded_callback
messages_callback
[][
3
]
=
{
{
0
,
0
,
0
},
/* HandoverPreparation */
...
...
@@ -260,6 +277,10 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
S1AP_S1SetupFailure_t
*
container
;
S1AP_S1SetupFailureIEs_t
*
ie
;
s1ap_eNB_mme_data_t
*
mme_desc_p
;
uint32_t
interval_sec
=
0
;
uint32_t
timer_kind
=
0
;
s1ap_eNB_instance_t
*
instance_p
;
DevAssert
(
pdu
!=
NULL
);
container
=
&
pdu
->
choice
.
unsuccessfulOutcome
.
value
.
choice
.
S1SetupFailure
;
...
...
@@ -270,7 +291,7 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
}
if
((
mme_desc_p
=
s1ap_eNB_get_MME
(
NULL
,
assoc_id
,
0
))
==
NULL
)
{
S1AP_ERROR
(
"[SCTP %d] Received S1 setup
respons
e for non existing "
S1AP_ERROR
(
"[SCTP %d] Received S1 setup
failur
e for non existing "
"MME context
\n
"
,
assoc_id
);
return
-
1
;
}
...
...
@@ -278,6 +299,10 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_S1SetupFailureIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_Cause
,
true
);
if
(
ie
==
NULL
)
{
return
-
1
;
}
if
((
ie
->
value
.
choice
.
Cause
.
present
==
S1AP_Cause_PR_misc
)
&&
(
ie
->
value
.
choice
.
Cause
.
choice
.
misc
==
S1AP_CauseMisc_unspecified
))
{
S1AP_WARN
(
"Received s1 setup failure for MME... MME is not ready
\n
"
);
...
...
@@ -285,8 +310,56 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
S1AP_ERROR
(
"Received s1 setup failure for MME... please check your parameters
\n
"
);
}
mme_desc_p
->
state
=
S1AP_ENB_STATE_WAITING
;
s1ap_handle_s1_setup_message
(
mme_desc_p
,
0
);
if
(
mme_desc_p
->
timer_id
!=
S1AP_TIMERID_INIT
)
{
s1ap_timer_remove
(
mme_desc_p
->
timer_id
);
mme_desc_p
->
timer_id
=
S1AP_TIMERID_INIT
;
}
instance_p
=
mme_desc_p
->
s1ap_eNB_instance
;
if
(
(
instance_p
->
s1_setupreq_count
>=
mme_desc_p
->
s1_setupreq_cnt
)
||
(
instance_p
->
s1_setupreq_count
==
0xffff
)
)
{
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_S1SetupFailureIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_TimeToWait
,
false
);
if
(
ie
!=
NULL
)
{
switch
(
ie
->
value
.
choice
.
TimeToWait
)
{
case
S1AP_TimeToWait_v1s
:
interval_sec
=
1
;
break
;
case
S1AP_TimeToWait_v2s
:
interval_sec
=
2
;
break
;
case
S1AP_TimeToWait_v5s
:
interval_sec
=
5
;
break
;
case
S1AP_TimeToWait_v10s
:
interval_sec
=
10
;
break
;
case
S1AP_TimeToWait_v20s
:
interval_sec
=
20
;
break
;
case
S1AP_TimeToWait_v60s
:
interval_sec
=
60
;
break
;
default:
interval_sec
=
instance_p
->
s1_setupreq_wait_timer
;
break
;
}
}
else
{
interval_sec
=
instance_p
->
s1_setupreq_wait_timer
;
}
timer_kind
=
mme_desc_p
->
cnx_id
;
timer_kind
=
timer_kind
|
S1AP_MMEIND
;
timer_kind
=
timer_kind
|
S1_SETREQ_WAIT
;
if
(
s1ap_timer_setup
(
interval_sec
,
0
,
TASK_S1AP
,
instance_p
->
instance
,
timer_kind
,
S1AP_TIMER_ONE_SHOT
,
NULL
,
&
mme_desc_p
->
timer_id
)
<
0
)
{
S1AP_ERROR
(
"Timer Start NG(S1 Setup Request) : MME=%d
\n
"
,
mme_desc_p
->
cnx_id
);
s1ap_eNB_snd_s1_setup_request
(
instance_p
,
mme_desc_p
);
}
}
else
{
S1AP_ERROR
(
"Retransmission count exceeded of S1 SETUP REQUEST : MME=%d
\n
"
,
mme_desc_p
->
cnx_id
);
}
return
0
;
}
...
...
@@ -314,9 +387,27 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
return
-
1
;
}
/* Set the capacity of this MME */
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_S1SetupResponseIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_RelativeMMECapacity
,
true
);
if
(
ie
==
NULL
)
{
return
-
1
;
}
mme_desc_p
->
relative_mme_capacity
=
ie
->
value
.
choice
.
RelativeMMECapacity
;
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_S1SetupResponseIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_ServedGUMMEIs
,
true
);
if
(
ie
==
NULL
)
{
return
-
1
;
}
if
(
mme_desc_p
->
timer_id
!=
S1AP_TIMERID_INIT
)
{
s1ap_timer_remove
(
mme_desc_p
->
timer_id
);
mme_desc_p
->
timer_id
=
S1AP_TIMERID_INIT
;
}
mme_desc_p
->
s1_setupreq_cnt
=
0
;
mme_desc_p
->
sctp_req_cnt
=
0
;
/* The list of served gummei can contain at most 8 elements.
* LTE related gummei is the first element in the list, i.e with an id of 0.
*/
...
...
@@ -369,12 +460,6 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
STAILQ_INSERT_TAIL
(
&
mme_desc_p
->
served_gummei
,
new_gummei_p
,
next
);
}
/* Set the capacity of this MME */
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_S1SetupResponseIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_RelativeMMECapacity
,
true
);
mme_desc_p
->
relative_mme_capacity
=
ie
->
value
.
choice
.
RelativeMMECapacity
;
/* Optionaly set the mme name */
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_S1SetupResponseIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_MMEname
,
false
);
...
...
@@ -725,6 +810,9 @@ int s1ap_eNB_handle_error_indication(uint32_t assoc_id,
S1AP_ProtocolIE_ID_id_CriticalityDiagnostics
,
false
);
if
(
ie
)
{
if
(
ie
->
value
.
choice
.
CriticalityDiagnostics
.
procedureCode
)
{
S1AP_WARN
(
"Received S1 Error indication CriticalityDiagnostics procedureCode = %ld
\n
"
,
*
ie
->
value
.
choice
.
CriticalityDiagnostics
.
procedureCode
);
}
// TODO continue
}
...
...
@@ -807,9 +895,11 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
&
(
S1AP_INITIAL_CONTEXT_SETUP_REQ
(
message_p
).
ue_ambr
.
br_dl
));
/* id-E-RABToBeSetupListCtxtSUReq */
}
else
{
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_InitialContextSetupRequestIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_E_RABToBeSetupListCtxtSUReq
,
true
);
...
...
@@ -852,6 +942,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
item_p
->
e_RABlevelQoSParameters
.
allocationRetentionPriority
.
pre_emptionVulnerability
;
}
/* for i... */
}
else
{
/* ie != NULL */
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -865,6 +956,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
S1AP_INITIAL_CONTEXT_SETUP_REQ
(
message_p
).
security_capabilities
.
integrity_algorithms
=
BIT_STRING_to_uint16
(
&
ie
->
value
.
choice
.
UESecurityCapabilities
.
integrityProtectionAlgorithms
);
}
else
{
/* ie != NULL */
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -876,6 +968,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
memcpy
(
&
S1AP_INITIAL_CONTEXT_SETUP_REQ
(
message_p
).
security_key
,
ie
->
value
.
choice
.
SecurityKey
.
buf
,
ie
->
value
.
choice
.
SecurityKey
.
size
);
}
else
{
/* ie != NULL */
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -918,6 +1011,13 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id,
return
-
1
;
}
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_UEContextReleaseCommand_IEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_Cause
,
true
);
if
(
ie
==
NULL
)
{
S1AP_ERROR
(
"Mandatory Element Nothing : UEContextReleaseCommand(Cause)
\n
"
);
return
-
1
;
}
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_UEContextReleaseCommand_IEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_UE_S1AP_IDs
,
true
);
...
...
@@ -965,9 +1065,26 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id,
//#warning "TODO mapping mme_ue_s1ap_id enb_ue_s1ap_id?"
case
S1AP_UE_S1AP_IDs_PR_mME_UE_S1AP_ID
:
mme_ue_s1ap_id
=
ie
->
value
.
choice
.
UE_S1AP_IDs
.
choice
.
uE_S1AP_ID_pair
.
mME_UE_S1AP_ID
;
S1AP_ERROR
(
"TO DO mapping mme_ue_s1ap_id enb_ue_s1ap_id"
);
(
void
)
mme_ue_s1ap_id
;
/* TODO: remove - it's to remove gcc warning about unused var */
mme_ue_s1ap_id
=
ie
->
value
.
choice
.
UE_S1AP_IDs
.
choice
.
mME_UE_S1AP_ID
;
RB_FOREACH
(
ue_desc_p
,
s1ap_ue_map
,
&
mme_desc_p
->
s1ap_eNB_instance
->
s1ap_ue_head
)
{
if
(
ue_desc_p
->
mme_ue_s1ap_id
==
mme_ue_s1ap_id
)
{
enb_ue_s1ap_id
=
ue_desc_p
->
eNB_ue_s1ap_id
;
message_p
=
itti_alloc_new_message
(
TASK_S1AP
,
0
,
S1AP_UE_CONTEXT_RELEASE_COMMAND
);
S1AP_UE_CONTEXT_RELEASE_COMMAND
(
message_p
).
eNB_ue_s1ap_id
=
enb_ue_s1ap_id
;
itti_send_msg_to_task
(
TASK_RRC_ENB
,
ue_desc_p
->
eNB_instance
->
instance
,
message_p
);
return
0
;
}
}
S1AP_ERROR
(
"[SCTP %d] Received UE context release command(mME_UE_S1AP_ID) for non "
"existing UE context 0x%06lx
\n
"
,
assoc_id
,
mme_ue_s1ap_id
);
return
-
1
;
case
S1AP_UE_S1AP_IDs_PR_NOTHING
:
default:
...
...
@@ -975,12 +1092,10 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id,
return
-
1
;
}
}
else
{
S1AP_ERROR
(
"Mandatory Element Nothing : UEContextReleaseCommand(UE_S1AP_IDs)
\n
"
);
return
-
1
;
}
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_UEContextReleaseCommand_IEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_Cause
,
true
);
/* TBD */
}
static
...
...
@@ -999,7 +1114,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id,
container
=
&
pdu
->
choice
.
initiatingMessage
.
value
.
choice
.
E_RABSetupRequest
;
if
((
mme_desc_p
=
s1ap_eNB_get_MME
(
NULL
,
assoc_id
,
0
))
==
NULL
)
{
S1AP_ERROR
(
"[SCTP %d] Received
initial context
setup request for non "
S1AP_ERROR
(
"[SCTP %d] Received
E-RAB
setup request for non "
"existing MME context
\n
"
,
assoc_id
);
return
-
1
;
}
...
...
@@ -1026,7 +1141,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id,
if
((
ue_desc_p
=
s1ap_eNB_get_ue_context
(
mme_desc_p
->
s1ap_eNB_instance
,
enb_ue_s1ap_id
))
==
NULL
)
{
S1AP_ERROR
(
"[SCTP %d] Received initial context
setup request for non "
S1AP_ERROR
(
"[SCTP %d] Received E-RAB
setup request for non "
"existing UE context 0x%06lx
\n
"
,
assoc_id
,
enb_ue_s1ap_id
);
return
-
1
;
...
...
@@ -1099,6 +1214,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id,
itti_send_msg_to_task
(
TASK_RRC_ENB
,
ue_desc_p
->
eNB_instance
->
instance
,
message_p
);
}
else
{
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -1119,13 +1235,6 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id,
// received Paging Message from MME
S1AP_DEBUG
(
"[SCTP %d] Received Paging Message From MME
\n
"
,
assoc_id
);
/* Paging procedure -> stream != 0 */
if
(
stream
==
0
)
{
LOG_W
(
S1AP
,
"[SCTP %d] Received Paging procedure on stream (%d)
\n
"
,
assoc_id
,
stream
);
return
-
1
;
}
if
((
mme_desc_p
=
s1ap_eNB_get_MME
(
NULL
,
assoc_id
,
0
))
==
NULL
)
{
S1AP_ERROR
(
"[SCTP %d] Received Paging for non "
"existing MME context
\n
"
,
assoc_id
);
...
...
@@ -1153,6 +1262,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id,
S1AP_PAGING_IND
(
message_p
).
ue_paging_identity
.
choice
.
s_tmsi
.
mme_code
=
0
;
S1AP_PAGING_IND
(
message_p
).
ue_paging_identity
.
choice
.
s_tmsi
.
m_tmsi
=
0
;
}
else
{
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -1180,6 +1290,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id,
if
(
i
!=
ie
->
value
.
choice
.
UEPagingID
.
choice
.
iMSI
.
size
-
1
)
{
/* invalid paging_p->uePagingID.choise.iMSI.buffer */
S1AP_ERROR
(
"[SCTP %d] Received Paging : uePagingID.choise.iMSI error(i %d 0x0F)
\n
"
,
assoc_id
,
i
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
}
else
{
...
...
@@ -1190,14 +1301,17 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id,
if
(
S1AP_PAGING_IND
(
message_p
).
ue_paging_identity
.
choice
.
imsi
.
length
>=
S1AP_IMSI_LENGTH
)
{
/* invalid paging_p->uePagingID.choise.iMSI.size */
S1AP_ERROR
(
"[SCTP %d] Received Paging : uePagingID.choise.iMSI.size(%d) is over IMSI length(%d)
\n
"
,
assoc_id
,
S1AP_PAGING_IND
(
message_p
).
ue_paging_identity
.
choice
.
imsi
.
length
,
S1AP_IMSI_LENGTH
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
}
else
{
/* of if (ie->value.choice.UEPagingID.present == S1AP_UEPagingID_PR_iMSI) */
/* invalid paging_p->uePagingID.present */
S1AP_ERROR
(
"[SCTP %d] Received Paging : uePagingID.present(%d) is unknown
\n
"
,
assoc_id
,
ie
->
value
.
choice
.
UEPagingID
.
present
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
}
else
{
/* of ie != NULL */
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -1230,6 +1344,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id,
return
-
1
;
}
}
else
{
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -1257,6 +1372,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id,
S1AP_PAGING_IND
(
message_p
).
tac
[
i
]);
}
}
else
{
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -1351,6 +1467,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id,
S1AP_E_RAB_MODIFY_RESP
(
message_p
).
e_rabs_failed
[
nb_of_e_rabs_failed
].
cause_value
=
S1AP_CauseRadioNetwork_unknown_mme_ue_s1ap_id
;
}
}
else
{
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -1403,6 +1520,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id,
itti_send_msg_to_task
(
TASK_RRC_ENB
,
ue_desc_p
->
eNB_instance
->
instance
,
message_p
);
}
else
{
/* of if (ie != NULL)*/
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -1476,22 +1594,6 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id,
message_p
=
itti_alloc_new_message
(
TASK_S1AP
,
0
,
S1AP_E_RAB_RELEASE_COMMAND
);
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
eNB_ue_s1ap_id
=
enb_ue_s1ap_id
;
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
mme_ue_s1ap_id
=
mme_ue_s1ap_id
;
/* id-NAS-PDU */
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_E_RABReleaseCommandIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_NAS_PDU
,
false
);
if
(
ie
&&
ie
->
value
.
choice
.
NAS_PDU
.
size
>
0
)
{
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
nas_pdu
.
length
=
ie
->
value
.
choice
.
NAS_PDU
.
size
;
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
nas_pdu
.
buffer
=
malloc
(
sizeof
(
uint8_t
)
*
ie
->
value
.
choice
.
NAS_PDU
.
size
);
memcpy
(
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
nas_pdu
.
buffer
,
ie
->
value
.
choice
.
NAS_PDU
.
buf
,
ie
->
value
.
choice
.
NAS_PDU
.
size
);
}
else
{
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
nas_pdu
.
length
=
0
;
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
nas_pdu
.
buffer
=
NULL
;
}
/* id-E-RABToBeReleasedList */
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_E_RABReleaseCommandIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList
,
true
);
...
...
@@ -1506,9 +1608,25 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id,
S1AP_DEBUG
(
"[SCTP] Received E-RAB release command for e-rab id %ld
\n
"
,
item_p
->
e_RAB_ID
);
}
}
else
{
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
/* id-NAS-PDU */
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_E_RABReleaseCommandIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_NAS_PDU
,
false
);
if
(
ie
&&
ie
->
value
.
choice
.
NAS_PDU
.
size
>
0
)
{
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
nas_pdu
.
length
=
ie
->
value
.
choice
.
NAS_PDU
.
size
;
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
nas_pdu
.
buffer
=
malloc
(
sizeof
(
uint8_t
)
*
ie
->
value
.
choice
.
NAS_PDU
.
size
);
memcpy
(
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
nas_pdu
.
buffer
,
ie
->
value
.
choice
.
NAS_PDU
.
buf
,
ie
->
value
.
choice
.
NAS_PDU
.
size
);
}
else
{
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
nas_pdu
.
length
=
0
;
S1AP_E_RAB_RELEASE_COMMAND
(
message_p
).
nas_pdu
.
buffer
=
NULL
;
}
itti_send_msg_to_task
(
TASK_RRC_ENB
,
ue_desc_p
->
eNB_instance
->
instance
,
message_p
);
return
0
;
}
...
...
@@ -1533,7 +1651,6 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id,
if
(
stream
==
0
)
{
S1AP_ERROR
(
"[SCTP %d] Received s1 path switch request ack on stream (%d)
\n
"
,
assoc_id
,
stream
);
//return -1;
}
if
((
mme_desc_p
=
s1ap_eNB_get_MME
(
NULL
,
assoc_id
,
0
))
==
NULL
)
{
...
...
@@ -1550,6 +1667,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id,
if
(
ie
==
NULL
)
{
S1AP_ERROR
(
"[SCTP %d] Received path switch request ack for non "
"ie context is NULL
\n
"
,
assoc_id
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -1572,6 +1690,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id,
if
(
ie
==
NULL
)
{
S1AP_ERROR
(
"[SCTP %d] Received path switch request ack for non "
"ie context is NULL
\n
"
,
assoc_id
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -1589,6 +1708,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id,
if
(
ie
==
NULL
)
{
S1AP_ERROR
(
"[SCTP %d] Received path switch request ack for non "
"ie context is NULL
\n
"
,
assoc_id
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
message_p
),
message_p
);
return
-
1
;
}
...
...
@@ -1602,14 +1722,10 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id,
S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate
,
false
);
if
(
ie
)
{
OCTET_STRING_TO_INT32
(
&
ie
->
value
.
choice
.
UEAggregateMaximumBitrate
.
uEaggregateMaximumBitRateUL
,
S1AP_PATH_SWITCH_REQ_ACK
(
message_p
).
ue_ambr
.
br_ul
);
OCTET_STRING_TO_INT32
(
&
ie
->
value
.
choice
.
UEAggregateMaximumBitrate
.
uEaggregateMaximumBitRateDL
,
S1AP_PATH_SWITCH_REQ_ACK
(
message_p
).
ue_ambr
.
br_dl
);
asn_INTEGER2ulong
(
&
ie
->
value
.
choice
.
UEAggregateMaximumBitrate
.
uEaggregateMaximumBitRateUL
,
&
S1AP_PATH_SWITCH_REQ_ACK
(
message_p
).
ue_ambr
.
br_ul
);
asn_INTEGER2ulong
(
&
ie
->
value
.
choice
.
UEAggregateMaximumBitrate
.
uEaggregateMaximumBitRateDL
,
&
S1AP_PATH_SWITCH_REQ_ACK
(
message_p
).
ue_ambr
.
br_dl
);
}
else
{
S1AP_WARN
(
"UEAggregateMaximumBitrate not supported
\n
"
);
S1AP_PATH_SWITCH_REQ_ACK
(
message_p
).
ue_ambr
.
br_ul
=
0
;
...
...
@@ -1688,9 +1804,8 @@ int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t assoc_
pathSwitchRequestFailure
=
&
pdu
->
choice
.
unsuccessfulOutcome
.
value
.
choice
.
PathSwitchRequestFailure
;
if
(
stream
!=
0
)
{
S1AP_
ERROR
(
"[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)
\n
"
,
S1AP_
WARN
(
"[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)
\n
"
,
assoc_id
,
stream
);
return
-
1
;
}
if
((
mme_desc_p
=
s1ap_eNB_get_MME
(
NULL
,
assoc_id
,
0
))
==
NULL
)
{
...
...
@@ -1754,3 +1869,144 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t as
return
0
;
}
//-----------------------------------------------------------------------------
/*
* eNB generate a S1 setup request towards MME
*/
static
int
s1ap_eNB_snd_s1_setup_request
(
s1ap_eNB_instance_t
*
instance_p
,
s1ap_eNB_mme_data_t
*
s1ap_mme_data_p
)
//-----------------------------------------------------------------------------
{
S1AP_S1AP_PDU_t
pdu
;
S1AP_S1SetupRequest_t
*
out
=
NULL
;
S1AP_S1SetupRequestIEs_t
*
ie
=
NULL
;
S1AP_SupportedTAs_Item_t
*
ta
=
NULL
;
S1AP_PLMNidentity_t
*
plmn
=
NULL
;
uint8_t
*
buffer
=
NULL
;
uint32_t
len
=
0
;
int
ret
=
0
;
uint32_t
timer_kind
=
0
;
DevAssert
(
instance_p
!=
NULL
);
DevAssert
(
s1ap_mme_data_p
!=
NULL
);
s1ap_mme_data_p
->
state
=
S1AP_ENB_STATE_WAITING
;
/* Prepare the S1AP message to encode */
memset
(
&
pdu
,
0
,
sizeof
(
pdu
));
pdu
.
present
=
S1AP_S1AP_PDU_PR_initiatingMessage
;
pdu
.
choice
.
initiatingMessage
.
procedureCode
=
S1AP_ProcedureCode_id_S1Setup
;
pdu
.
choice
.
initiatingMessage
.
criticality
=
S1AP_Criticality_reject
;
pdu
.
choice
.
initiatingMessage
.
value
.
present
=
S1AP_InitiatingMessage__value_PR_S1SetupRequest
;
out
=
&
pdu
.
choice
.
initiatingMessage
.
value
.
choice
.
S1SetupRequest
;
/* mandatory */
ie
=
(
S1AP_S1SetupRequestIEs_t
*
)
calloc
(
1
,
sizeof
(
S1AP_S1SetupRequestIEs_t
));
ie
->
id
=
S1AP_ProtocolIE_ID_id_Global_ENB_ID
;
ie
->
criticality
=
S1AP_Criticality_reject
;
ie
->
value
.
present
=
S1AP_S1SetupRequestIEs__value_PR_Global_ENB_ID
;
MCC_MNC_TO_PLMNID
(
instance_p
->
mcc
[
s1ap_mme_data_p
->
broadcast_plmn_index
[
0
]],
instance_p
->
mnc
[
s1ap_mme_data_p
->
broadcast_plmn_index
[
0
]],
instance_p
->
mnc_digit_length
[
s1ap_mme_data_p
->
broadcast_plmn_index
[
0
]],
&
ie
->
value
.
choice
.
Global_ENB_ID
.
pLMNidentity
);
ie
->
value
.
choice
.
Global_ENB_ID
.
eNB_ID
.
present
=
S1AP_ENB_ID_PR_macroENB_ID
;
MACRO_ENB_ID_TO_BIT_STRING
(
instance_p
->
eNB_id
,
&
ie
->
value
.
choice
.
Global_ENB_ID
.
eNB_ID
.
choice
.
macroENB_ID
);
S1AP_INFO
(
"%d -> %02x%02x%02x
\n
"
,
instance_p
->
eNB_id
,
ie
->
value
.
choice
.
Global_ENB_ID
.
eNB_ID
.
choice
.
macroENB_ID
.
buf
[
0
],
ie
->
value
.
choice
.
Global_ENB_ID
.
eNB_ID
.
choice
.
macroENB_ID
.
buf
[
1
],
ie
->
value
.
choice
.
Global_ENB_ID
.
eNB_ID
.
choice
.
macroENB_ID
.
buf
[
2
]);
ASN_SEQUENCE_ADD
(
&
out
->
protocolIEs
.
list
,
ie
);
/* optional */
if
(
instance_p
->
eNB_name
)
{
ie
=
(
S1AP_S1SetupRequestIEs_t
*
)
calloc
(
1
,
sizeof
(
S1AP_S1SetupRequestIEs_t
));
ie
->
id
=
S1AP_ProtocolIE_ID_id_eNBname
;
ie
->
criticality
=
S1AP_Criticality_ignore
;
ie
->
value
.
present
=
S1AP_S1SetupRequestIEs__value_PR_ENBname
;
OCTET_STRING_fromBuf
(
&
ie
->
value
.
choice
.
ENBname
,
instance_p
->
eNB_name
,
strlen
(
instance_p
->
eNB_name
));
ASN_SEQUENCE_ADD
(
&
out
->
protocolIEs
.
list
,
ie
);
}
/* mandatory */
ie
=
(
S1AP_S1SetupRequestIEs_t
*
)
calloc
(
1
,
sizeof
(
S1AP_S1SetupRequestIEs_t
));
ie
->
id
=
S1AP_ProtocolIE_ID_id_SupportedTAs
;
ie
->
criticality
=
S1AP_Criticality_reject
;
ie
->
value
.
present
=
S1AP_S1SetupRequestIEs__value_PR_SupportedTAs
;
{
ta
=
(
S1AP_SupportedTAs_Item_t
*
)
calloc
(
1
,
sizeof
(
S1AP_SupportedTAs_Item_t
));
INT16_TO_OCTET_STRING
(
instance_p
->
tac
,
&
ta
->
tAC
);
{
for
(
int
i
=
0
;
i
<
s1ap_mme_data_p
->
broadcast_plmn_num
;
++
i
)
{
plmn
=
(
S1AP_PLMNidentity_t
*
)
calloc
(
1
,
sizeof
(
S1AP_PLMNidentity_t
));
MCC_MNC_TO_TBCD
(
instance_p
->
mcc
[
s1ap_mme_data_p
->
broadcast_plmn_index
[
i
]],
instance_p
->
mnc
[
s1ap_mme_data_p
->
broadcast_plmn_index
[
i
]],
instance_p
->
mnc_digit_length
[
s1ap_mme_data_p
->
broadcast_plmn_index
[
i
]],
plmn
);
ASN_SEQUENCE_ADD
(
&
ta
->
broadcastPLMNs
.
list
,
plmn
);
}
}
ASN_SEQUENCE_ADD
(
&
ie
->
value
.
choice
.
SupportedTAs
.
list
,
ta
);
}
ASN_SEQUENCE_ADD
(
&
out
->
protocolIEs
.
list
,
ie
);
/* mandatory */
ie
=
(
S1AP_S1SetupRequestIEs_t
*
)
calloc
(
1
,
sizeof
(
S1AP_S1SetupRequestIEs_t
));
ie
->
id
=
S1AP_ProtocolIE_ID_id_DefaultPagingDRX
;
ie
->
criticality
=
S1AP_Criticality_ignore
;
ie
->
value
.
present
=
S1AP_S1SetupRequestIEs__value_PR_PagingDRX
;
ie
->
value
.
choice
.
PagingDRX
=
instance_p
->
default_drx
;
ASN_SEQUENCE_ADD
(
&
out
->
protocolIEs
.
list
,
ie
);
/* optional */
if
(
0
)
{
ie
=
(
S1AP_S1SetupRequestIEs_t
*
)
calloc
(
1
,
sizeof
(
S1AP_S1SetupRequestIEs_t
));
ie
->
id
=
S1AP_ProtocolIE_ID_id_CSG_IdList
;
ie
->
criticality
=
S1AP_Criticality_reject
;
ie
->
value
.
present
=
S1AP_S1SetupRequestIEs__value_PR_CSG_IdList
;
// ie->value.choice.CSG_IdList = ;
ASN_SEQUENCE_ADD
(
&
out
->
protocolIEs
.
list
,
ie
);
}
/* optional */
#if (S1AP_VERSION >= MAKE_VERSION(13, 0, 0))
if
(
0
)
{
ie
=
(
S1AP_S1SetupRequestIEs_t
*
)
calloc
(
1
,
sizeof
(
S1AP_S1SetupRequestIEs_t
));
ie
->
id
=
S1AP_ProtocolIE_ID_id_UE_RetentionInformation
;
ie
->
criticality
=
S1AP_Criticality_ignore
;
ie
->
value
.
present
=
S1AP_S1SetupRequestIEs__value_PR_UE_RetentionInformation
;
// ie->value.choice.UE_RetentionInformation = ;
ASN_SEQUENCE_ADD
(
&
out
->
protocolIEs
.
list
,
ie
);
}
/* optional */
if
(
0
)
{
ie
=
(
S1AP_S1SetupRequestIEs_t
*
)
calloc
(
1
,
sizeof
(
S1AP_S1SetupRequestIEs_t
));
ie
->
id
=
S1AP_ProtocolIE_ID_id_NB_IoT_DefaultPagingDRX
;
ie
->
criticality
=
S1AP_Criticality_ignore
;
ie
->
value
.
present
=
S1AP_S1SetupRequestIEs__value_PR_NB_IoT_DefaultPagingDRX
;
// ie->value.choice.NB_IoT_DefaultPagingDRX = ;
ASN_SEQUENCE_ADD
(
&
out
->
protocolIEs
.
list
,
ie
);
}
#endif
/* #if (S1AP_VERSION >= MAKE_VERSION(14, 0, 0)) */
if
(
s1ap_eNB_encode_pdu
(
&
pdu
,
&
buffer
,
&
len
)
<
0
)
{
S1AP_ERROR
(
"Failed to encode S1 setup request
\n
"
);
return
-
1
;
}
timer_kind
=
s1ap_mme_data_p
->
cnx_id
;
timer_kind
=
timer_kind
|
S1AP_MMEIND
;
timer_kind
=
timer_kind
|
S1_SETRSP_WAIT
;
if
(
s1ap_timer_setup
(
instance_p
->
s1_setuprsp_wait_timer
,
0
,
TASK_S1AP
,
instance_p
->
instance
,
timer_kind
,
S1AP_TIMER_ONE_SHOT
,
NULL
,
&
s1ap_mme_data_p
->
timer_id
)
<
0
)
{
S1AP_ERROR
(
"Timer Start NG(S1 Setup Response) : MME=%d
\n
"
,
s1ap_mme_data_p
->
cnx_id
);
}
s1ap_mme_data_p
->
s1_setupreq_cnt
++
;
/* Non UE-Associated signalling -> stream = 0 */
s1ap_eNB_itti_send_sctp_data_req
(
instance_p
->
instance
,
s1ap_mme_data_p
->
assoc_id
,
buffer
,
len
,
0
);
return
ret
;
}
targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf
View file @
b90c0680
...
...
@@ -225,21 +225,35 @@ gNBs =
//////////
MME
parameters
:
mme_ip_address
= ( {
ipv4
=
"192.168.
12.26
"
;
mme_ip_address
= ( {
ipv4
=
"192.168.
61.3
"
;
ipv6
=
"192:168:30::17"
;
active
=
"yes"
;
preference
=
"ipv4"
;
}
);
///
X2
enable_x2
=
"yes"
;
t_reloc_prep
=
1000
; /*
unit
:
millisecond
*/
tx2_reloc_overall
=
2000
; /*
unit
:
millisecond
*/
t_dc_prep
=
1000
; /*
unit
:
millisecond
*/
t_dc_overall
=
2000
; /*
unit
:
millisecond
*/
target_enb_x2_ip_address
= (
{
ipv4
=
"127.0.0.1"
; /*
"CI_FR1_CTL_ENB_IP_ADDR"
; */
ipv6
=
"192:168:30::17"
;
preference
=
"ipv4"
;
}
);
NETWORK_INTERFACES
:
{
GNB_INTERFACE_NAME_FOR_S1_MME
=
"
eth0
"
;
GNB_IPV4_ADDRESS_FOR_S1_MME
=
"1
92.168.12.111/24
"
;
GNB_INTERFACE_NAME_FOR_S1U
=
"
eth0
"
;
GNB_IPV4_ADDRESS_FOR_S1U
=
"1
92.168.12.111/24
"
;
GNB_INTERFACE_NAME_FOR_S1_MME
=
"
lo
"
;
GNB_IPV4_ADDRESS_FOR_S1_MME
=
"1
27.0.0.2
"
;
GNB_INTERFACE_NAME_FOR_S1U
=
"
lo
"
;
GNB_IPV4_ADDRESS_FOR_S1U
=
"1
27.0.0.2
"
;
GNB_PORT_FOR_S1U
=
2152
;
# Spec 2152
GNB_IPV4_ADDRESS_FOR_X2C
=
"127.0.0.2"
;
GNB_PORT_FOR_X2C
=
36422
;
# Spec 36422
};
}
);
...
...
@@ -249,7 +263,7 @@ MACRLCs = (
{
num_cc
=
1
;
local_s_if_name
=
"lo:"
;
remote_s_address
=
"127.0.0.
1
"
; //
pnf
addr
[!]
remote_s_address
=
"127.0.0.
2
"
; //
pnf
addr
[!]
local_s_address
=
"127.0.0.2"
; //
vnf
addr
local_s_portc
=
50001
; //
vnf
p5
port
remote_s_portc
=
50000
; //
pnf
p5
port
[!]
...
...
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