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
wangjie
OpenXG-RAN
Commits
46407ca4
Commit
46407ca4
authored
Apr 08, 2020
by
Haruki NAOI
Committed by
masayuki.harada
Jan 06, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add S1down auto recovery.
(cherry picked from commit 2339972ceaeb75fe18c0b2ae9ea69216dd919668)
parent
7631a1dc
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1287 additions
and
116 deletions
+1287
-116
cmake_targets/CMakeLists.txt
cmake_targets/CMakeLists.txt
+1
-0
openair2/COMMON/s1ap_messages_types.h
openair2/COMMON/s1ap_messages_types.h
+5
-0
openair2/COMMON/tasks_def.h
openair2/COMMON/tasks_def.h
+2
-1
openair2/ENB_APP/enb_config.c
openair2/ENB_APP/enb_config.c
+59
-0
openair2/ENB_APP/enb_paramdef.h
openair2/ENB_APP/enb_paramdef.h
+15
-0
openair2/X2AP/x2ap_common.h
openair2/X2AP/x2ap_common.h
+1
-1
openair2/X2AP/x2ap_eNB_handler.c
openair2/X2AP/x2ap_eNB_handler.c
+34
-1
openair3/S1AP/s1ap_common.h
openair3/S1AP/s1ap_common.h
+6
-1
openair3/S1AP/s1ap_eNB.c
openair3/S1AP/s1ap_eNB.c
+362
-36
openair3/S1AP/s1ap_eNB_defs.h
openair3/S1AP/s1ap_eNB_defs.h
+12
-0
openair3/S1AP/s1ap_eNB_handlers.c
openair3/S1AP/s1ap_eNB_handlers.c
+340
-65
openair3/S1AP/s1ap_eNB_management_procedures.c
openair3/S1AP/s1ap_eNB_management_procedures.c
+39
-8
openair3/S1AP/s1ap_eNB_nas_procedures.c
openair3/S1AP/s1ap_eNB_nas_procedures.c
+12
-0
openair3/S1AP/s1ap_eNB_overload.c
openair3/S1AP/s1ap_eNB_overload.c
+4
-0
openair3/S1AP/s1ap_eNB_timer.c
openair3/S1AP/s1ap_eNB_timer.c
+300
-0
openair3/S1AP/s1ap_eNB_timer.h
openair3/S1AP/s1ap_eNB_timer.h
+86
-0
openair3/S1AP/s1ap_eNB_trace.c
openair3/S1AP/s1ap_eNB_trace.c
+4
-0
openair3/SCTP/sctp_default_values.h
openair3/SCTP/sctp_default_values.h
+2
-2
openair3/SCTP/sctp_eNB_task.c
openair3/SCTP/sctp_eNB_task.c
+3
-1
No files found.
cmake_targets/CMakeLists.txt
View file @
46407ca4
...
...
@@ -540,6 +540,7 @@ add_library(S1AP_ENB
${
S1AP_DIR
}
/s1ap_eNB_overload.c
${
S1AP_DIR
}
/s1ap_eNB_trace.c
${
S1AP_DIR
}
/s1ap_eNB_ue_context.c
${
S1AP_DIR
}
/s1ap_eNB_timer.c
)
add_dependencies
(
S1AP_ENB rrc_flag s1ap_flag
)
...
...
openair2/COMMON/s1ap_messages_types.h
View file @
46407ca4
...
...
@@ -393,6 +393,11 @@ typedef struct s1ap_register_enb_req_s {
/* Number of SCTP streams used for a mme association */
uint16_t
sctp_in_streams
;
uint16_t
sctp_out_streams
;
uint16_t
s1_setuprsp_wait_timer
;
uint16_t
s1_setupreq_wait_timer
;
uint16_t
s1_setupreq_count
;
uint16_t
sctp_req_timer
;
uint16_t
sctp_req_count
;
}
s1ap_register_enb_req_t
;
//-------------------------------------------------------------------------------------------//
...
...
openair2/COMMON/tasks_def.h
View file @
46407ca4
...
...
@@ -47,7 +47,8 @@ TASK_DEF(TASK_RAL_ENB, TASK_PRIORITY_MED, 200)
TASK_DEF
(
TASK_UDP
,
TASK_PRIORITY_MED
,
1000
)
// GTP_V1U task
TASK_DEF
(
TASK_GTPV1_U
,
TASK_PRIORITY_MED
,
1000
)
TASK_DEF
(
TASK_S1AP
,
TASK_PRIORITY_MED
,
200
)
//TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200)
TASK_DEF
(
TASK_S1AP
,
TASK_PRIORITY_MED
,
2000
)
TASK_DEF
(
TASK_CU_F1
,
TASK_PRIORITY_MED
,
200
)
TASK_DEF
(
TASK_DU_F1
,
TASK_PRIORITY_MED
,
200
)
/// M3ap task, acts as both source and target
...
...
openair2/ENB_APP/enb_config.c
View file @
46407ca4
...
...
@@ -2426,6 +2426,65 @@ int RCconfig_S1(
"to
\n
"
" tracking_area_code = 1; // no string!!
\n
"
" plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )
\n
"
);
if
(
*
ENBParamList
.
paramarray
[
k
][
ENB_S1SETUP_RSP_TIMER_IDX
].
uptr
<=
0xffff
)
{
S1AP_REGISTER_ENB_REQ
(
msg_p
).
s1_setuprsp_wait_timer
=
*
ENBParamList
.
paramarray
[
k
][
ENB_S1SETUP_RSP_TIMER_IDX
].
uptr
;
}
else
{
LOG_E
(
S1AP
,
"s1setup_rsp_timer value in conf file is invalid (%d). Default value is set.
\n
"
,
*
ENBParamList
.
paramarray
[
k
][
ENB_S1SETUP_RSP_TIMER_IDX
].
uptr
);
S1AP_REGISTER_ENB_REQ
(
msg_p
).
s1_setuprsp_wait_timer
=
5
;
}
if
(
*
ENBParamList
.
paramarray
[
k
][
ENB_S1SETUP_REQ_TIMER_IDX
].
uptr
<=
0xffff
)
{
S1AP_REGISTER_ENB_REQ
(
msg_p
).
s1_setupreq_wait_timer
=
*
ENBParamList
.
paramarray
[
k
][
ENB_S1SETUP_REQ_TIMER_IDX
].
uptr
;
}
else
{
LOG_E
(
S1AP
,
"s1setup_req_timer value in conf file is invalid (%d). Default value is set.
\n
"
,
*
ENBParamList
.
paramarray
[
k
][
ENB_S1SETUP_REQ_TIMER_IDX
].
uptr
);
S1AP_REGISTER_ENB_REQ
(
msg_p
).
s1_setupreq_wait_timer
=
5
;
}
if
(
*
ENBParamList
.
paramarray
[
k
][
ENB_S1SETUP_REQ_COUNT_IDX
].
uptr
<=
0xffff
)
{
S1AP_REGISTER_ENB_REQ
(
msg_p
).
s1_setupreq_count
=
*
ENBParamList
.
paramarray
[
k
][
ENB_S1SETUP_REQ_COUNT_IDX
].
uptr
;
}
else
{
LOG_E
(
S1AP
,
"s1setup_req_count value in conf file is invalid (%d). Default value is set.
\n
"
,
*
ENBParamList
.
paramarray
[
k
][
ENB_S1SETUP_REQ_COUNT_IDX
].
uptr
);
S1AP_REGISTER_ENB_REQ
(
msg_p
).
s1_setupreq_count
=
0xffff
;
}
if
(
*
ENBParamList
.
paramarray
[
k
][
ENB_SCTP_REQ_TIMER_IDX
].
uptr
<=
0xffff
)
{
S1AP_REGISTER_ENB_REQ
(
msg_p
).
sctp_req_timer
=
*
ENBParamList
.
paramarray
[
k
][
ENB_SCTP_REQ_TIMER_IDX
].
uptr
;
}
else
{
LOG_E
(
S1AP
,
"sctp_req_timer value in conf file is invalid (%d). Default value is set.
\n
"
,
*
ENBParamList
.
paramarray
[
k
][
ENB_SCTP_REQ_TIMER_IDX
].
uptr
);
S1AP_REGISTER_ENB_REQ
(
msg_p
).
sctp_req_timer
=
180
;
}
if
(
*
ENBParamList
.
paramarray
[
k
][
ENB_SCTP_REQ_COUNT_IDX
].
uptr
<=
0xffff
)
{
S1AP_REGISTER_ENB_REQ
(
msg_p
).
sctp_req_count
=
*
ENBParamList
.
paramarray
[
k
][
ENB_SCTP_REQ_COUNT_IDX
].
uptr
;
}
else
{
LOG_E
(
S1AP
,
"sctp_req_count value in conf file is invalid (%d). Default value is set.
\n
"
,
*
ENBParamList
.
paramarray
[
k
][
ENB_SCTP_REQ_COUNT_IDX
].
uptr
);
S1AP_REGISTER_ENB_REQ
(
msg_p
).
sctp_req_count
=
0xffff
;
}
config_getlist
(
&
PLMNParamList
,
PLMNParams
,
sizeof
(
PLMNParams
)
/
sizeof
(
paramdef_t
),
aprefix
);
if
(
PLMNParamList
.
numelt
<
1
||
PLMNParamList
.
numelt
>
6
)
{
...
...
openair2/ENB_APP/enb_paramdef.h
View file @
46407ca4
...
...
@@ -214,6 +214,11 @@ typedef enum {
#define ENB_CONFIG_STRING_X2 "enable_x2"
#define ENB_CONFIG_STRING_ENB_M2 "enable_enb_m2"
#define ENB_CONFIG_STRING_MCE_M2 "enable_mce_m2"
#define ENB_CONFIG_STRING_S1SETUP_RSP_TIMER "s1setup_rsp_timer"
#define ENB_CONFIG_STRING_S1SETUP_REQ_TIMER "s1setup_req_timer"
#define ENB_CONFIG_STRING_S1SETUP_REQ_COUNT "s1setup_req_count"
#define ENB_CONFIG_STRING_SCTP_REQ_TIMER "sctp_req_timer"
#define ENB_CONFIG_STRING_SCTP_REQ_COUNT "sctp_req_count"
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
/* cell configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
...
...
@@ -239,6 +244,11 @@ typedef enum {
{ENB_CONFIG_STRING_X2, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_ENB_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_MCE_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_S1SETUP_RSP_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_S1SETUP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_S1SETUP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_SCTP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:180, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_SCTP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \
}
#define ENB_ENB_ID_IDX 0
...
...
@@ -261,6 +271,11 @@ typedef enum {
#define ENB_ENABLE_X2 17
#define ENB_ENABLE_ENB_M2 18
#define ENB_ENABLE_MCE_M2 19
#define ENB_S1SETUP_RSP_TIMER_IDX 20
#define ENB_S1SETUP_REQ_TIMER_IDX 21
#define ENB_S1SETUP_REQ_COUNT_IDX 22
#define ENB_SCTP_REQ_TIMER_IDX 23
#define ENB_SCTP_REQ_COUNT_IDX 24
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
#define ENBPARAMS_CHECK { \
...
...
openair2/X2AP/x2ap_common.h
View file @
46407ca4
...
...
@@ -84,7 +84,7 @@ extern int asn1_xer_print;
break; \
} \
} \
if (mandatory) DevAssert(ie != NULL);
\
/* if (mandatory) DevAssert(ie != NULL); \*/
\
} while(0)
/** \brief Function callback prototype.
...
...
openair2/X2AP/x2ap_eNB_handler.c
View file @
46407ca4
...
...
@@ -536,6 +536,14 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance,
return
-
1
;
}
if
((
x2ap_eNB_data
->
state
==
X2AP_ENB_STATE_CONNECTED
)
||
(
x2ap_eNB_data
->
state
==
X2AP_ENB_STATE_READY
))
{
X2AP_ERROR
(
"Received Unexpexted X2 Setup Response Message
\n
"
);
return
-
1
;
}
X2AP_DEBUG
(
"Received a new X2 setup response
\n
"
);
X2AP_FIND_PROTOCOLIE_BY_ID
(
X2AP_X2SetupResponse_IEs_t
,
ie
,
x2SetupResponse
,
...
...
@@ -662,6 +670,14 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance,
return
-
1
;
}
if
((
x2ap_eNB_data
->
state
==
X2AP_ENB_STATE_CONNECTED
)
||
(
x2ap_eNB_data
->
state
==
X2AP_ENB_STATE_READY
))
{
X2AP_ERROR
(
"Received Unexpexted X2 Setup Failure Message
\n
"
);
return
-
1
;
}
X2AP_DEBUG
(
"Received a new X2 setup failure
\n
"
);
X2AP_FIND_PROTOCOLIE_BY_ID
(
X2AP_X2SetupFailure_IEs_t
,
ie
,
x2SetupFailure
,
...
...
@@ -730,6 +746,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID
,
true
);
if
(
ie
==
NULL
)
{
X2AP_ERROR
(
"%s %d: ie is a NULL pointer
\n
"
,
__FILE__
,
__LINE__
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
msg
),
msg
);
return
-
1
;
}
...
...
@@ -750,7 +767,11 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
//measResultListEUTRA.list.array[ncell_index]->physCellId;
X2AP_FIND_PROTOCOLIE_BY_ID
(
X2AP_HandoverRequest_IEs_t
,
ie
,
x2HandoverRequest
,
X2AP_ProtocolIE_ID_id_GUMMEI_ID
,
true
);
if
(
ie
==
NULL
)
{
X2AP_ERROR
(
"%s %d: ie is a NULL pointer
\n
"
,
__FILE__
,
__LINE__
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
msg
),
msg
);
return
-
1
;
}
TBCD_TO_MCC_MNC
(
&
ie
->
value
.
choice
.
ECGI
.
pLMN_Identity
,
X2AP_HANDOVER_REQ
(
msg
).
ue_gummei
.
mcc
,
X2AP_HANDOVER_REQ
(
msg
).
ue_gummei
.
mnc
,
X2AP_HANDOVER_REQ
(
msg
).
ue_gummei
.
mnc_len
);
OCTET_STRING_TO_INT8
(
&
ie
->
value
.
choice
.
GUMMEI
.
mME_Code
,
X2AP_HANDOVER_REQ
(
msg
).
ue_gummei
.
mme_code
);
...
...
@@ -761,6 +782,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
if
(
ie
==
NULL
)
{
X2AP_ERROR
(
"%s %d: ie is a NULL pointer
\n
"
,
__FILE__
,
__LINE__
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
msg
),
msg
);
return
-
1
;
}
...
...
@@ -872,6 +894,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
if
(
ie
==
NULL
)
{
X2AP_ERROR
(
"%s %d: ie is a NULL pointer
\n
"
,
__FILE__
,
__LINE__
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
msg
),
msg
);
return
-
1
;
}
...
...
@@ -882,6 +905,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
if
(
ie
==
NULL
)
{
X2AP_ERROR
(
"%s %d: ie is a NULL pointer
\n
"
,
__FILE__
,
__LINE__
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
msg
),
msg
);
return
-
1
;
}
...
...
@@ -912,6 +936,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
if
(
ie
==
NULL
)
{
X2AP_ERROR
(
"%s %d: ie is a NULL pointer
\n
"
,
__FILE__
,
__LINE__
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
msg
),
msg
);
return
-
1
;
}
else
{
if
(
ie
->
value
.
choice
.
E_RABs_Admitted_List
.
list
.
count
>
0
)
{
...
...
@@ -959,6 +984,12 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
X2AP_FIND_PROTOCOLIE_BY_ID
(
X2AP_HandoverRequestAcknowledge_IEs_t
,
ie
,
x2HandoverRequestAck
,
X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer
,
true
);
if
(
ie
==
NULL
)
{
X2AP_ERROR
(
"%s %d: ie is a NULL pointer
\n
"
,
__FILE__
,
__LINE__
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
msg
),
msg
);
return
-
1
;
}
X2AP_TargeteNBtoSource_eNBTransparentContainer_t
*
c
=
&
ie
->
value
.
choice
.
TargeteNBtoSource_eNBTransparentContainer
;
if
(
c
->
size
>
1024
/* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s */
)
...
...
@@ -1012,6 +1043,7 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance,
if
(
ie
==
NULL
)
{
X2AP_ERROR
(
"%s %d: ie is a NULL pointer
\n
"
,
__FILE__
,
__LINE__
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
msg
),
msg
);
return
-
1
;
}
...
...
@@ -1022,6 +1054,7 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance,
if
(
ie
==
NULL
)
{
X2AP_ERROR
(
"%s %d: ie is a NULL pointer
\n
"
,
__FILE__
,
__LINE__
);
itti_free
(
ITTI_MSG_ORIGIN_ID
(
msg
),
msg
);
return
-
1
;
}
...
...
openair3/S1AP/s1ap_common.h
View file @
46407ca4
...
...
@@ -106,7 +106,12 @@ extern int asn1_xer_print;
if (ie == NULL ) { \
S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\
} \
if (mandatory) DevAssert(ie != NULL); \
if (mandatory) { \
if (ie == NULL) { \
S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\
return -1; \
} \
} \
} while(0)
/** \brief Function callback prototype.
**/
...
...
openair3/S1AP/s1ap_eNB.c
View file @
46407ca4
...
...
@@ -58,6 +58,8 @@
#include "s1ap_eNB_ue_context.h" // test, to be removed
#include "msc.h"
#include "s1ap_eNB_timer.h"
#include "assertions.h"
#include "conversions.h"
#if defined(TEST_S1C_MME)
...
...
@@ -73,6 +75,11 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
void
s1ap_eNB_handle_sctp_association_resp
(
instance_t
instance
,
sctp_new_association_resp_t
*
sctp_new_association_resp
);
static
int
s1ap_sctp_req
(
s1ap_eNB_instance_t
*
instance_p
,
s1ap_eNB_mme_data_t
*
s1ap_mme_data_p
);
void
s1ap_eNB_timer_expired
(
instance_t
instance
,
s1ap_timer_has_expired_t
*
msg_p
);
uint32_t
s1ap_generate_eNB_id
(
void
)
{
char
*
out
;
char
hostname
[
50
];
...
...
@@ -114,9 +121,9 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
local_ip_addr
,
sizeof
(
*
local_ip_addr
));
S1AP_INFO
(
"[eNB %d] check the mme registration state
\n
"
,
instance_p
->
instance
);
mme
=
NULL
;
if
(
mme
==
NULL
)
{
//
mme = NULL;
//
//
if ( mme == NULL ) {
/* Create new MME descriptor */
s1ap_mme_data_p
=
calloc
(
1
,
sizeof
(
*
s1ap_mme_data_p
));
DevAssert
(
s1ap_mme_data_p
!=
NULL
);
...
...
@@ -136,28 +143,33 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
* but not yet associated.
*/
RB_INSERT
(
s1ap_mme_map
,
&
instance_p
->
s1ap_mme_head
,
s1ap_mme_data_p
);
s1ap_mme_data_p
->
state
=
S1AP_ENB_STATE_WAITING
;
instance_p
->
s1ap_mme_nb
++
;
instance_p
->
s1ap_mme_pending_nb
++
;
}
else
if
(
mme
->
state
==
S1AP_ENB_STATE_WAITING
)
{
// s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING;
s1ap_mme_data_p
->
state
=
S1AP_ENB_STATE_DISCONNECTED
;
memcpy
(
&
(
s1ap_mme_data_p
->
mme_ip_address
),
mme_ip_address
,
sizeof
(
net_ip_address_t
)
);
s1ap_mme_data_p
->
overload_state
=
S1AP_NO_OVERLOAD
;
s1ap_mme_data_p
->
sctp_req_cnt
++
;
s1ap_mme_data_p
->
timer_id
=
S1AP_TIMERID_INIT
;
// instance_p->s1ap_mme_nb ++;
instance_p
->
s1ap_mme_pending_nb
++
;
sctp_new_association_req_p
->
ulp_cnx_id
=
mme
->
cnx_id
;
S1AP_INFO
(
"[eNB %d] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)
\n
"
,
instance_p
->
instance
,
mme
->
state
,
mme
->
cnx_id
,
instance_p
->
s1ap_mme_nb
,
instance_p
->
s1ap_mme_pending_nb
);
/*s1ap_mme_data_p->cnx_id = mme->cnx_id;
sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id;
s1ap_mme_data_p->assoc_id = -1;
s1ap_mme_data_p->s1ap_eNB_instance = instance_p;
*/
}
else
{
S1AP_WARN
(
"[eNB %d] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)
\n
"
,
instance_p
->
instance
,
mme
->
state
,
mme
->
cnx_id
,
instance_p
->
s1ap_mme_nb
,
instance_p
->
s1ap_mme_pending_nb
);
}
// } else if (mme->state == S1AP_ENB_STATE_WAITING) {
// instance_p->s1ap_mme_pending_nb ++;
// sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id;
// S1AP_INFO("[eNB %d] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n",
// instance_p->instance,
// mme->state, mme->cnx_id,
// instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb);
// /*s1ap_mme_data_p->cnx_id = mme->cnx_id;
// sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id;
//
// s1ap_mme_data_p->assoc_id = -1;
// s1ap_mme_data_p->s1ap_eNB_instance = instance_p;
// */
// } else {
// S1AP_WARN("[eNB %d] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n",
// instance_p->instance,
// mme->state, mme->cnx_id,
// instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb);
// }
itti_send_msg_to_task
(
TASK_SCTP
,
instance_p
->
instance
,
message_p
);
}
...
...
@@ -168,6 +180,7 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
uint8_t
index
;
DevAssert
(
s1ap_register_eNB
!=
NULL
);
/* Look if the provided instance already exists */
s1ap_timer_init
();
new_instance
=
s1ap_eNB_get_instance
(
instance
);
if
(
new_instance
!=
NULL
)
{
...
...
@@ -206,6 +219,15 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
new_instance
->
mnc_digit_length
[
i
]
=
s1ap_register_eNB
->
mnc_digit_length
[
i
];
}
memcpy
(
&
(
new_instance
->
enb_ip_address
),
&
(
s1ap_register_eNB
->
enb_ip_address
),
sizeof
(
net_ip_address_t
)
);
new_instance
->
s1_setuprsp_wait_timer
=
s1ap_register_eNB
->
s1_setuprsp_wait_timer
;
new_instance
->
s1_setupreq_wait_timer
=
s1ap_register_eNB
->
s1_setupreq_wait_timer
;
new_instance
->
s1_setupreq_count
=
s1ap_register_eNB
->
s1_setupreq_count
;
new_instance
->
sctp_req_timer
=
s1ap_register_eNB
->
sctp_req_timer
;
new_instance
->
sctp_req_count
=
s1ap_register_eNB
->
sctp_req_count
;
new_instance
->
sctp_in_streams
=
s1ap_register_eNB
->
sctp_in_streams
;
new_instance
->
sctp_out_streams
=
s1ap_register_eNB
->
sctp_out_streams
;
new_instance
->
num_plmn
=
s1ap_register_eNB
->
num_plmn
;
new_instance
->
default_drx
=
s1ap_register_eNB
->
default_drx
;
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
...
...
@@ -216,8 +238,14 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
s1ap_register_eNB
->
eNB_id
);
}
DevCheck
(
s1ap_register_eNB
->
nb_mme
<=
S1AP_MAX_NB_MME_IP_ADDRESS
,
S1AP_MAX_NB_MME_IP_ADDRESS
,
s1ap_register_eNB
->
nb_mme
,
0
);
// DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS,
// S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0);
if
(
s1ap_register_eNB
->
nb_mme
>
S1AP_MAX_NB_MME_IP_ADDRESS
)
{
S1AP_ERROR
(
"Invalid MME number = %d
\n
"
,
s1ap_register_eNB
->
nb_mme
);
s1ap_register_eNB
->
nb_mme
=
S1AP_MAX_NB_MME_IP_ADDRESS
;
}
new_instance
->
s1ap_mme_nb
=
s1ap_register_eNB
->
nb_mme
;
/* Trying to connect to provided list of MME ip address */
for
(
index
=
0
;
index
<
s1ap_register_eNB
->
nb_mme
;
index
++
)
{
...
...
@@ -249,28 +277,153 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
void
s1ap_eNB_handle_sctp_association_resp
(
instance_t
instance
,
sctp_new_association_resp_t
*
sctp_new_association_resp
)
{
s1ap_eNB_instance_t
*
instance_p
;
s1ap_eNB_mme_data_t
*
s1ap_mme_data_p
;
s1ap_eNB_ue_context_t
*
ue_p
=
NULL
;
MessageDef
*
message_p
=
NULL
;
uint32_t
timer_kind
=
0
;
struct
plmn_identity_s
*
plmnInfo
;
struct
served_group_id_s
*
groupInfo
;
struct
served_gummei_s
*
gummeiInfo
;
struct
mme_code_s
*
mmeCode
;
int8_t
cnt
=
0
;
unsigned
enb_s1ap_id
[
20
];
DevAssert
(
sctp_new_association_resp
!=
NULL
);
instance_p
=
s1ap_eNB_get_instance
(
instance
);
DevAssert
(
instance_p
!=
NULL
);
s1ap_mme_data_p
=
s1ap_eNB_get_MME
(
instance_p
,
-
1
,
sctp_new_association_resp
->
ulp_cnx_id
);
DevAssert
(
s1ap_mme_data_p
!=
NULL
);
memset
(
enb_s1ap_id
,
0
,
sizeof
(
enb_s1ap_id
)
);
if
(
s1ap_mme_data_p
->
timer_id
!=
S1AP_TIMERID_INIT
)
{
s1ap_timer_remove
(
s1ap_mme_data_p
->
timer_id
);
s1ap_mme_data_p
->
timer_id
=
S1AP_TIMERID_INIT
;
}
if
(
sctp_new_association_resp
->
sctp_state
!=
SCTP_STATE_ESTABLISHED
)
{
S1AP_WARN
(
"Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u
\n
"
,
sctp_new_association_resp
->
sctp_state
,
instance
,
sctp_new_association_resp
->
ulp_cnx_id
);
s1ap_handle_s1_setup_message
(
s1ap_mme_data_p
,
sctp_new_association_resp
->
sctp_state
==
SCTP_STATE_SHUTDOWN
);
return
;
if
(
sctp_new_association_resp
->
sctp_state
!=
SCTP_STATE_ESTABLISHED
)
{
RB_FOREACH
(
ue_p
,
s1ap_ue_map
,
&
instance_p
->
s1ap_ue_head
)
{
if
(
ue_p
->
mme_ref
==
s1ap_mme_data_p
)
{
enb_s1ap_id
[
cnt
]
=
ue_p
->
eNB_ue_s1ap_id
;
cnt
++
;
message_p
=
NULL
;
message_p
=
itti_alloc_new_message
(
TASK_S1AP
,
S1AP_UE_CONTEXT_RELEASE_COMMAND
);
if
(
message_p
!=
NULL
)
{
S1AP_UE_CONTEXT_RELEASE_COMMAND
(
message_p
).
eNB_ue_s1ap_id
=
ue_p
->
eNB_ue_s1ap_id
;
if
(
itti_send_msg_to_task
(
TASK_RRC_ENB
,
ue_p
->
eNB_instance
->
instance
,
message_p
)
<
0
)
{
S1AP_ERROR
(
"UE Context Release Command Transmission Failure: eNB_ue_s1ap_id=%d
\n
"
,
ue_p
->
eNB_ue_s1ap_id
);
}
}
else
{
S1AP_ERROR
(
"Invalid message_p : eNB_ue_s1ap_id=%d
\n
"
,
ue_p
->
eNB_ue_s1ap_id
);
}
}
}
for
(
;
cnt
>
0
;
)
{
cnt
--
;
s1ap_ue_context_release
(
instance
,
(
uint32_t
)
enb_s1ap_id
[
cnt
]
);
}
s1ap_mme_data_p
->
mme_name
=
0
;
s1ap_mme_data_p
->
overload_state
=
S1AP_NO_OVERLOAD
;
s1ap_mme_data_p
->
nextstream
=
0
;
s1ap_mme_data_p
->
in_streams
=
0
;
s1ap_mme_data_p
->
out_streams
=
0
;
s1ap_mme_data_p
->
assoc_id
=
-
1
;
while
(
!
STAILQ_EMPTY
(
&
s1ap_mme_data_p
->
served_gummei
))
{
gummeiInfo
=
STAILQ_FIRST
(
&
s1ap_mme_data_p
->
served_gummei
);
STAILQ_REMOVE_HEAD
(
&
s1ap_mme_data_p
->
served_gummei
,
next
);
while
(
!
STAILQ_EMPTY
(
&
gummeiInfo
->
served_plmns
))
{
plmnInfo
=
STAILQ_FIRST
(
&
gummeiInfo
->
served_plmns
);
STAILQ_REMOVE_HEAD
(
&
gummeiInfo
->
served_plmns
,
next
);
free
(
plmnInfo
);
}
while
(
!
STAILQ_EMPTY
(
&
gummeiInfo
->
served_group_ids
))
{
groupInfo
=
STAILQ_FIRST
(
&
gummeiInfo
->
served_group_ids
);
STAILQ_REMOVE_HEAD
(
&
gummeiInfo
->
served_group_ids
,
next
);
free
(
groupInfo
);
}
while
(
!
STAILQ_EMPTY
(
&
gummeiInfo
->
mme_codes
))
{
mmeCode
=
STAILQ_FIRST
(
&
gummeiInfo
->
mme_codes
);
STAILQ_REMOVE_HEAD
(
&
gummeiInfo
->
mme_codes
,
next
);
free
(
mmeCode
);
}
free
(
gummeiInfo
);
}
STAILQ_INIT
(
&
s1ap_mme_data_p
->
served_gummei
);
if
(
s1ap_mme_data_p
->
state
==
S1AP_ENB_STATE_DISCONNECTED
)
{
if
(
(
s1ap_mme_data_p
->
sctp_req_cnt
<=
instance_p
->
sctp_req_count
)
||
(
instance_p
->
sctp_req_count
==
0xffff
)
)
{
timer_kind
=
s1ap_mme_data_p
->
cnx_id
;
timer_kind
=
timer_kind
|
S1AP_MMEIND
;
timer_kind
=
timer_kind
|
SCTP_REQ_WAIT
;
if
(
s1ap_timer_setup
(
instance_p
->
sctp_req_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(SCTP retransmission wait timer) : MME=%d
\n
"
,
s1ap_mme_data_p
->
cnx_id
);
s1ap_sctp_req
(
instance_p
,
s1ap_mme_data_p
);
}
}
else
{
S1AP_ERROR
(
"Retransmission count exceeded of SCTP : MME=%d
\n
"
,
s1ap_mme_data_p
->
cnx_id
);
}
}
else
{
S1AP_ERROR
(
"SCTP disconnection reception : MME = %d
\n
"
,
s1ap_mme_data_p
->
cnx_id
);
if
(
(
s1ap_mme_data_p
->
sctp_req_cnt
<=
instance_p
->
sctp_req_count
)
||
(
instance_p
->
sctp_req_count
==
0xffff
)
)
{
s1ap_sctp_req
(
instance_p
,
s1ap_mme_data_p
);
}
else
{
S1AP_ERROR
(
"Retransmission count exceeded of SCTP : MME=%d
\n
"
,
s1ap_mme_data_p
->
cnx_id
);
}
s1ap_mme_data_p
->
state
=
S1AP_ENB_STATE_DISCONNECTED
;
}
}
// if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
// S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
// sctp_new_association_resp->sctp_state,
// instance,
// sctp_new_association_resp->ulp_cnx_id);
// s1ap_handle_s1_setup_message(s1ap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
// return;
// }
else
{
/* Update parameters */
s1ap_mme_data_p
->
assoc_id
=
sctp_new_association_resp
->
assoc_id
;
s1ap_mme_data_p
->
in_streams
=
sctp_new_association_resp
->
in_streams
;
s1ap_mme_data_p
->
out_streams
=
sctp_new_association_resp
->
out_streams
;
/* Prepare new S1 Setup Request */
s1ap_eNB_generate_s1_setup_request
(
instance_p
,
s1ap_mme_data_p
);
s1ap_mme_data_p
->
s1_setupreq_cnt
=
0
;
s1ap_mme_data_p
->
sctp_req_cnt
=
0
;
if
(
s1ap_eNB_generate_s1_setup_request
(
instance_p
,
s1ap_mme_data_p
)
==
-
1
)
{
S1AP_ERROR
(
"s1ap eNB generate s1 setup request failed
\n
"
);
return
;
}
}
static
...
...
@@ -288,9 +441,102 @@ void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) {
AssertFatal
(
result
==
EXIT_SUCCESS
,
"Failed to free memory (%d)!
\n
"
,
result
);
}
void
s1ap_eNB_timer_expired
(
instance_t
instance
,
s1ap_timer_has_expired_t
*
msg_p
)
{
uint32_t
timer_kind
=
0
;
int16_t
line_ind
=
0
;
s1ap_eNB_mme_data_t
*
mme_desc_p
=
NULL
;
uint32_t
timer_ind
=
0
;
s1ap_eNB_instance_t
*
instance_p
=
NULL
;
long
timer_id
=
S1AP_TIMERID_INIT
;
instance_p
=
s1ap_eNB_get_instance
(
instance
);
timer_kind
=
msg_p
->
timer_kind
;
line_ind
=
(
int16_t
)(
timer_kind
&
S1AP_LINEIND
);
timer_id
=
msg_p
->
timer_id
;
if
(
(
timer_kind
&
S1AP_MMEIND
)
==
S1AP_MMEIND
)
{
mme_desc_p
=
s1ap_eNB_get_MME
(
instance_p
,
-
1
,
line_ind
);
if
(
mme_desc_p
!=
NULL
)
{
if
(
timer_id
==
mme_desc_p
->
timer_id
)
{
mme_desc_p
->
timer_id
=
S1AP_TIMERID_INIT
;
timer_ind
=
timer_kind
&
S1AP_TIMERIND
;
switch
(
timer_ind
)
{
case
S1_SETRSP_WAIT
:
{
if
(
(
instance_p
->
s1_setupreq_count
>=
mme_desc_p
->
s1_setupreq_cnt
)
||
(
instance_p
->
s1_setupreq_count
==
0xffff
)
)
{
s1ap_eNB_generate_s1_setup_request
(
instance_p
,
mme_desc_p
);
}
else
{
S1AP_ERROR
(
"Retransmission count exceeded of S1 SETUP REQUEST : MME=%d
\n
"
,
line_ind
);
}
break
;
}
case
S1_SETREQ_WAIT
:
{
if
(
(
instance_p
->
s1_setupreq_count
>=
mme_desc_p
->
s1_setupreq_cnt
)
||
(
instance_p
->
s1_setupreq_count
==
0xffff
)
)
{
s1ap_eNB_generate_s1_setup_request
(
instance_p
,
mme_desc_p
);
}
else
{
S1AP_ERROR
(
"Retransmission count exceeded of S1 SETUP REQUEST : MME=%d
\n
"
,
line_ind
);
}
break
;
}
case
SCTP_REQ_WAIT
:
{
if
(
(
instance_p
->
sctp_req_count
>=
mme_desc_p
->
sctp_req_cnt
)
||
(
instance_p
->
sctp_req_count
==
0xffff
)
)
{
s1ap_sctp_req
(
instance_p
,
mme_desc_p
);
}
else
{
S1AP_ERROR
(
"Retransmission count exceeded of SCTP : MME=%d
\n
"
,
line_ind
);
}
break
;
}
default:
{
S1AP_WARN
(
"Invalid Timer indication
\n
"
);
break
;
}
}
}
else
{
S1AP_DEBUG
(
"Unmatch timer id
\n
"
);
return
;
}
}
else
{
S1AP_WARN
(
"Not applicable MME detected : connection id = %d
\n
"
,
line_ind
);
return
;
}
}
else
{
}
return
;
}
void
s1ap_eNB_init
(
void
)
{
S1AP_DEBUG
(
"Starting S1AP layer
\n
"
);
s1ap_eNB_prepare_internal_data
();
s1ap_timer_init
();
itti_mark_task_ready
(
TASK_S1AP
);
MSC_START_USE
();
}
...
...
@@ -411,6 +657,13 @@ void *s1ap_eNB_process_itti_msg(void *notUsed) {
}
break
;
case
TIMER_HAS_EXPIRED
:
{
s1ap_eNB_timer_expired
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
&
TIMER_HAS_EXPIRED
(
received_msg
));
}
break
;
default:
S1AP_ERROR
(
"Received unhandled message: %d:%s
\n
"
,
ITTI_MSG_ID
(
received_msg
),
ITTI_MSG_NAME
(
received_msg
));
...
...
@@ -451,6 +704,7 @@ static int s1ap_eNB_generate_s1_setup_request(
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
;
...
...
@@ -525,6 +779,17 @@ static int s1ap_eNB_generate_s1_setup_request(
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
;
...
...
@@ -533,3 +798,64 @@ static int s1ap_eNB_generate_s1_setup_request(
static
int
s1ap_sctp_req
(
s1ap_eNB_instance_t
*
instance_p
,
s1ap_eNB_mme_data_t
*
s1ap_mme_data_p
)
{
MessageDef
*
message_p
=
NULL
;
sctp_new_association_req_t
*
sctp_new_association_req_p
=
NULL
;
if
(
instance_p
==
NULL
)
{
S1AP_ERROR
(
"Invalid instance_p
\n
"
);
return
-
1
;
}
message_p
=
itti_alloc_new_message
(
TASK_S1AP
,
SCTP_NEW_ASSOCIATION_REQ
);
sctp_new_association_req_p
=
&
message_p
->
ittiMsg
.
sctp_new_association_req
;
sctp_new_association_req_p
->
port
=
S1AP_PORT_NUMBER
;
sctp_new_association_req_p
->
ppid
=
S1AP_SCTP_PPID
;
sctp_new_association_req_p
->
in_streams
=
instance_p
->
sctp_in_streams
;
sctp_new_association_req_p
->
out_streams
=
instance_p
->
sctp_out_streams
;
sctp_new_association_req_p
->
ulp_cnx_id
=
s1ap_mme_data_p
->
cnx_id
;
if
(
s1ap_mme_data_p
->
mme_ip_address
.
ipv4
!=
0
)
{
memcpy
(
&
sctp_new_association_req_p
->
remote_address
,
&
s1ap_mme_data_p
->
mme_ip_address
,
sizeof
(
net_ip_address_t
));
if
(
instance_p
->
enb_ip_address
.
ipv4
!=
0
)
{
memcpy
(
&
sctp_new_association_req_p
->
local_address
,
&
instance_p
->
enb_ip_address
,
sizeof
(
net_ip_address_t
));
}
else
{
S1AP_ERROR
(
"Invalid IP Address Format V4(MME):V6
\n
"
);
return
-
1
;
}
}
else
{
memcpy
(
&
sctp_new_association_req_p
->
remote_address
,
&
s1ap_mme_data_p
->
mme_ip_address
,
sizeof
(
net_ip_address_t
));
if
(
instance_p
->
enb_ip_address
.
ipv6
!=
0
)
{
memcpy
(
&
sctp_new_association_req_p
->
local_address
,
&
instance_p
->
enb_ip_address
,
sizeof
(
net_ip_address_t
));
}
else
{
S1AP_ERROR
(
"Invalid IP Address Format V6(MME):V4
\n
"
);
return
-
1
;
}
}
itti_send_msg_to_task
(
TASK_SCTP
,
instance_p
->
instance
,
message_p
);
s1ap_mme_data_p
->
sctp_req_cnt
++
;
return
0
;
}
openair3/S1AP/s1ap_eNB_defs.h
View file @
46407ca4
...
...
@@ -166,6 +166,10 @@ typedef struct s1ap_eNB_mme_data_s {
struct
s1ap_eNB_instance_s
*
s1ap_eNB_instance
;
uint32_t
nb_calls
;
net_ip_address_t
mme_ip_address
;
long
timer_id
;
uint16_t
s1_setupreq_cnt
;
uint16_t
sctp_req_cnt
;
}
s1ap_eNB_mme_data_t
;
typedef
struct
s1ap_eNB_instance_s
{
...
...
@@ -218,6 +222,14 @@ typedef struct s1ap_eNB_instance_s {
/* Default Paging DRX of the eNB as defined in TS 36.304 */
paging_drx_t
default_drx
;
net_ip_address_t
enb_ip_address
;
uint16_t
s1_setuprsp_wait_timer
;
uint16_t
s1_setupreq_wait_timer
;
uint16_t
s1_setupreq_count
;
uint16_t
sctp_req_timer
;
uint16_t
sctp_req_count
;
uint16_t
sctp_in_streams
;
uint16_t
sctp_out_streams
;
}
s1ap_eNB_instance_t
;
typedef
struct
{
...
...
openair3/S1AP/s1ap_eNB_handlers.c
View file @
46407ca4
...
...
@@ -49,6 +49,7 @@
#include "assertions.h"
#include "conversions.h"
#include "msc.h"
#include "s1ap_eNB_timer.h"
static
int
s1ap_eNB_handle_s1_setup_response
(
uint32_t
assoc_id
,
...
...
@@ -109,6 +110,10 @@ 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
);
/* Handlers matrix. Only eNB related procedure present here */
s1ap_message_decoded_callback
messages_callback
[][
3
]
=
{
{
0
,
0
,
0
},
/* HandoverPreparation */
...
...
@@ -260,6 +265,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 +279,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 +287,11 @@ 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 +299,65 @@ 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 +385,29 @@ 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.
*/
...
...
@@ -370,11 +461,11 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
}
/* 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
;
//
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
);
...
...
@@ -392,7 +483,7 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
*/
mme_desc_p
->
state
=
S1AP_ENB_STATE_CONNECTED
;
mme_desc_p
->
s1ap_eNB_instance
->
s1ap_mme_associated_nb
++
;
s1ap_handle_s1_setup_message
(
mme_desc_p
,
0
);
//
s1ap_handle_s1_setup_message(mme_desc_p, 0);
return
0
;
}
...
...
@@ -725,6 +816,10 @@ 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 = %d
\n
"
,
*
ie
->
value
.
choice
.
CriticalityDiagnostics
.
procedureCode
);
}
// TODO continue
}
...
...
@@ -807,6 +902,33 @@ 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
;
}
/* id-UESecurityCapabilities */
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_InitialContextSetupRequestIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_UESecurityCapabilities
,
true
);
if
(
ie
!=
NULL
)
{
/* checked by macro but cppcheck doesn't see it */
S1AP_INITIAL_CONTEXT_SETUP_REQ
(
message_p
).
security_capabilities
.
encryption_algorithms
=
BIT_STRING_to_uint16
(
&
ie
->
value
.
choice
.
UESecurityCapabilities
.
encryptionAlgorithms
);
S1AP_INITIAL_CONTEXT_SETUP_REQ
(
message_p
).
security_capabilities
.
integrity_algorithms
=
BIT_STRING_to_uint16
(
&
ie
->
value
.
choice
.
UESecurityCapabilities
.
integrityProtectionAlgorithms
);
/* id-SecurityKey : Copy the security key */
}
else
{
/* ie != NULL */
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_SecurityKey
,
true
);
if
(
ie
!=
NULL
)
{
/* checked by macro but cppcheck doesn't see it */
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
;
}
...
...
@@ -852,34 +974,11 @@ 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
;
}
/* id-UESecurityCapabilities */
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_InitialContextSetupRequestIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_UESecurityCapabilities
,
true
);
if
(
ie
!=
NULL
)
{
/* checked by macro but cppcheck doesn't see it */
S1AP_INITIAL_CONTEXT_SETUP_REQ
(
message_p
).
security_capabilities
.
encryption_algorithms
=
BIT_STRING_to_uint16
(
&
ie
->
value
.
choice
.
UESecurityCapabilities
.
encryptionAlgorithms
);
S1AP_INITIAL_CONTEXT_SETUP_REQ
(
message_p
).
security_capabilities
.
integrity_algorithms
=
BIT_STRING_to_uint16
(
&
ie
->
value
.
choice
.
UESecurityCapabilities
.
integrityProtectionAlgorithms
);
/* id-SecurityKey : Copy the security key */
}
else
{
/* ie != NULL */
return
-
1
;
}
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_InitialContextSetupRequestIEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_SecurityKey
,
true
);
if
(
ie
!=
NULL
)
{
/* checked by macro but cppcheck doesn't see it */
memcpy
(
&
S1AP_INITIAL_CONTEXT_SETUP_REQ
(
message_p
).
security_key
,
ie
->
value
.
choice
.
SecurityKey
.
buf
,
ie
->
value
.
choice
.
SecurityKey
.
size
);
itti_send_msg_to_task
(
TASK_RRC_ENB
,
ue_desc_p
->
eNB_instance
->
instance
,
message_p
);
}
else
{
/* ie != NULL */
return
-
1
;
}
return
0
;
}
...
...
@@ -904,6 +1003,14 @@ 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
);
...
...
@@ -951,9 +1058,29 @@ 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.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
,
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:
...
...
@@ -961,12 +1088,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
...
...
@@ -985,7 +1110,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
;
}
...
...
@@ -1012,7 +1137,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
;
...
...
@@ -1085,6 +1210,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
;
}
...
...
@@ -1132,6 +1258,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
;
}
...
...
@@ -1159,6 +1286,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
{
...
...
@@ -1169,14 +1297,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
;
}
...
...
@@ -1209,6 +1340,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
;
}
...
...
@@ -1236,6 +1368,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
;
}
...
...
@@ -1330,6 +1463,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
;
}
...
...
@@ -1382,6 +1516,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
;
}
...
...
@@ -1455,22 +1590,6 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id,
message_p
=
itti_alloc_new_message
(
TASK_S1AP
,
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
);
...
...
@@ -1485,9 +1604,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
;
}
...
...
@@ -1528,6 +1663,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
;
}
...
...
@@ -1550,6 +1686,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
;
}
...
...
@@ -1567,6 +1704,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
;
}
...
...
@@ -1580,14 +1718,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
;
...
...
@@ -1731,3 +1865,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
;
}
openair3/S1AP/s1ap_eNB_management_procedures.c
View file @
46407ca4
...
...
@@ -95,12 +95,15 @@ struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(
{
struct
s1ap_eNB_mme_data_s
temp
;
struct
s1ap_eNB_mme_data_s
*
found
;
struct
s1ap_eNB_mme_data_s
*
mme_p
;
memset
(
&
temp
,
0
,
sizeof
(
struct
s1ap_eNB_mme_data_s
));
temp
.
assoc_id
=
assoc_id
;
temp
.
cnx_id
=
cnx_id
;
if
(
cnx_id
!=
0
)
{
if
(
instance_p
==
NULL
)
{
STAILQ_FOREACH
(
instance_p
,
&
s1ap_eNB_internal_data
.
s1ap_eNB_instances_head
,
s1ap_eNB_entries
)
{
...
...
@@ -113,6 +116,34 @@ struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(
}
else
{
return
RB_FIND
(
s1ap_mme_map
,
&
instance_p
->
s1ap_mme_head
,
&
temp
);
}
}
else
{
if
(
instance_p
==
NULL
)
{
STAILQ_FOREACH
(
instance_p
,
&
s1ap_eNB_internal_data
.
s1ap_eNB_instances_head
,
s1ap_eNB_entries
)
{
RB_FOREACH
(
mme_p
,
s1ap_mme_map
,
&
instance_p
->
s1ap_mme_head
)
{
if
(
mme_p
->
assoc_id
==
assoc_id
)
{
return
mme_p
;
}
}
}
}
else
{
RB_FOREACH
(
mme_p
,
s1ap_mme_map
,
&
instance_p
->
s1ap_mme_head
)
{
if
(
mme_p
->
assoc_id
==
assoc_id
)
{
return
mme_p
;
}
}
}
}
return
NULL
;
}
...
...
openair3/S1AP/s1ap_eNB_nas_procedures.c
View file @
46407ca4
...
...
@@ -359,10 +359,18 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
container
=
&
pdu
->
choice
.
initiatingMessage
.
value
.
choice
.
DownlinkNASTransport
;
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_DownlinkNASTransport_IEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID
,
true
);
if
(
ie
==
NULL
)
{
return
-
1
;
}
mme_ue_s1ap_id
=
ie
->
value
.
choice
.
MME_UE_S1AP_ID
;
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_DownlinkNASTransport_IEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID
,
true
);
if
(
ie
==
NULL
)
{
return
-
1
;
}
enb_ue_s1ap_id
=
ie
->
value
.
choice
.
ENB_UE_S1AP_ID
;
if
((
ue_desc_p
=
s1ap_eNB_get_ue_context
(
s1ap_eNB_instance
,
...
...
@@ -417,6 +425,10 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
S1AP_FIND_PROTOCOLIE_BY_ID
(
S1AP_DownlinkNASTransport_IEs_t
,
ie
,
container
,
S1AP_ProtocolIE_ID_id_NAS_PDU
,
true
);
if
(
ie
==
NULL
)
{
return
-
1
;
}
/* Forward the NAS PDU to RRC */
s1ap_eNB_itti_send_nas_downlink_ind
(
s1ap_eNB_instance
->
instance
,
ue_desc_p
->
ue_initial_id
,
...
...
openair3/S1AP/s1ap_eNB_overload.c
View file @
46407ca4
...
...
@@ -62,6 +62,10 @@ int s1ap_eNB_handle_overload_start(uint32_t assoc_id,
S1AP_OverloadResponse_PR_overloadAction
,
S1AP_OverloadResponse_PR_overloadAction
,
0
,
0
);
}
else
{
return
-
1
;
}
/* Non UE-associated signalling -> stream 0 */
if
(
stream
!=
0
)
{
S1AP_ERROR
(
"[SCTP %d] Received s1 overload start on stream != 0 (%d)
\n
"
,
...
...
openair3/S1AP/s1ap_eNB_timer.c
0 → 100644
View file @
46407ca4
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include "assertions.h"
#include "intertask_interface.h"
#include "s1ap_eNB_timer.h"
#include "common/utils/LOG/log.h"
#include "queue.h"
#include "s1ap_common.h"
struct
s1ap_timer_elm_s
{
task_id_t
task_id
;
///< Task ID which has requested the timer
int32_t
instance
;
///< Instance of the task which has requested the timer
uint32_t
timer_kind
;
///< Instance of the task which has requested the timer
timer_t
timer
;
///< Unique timer id
timer_type_t
type
;
///< Timer type
void
*
timer_arg
;
///< Optional argument that will be passed when timer expires
STAILQ_ENTRY
(
s1ap_timer_elm_s
)
entries
;
///< Pointer to next element
};
typedef
struct
timer_desc_s
{
STAILQ_HEAD
(
timer_list_head
,
s1ap_timer_elm_s
)
timer_queue
;
pthread_mutex_t
timer_list_mutex
;
struct
timespec
timeout
;
}
timer_desc_t
;
static
timer_desc_t
timer_desc
;
#define TIMER_SEARCH(vAR, tIMERfIELD, tIMERvALUE, tIMERqUEUE) \
do { \
STAILQ_FOREACH(vAR, tIMERqUEUE, entries) { \
if (((vAR)->tIMERfIELD == tIMERvALUE)) \
break; \
} \
} while(0)
int
s1ap_timer_timeout
(
sigval_t
info
)
{
struct
s1ap_timer_elm_s
*
timer_p
;
MessageDef
*
message_p
;
s1ap_timer_has_expired_t
*
timer_expired_p
;
task_id_t
task_id
;
int32_t
instance
;
uint32_t
timer_kind
;
timer_kind
=
info
.
sival_int
;
if
(
pthread_mutex_lock
(
&
timer_desc
.
timer_list_mutex
)
!=
0
)
{
S1AP_ERROR
(
"Failed to mutex lock timeout=%x
\n
"
,
timer_kind
);
return
-
1
;
}
TIMER_SEARCH
(
timer_p
,
timer_kind
,
timer_kind
,
&
timer_desc
.
timer_queue
);
if
(
pthread_mutex_unlock
(
&
timer_desc
.
timer_list_mutex
)
!=
0
)
{
S1AP_ERROR
(
"Failed to mutex unlock timeout=%x
\n
"
,
timer_kind
);
}
if
(
timer_p
==
NULL
)
{
S1AP_ERROR
(
"Didn't find timer 0x%lx in list
\n
"
,
timer_kind
);
return
-
1
;
}
S1AP_DEBUG
(
"Timer kind 0x%x has expired
\n
"
,
timer_kind
);
task_id
=
timer_p
->
task_id
;
instance
=
timer_p
->
instance
;
message_p
=
itti_alloc_new_message
(
TASK_UNKNOWN
,
TIMER_HAS_EXPIRED
);
timer_expired_p
=
&
message_p
->
ittiMsg
.
timer_has_expired
;
timer_expired_p
->
timer_id
=
(
long
)
timer_p
->
timer
;
timer_expired_p
->
timer_kind
=
timer_p
->
timer_kind
;
timer_expired_p
->
arg
=
timer_p
->
timer_arg
;
/* Timer is a one shot timer, remove it */
if
(
timer_p
->
type
==
S1AP_TIMER_ONE_SHOT
)
{
if
(
s1ap_timer_remove
((
long
)
timer_p
->
timer
)
!=
0
)
{
S1AP_DEBUG
(
"Failed to delete timer 0x%lx
\n
"
,
(
long
)
timer_p
->
timer
);
}
}
/* Notify task of timer expiry */
if
(
itti_send_msg_to_task
(
task_id
,
instance
,
message_p
)
<
0
)
{
S1AP_ERROR
(
"Failed to send msg TIMER_HAS_EXPIRED to task %u
\n
"
,
task_id
);
free
(
message_p
);
return
-
1
;
}
return
0
;
}
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
)
{
struct
sigevent
evp
;
struct
itimerspec
its
;
struct
s1ap_timer_elm_s
*
timer_p
;
timer_t
timer
;
if
(
timer_id
==
NULL
)
{
S1AP_ERROR
(
"Invalid timer_id
\n
"
);
return
-
1
;
}
if
(
type
>=
S1AP_TIMER_TYPE_MAX
)
{
S1AP_ERROR
(
"Invalid timer type (%d/%d)!
\n
"
,
type
,
TIMER_TYPE_MAX
);
return
-
1
;
}
if
(
*
timer_id
!=
S1AP_TIMERID_INIT
)
{
if
(
s1ap_timer_remove
(
*
timer_id
)
!=
0
)
{
S1AP_ERROR
(
"Failed to delete timer when the timer start 0x%lx
\n
"
,
*
timer_id
);
}
}
/* Allocate new timer list element */
timer_p
=
malloc
(
sizeof
(
struct
s1ap_timer_elm_s
));
if
(
timer_p
==
NULL
)
{
S1AP_ERROR
(
"Failed to create new timer element
\n
"
);
return
-
1
;
}
memset
(
&
timer
,
0
,
sizeof
(
timer_t
));
memset
(
&
evp
,
0
,
sizeof
(
evp
));
timer_p
->
task_id
=
task_id
;
timer_p
->
instance
=
instance
;
timer_p
->
timer_kind
=
timer_kind
;
timer_p
->
type
=
type
;
timer_p
->
timer_arg
=
timer_arg
;
evp
.
sigev_notify
=
(
int
)
SIGEV_THREAD
;
evp
.
sigev_notify_function
=
(
void
*
)
s1ap_timer_timeout
;
evp
.
sigev_signo
=
SIGRTMIN
;
evp
.
sigev_notify_attributes
=
NULL
;
evp
.
sigev_value
.
sival_int
=
timer_kind
;
/* At the timer creation, the timer structure will be filled in with timer_id,
* which is unique for this process. This id is allocated by kernel and the
* value might be used to distinguish timers.
*/
if
(
timer_create
(
CLOCK_REALTIME
,
&
evp
,
&
timer
)
<
0
)
{
S1AP_ERROR
(
"Failed to create timer: (%s:%d)
\n
"
,
strerror
(
errno
),
errno
);
free
(
timer_p
);
return
-
1
;
}
/* Fill in the first expiration value. */
its
.
it_value
.
tv_sec
=
interval_sec
;
its
.
it_value
.
tv_nsec
=
interval_us
*
1000
;
if
(
type
==
S1AP_TIMER_PERIODIC
)
{
/* Asked for periodic timer. We set the interval time */
its
.
it_interval
.
tv_sec
=
interval_sec
;
its
.
it_interval
.
tv_nsec
=
interval_us
*
1000
;
}
else
{
/* Asked for one-shot timer. Do not set the interval field */
its
.
it_interval
.
tv_sec
=
0
;
its
.
it_interval
.
tv_nsec
=
0
;
}
if
(
timer_settime
(
timer
,
0
,
&
its
,
NULL
)
)
{
S1AP_ERROR
(
"Failed to Settimer: (%s:%d)
\n
"
,
strerror
(
errno
),
errno
);
free
(
timer_p
);
return
-
1
;
}
/* Simply set the timer_id argument. so it can be used by caller */
*
timer_id
=
(
long
)
timer
;
timer_p
->
timer
=
timer
;
/* Lock the queue and insert the timer at the tail */
if
(
pthread_mutex_lock
(
&
timer_desc
.
timer_list_mutex
)
!=
0
)
{
S1AP_ERROR
(
"Failed to mutex lock
\n
"
);
if
(
timer_delete
(
timer_p
->
timer
)
<
0
)
{
S1AP_ERROR
(
"Failed to delete timer 0x%lx
\n
"
,
(
long
)
timer_p
->
timer
);
}
free
(
timer_p
);
timer_p
=
NULL
;
return
-
1
;
}
STAILQ_INSERT_TAIL
(
&
timer_desc
.
timer_queue
,
timer_p
,
entries
);
if
(
pthread_mutex_unlock
(
&
timer_desc
.
timer_list_mutex
)
!=
0
)
{
S1AP_ERROR
(
"Failed to mutex unlock
\n
"
);
}
return
0
;
}
int
s1ap_timer_remove
(
long
timer_id
)
{
int
rc
=
0
;
struct
s1ap_timer_elm_s
*
timer_p
;
if
(
pthread_mutex_lock
(
&
timer_desc
.
timer_list_mutex
)
!=
0
)
{
S1AP_ERROR
(
"Failed to mutex lock
\n
"
);
if
(
timer_delete
(
timer_id
)
<
0
)
{
S1AP_ERROR
(
"Failed to delete timer 0x%lx
\n
"
,
(
long
)
timer_id
);
}
return
-
1
;
}
TIMER_SEARCH
(
timer_p
,
timer
,
((
timer_t
)
timer_id
),
&
timer_desc
.
timer_queue
);
/* We didn't find the timer in list */
if
(
timer_p
==
NULL
)
{
S1AP_ERROR
(
"Didn't find timer 0x%lx in list
\n
"
,
timer_id
);
if
(
pthread_mutex_unlock
(
&
timer_desc
.
timer_list_mutex
)
!=
0
)
{
S1AP_ERROR
(
"Failed to mutex unlock
\n
"
);
}
return
-
1
;
}
timer_delete
(
timer_p
->
timer
);
STAILQ_REMOVE
(
&
timer_desc
.
timer_queue
,
timer_p
,
s1ap_timer_elm_s
,
entries
);
if
(
pthread_mutex_unlock
(
&
timer_desc
.
timer_list_mutex
)
!=
0
)
{
S1AP_ERROR
(
"Failed to mutex unlock
\n
"
);
}
free
(
timer_p
);
timer_p
=
NULL
;
return
rc
;
}
int
s1ap_timer_init
(
void
)
{
memset
(
&
timer_desc
,
0
,
sizeof
(
timer_desc_t
));
STAILQ_INIT
(
&
timer_desc
.
timer_queue
);
pthread_mutex_init
(
&
timer_desc
.
timer_list_mutex
,
NULL
);
return
0
;
}
openair3/S1AP/s1ap_eNB_timer.h
0 → 100644
View file @
46407ca4
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef TIMER_H_
#define TIMER_H_
#include <signal.h>
#define SIGTIMER SIGRTMIN
typedef
enum
s1ap_timer_type_s
{
S1AP_TIMER_PERIODIC
,
S1AP_TIMER_ONE_SHOT
,
S1AP_TIMER_TYPE_MAX
,
}
s1ap_timer_type_t
;
typedef
struct
{
void
*
arg
;
long
timer_id
;
int32_t
timer_kind
;
}
s1ap_timer_has_expired_t
;
int
s1ap_timer_timeout
(
sigval_t
info
);
/** \brief Request a new timer
* \param interval_sec timer interval in seconds
* \param interval_us timer interval in micro seconds
* \param task_id task id of the task requesting the timer
* \param instance instance of the task requesting the timer
* \param type timer type
* \param timer_id unique timer identifier
* @returns -1 on failure, 0 otherwise
**/
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
);
/** \brief Remove the timer from list
* \param timer_id unique timer id
* @returns -1 on failure, 0 otherwise
**/
int
s1ap_timer_remove
(
long
timer_id
);
/** \brief Initialize timer task and its API
* \param mme_config MME common configuration
* @returns -1 on failure, 0 otherwise
**/
int
s1ap_timer_init
(
void
);
#define S1AP_MMEIND 0x80000000
#define S1AP_UEIND 0x00000000
#define S1_SETRSP_WAIT 0x00010000
#define S1_SETREQ_WAIT 0x00020000
#define SCTP_REQ_WAIT 0x00030000
#define S1AP_LINEIND 0x0000ffff
#define S1AP_TIMERIND 0x00ff0000
#define S1AP_TIMERID_INIT 0xffffffffffffffff
#endif
openair3/S1AP/s1ap_eNB_trace.c
View file @
46407ca4
...
...
@@ -121,6 +121,10 @@ int s1ap_eNB_handle_trace_start(uint32_t assoc_id,
if
(
ie
!=
NULL
)
{
ue_desc_p
=
s1ap_eNB_get_ue_context
(
mme_ref_p
->
s1ap_eNB_instance
,
ie
->
value
.
choice
.
ENB_UE_S1AP_ID
);
}
else
{
return
-
1
;
}
if
(
ue_desc_p
==
NULL
)
{
/* Could not find context associated with this eNB_ue_s1ap_id -> generate
...
...
openair3/SCTP/sctp_default_values.h
View file @
46407ca4
...
...
@@ -24,8 +24,8 @@
#define SCTP_OUT_STREAMS (16)
#define SCTP_IN_STREAMS (16)
#define SCTP_MAX_ATTEMPTS (
2
)
#define SCTP_TIMEOUT (
5
)
#define SCTP_MAX_ATTEMPTS (
8
)
#define SCTP_TIMEOUT (
60000
)
#define SCTP_RECV_BUFFER_SIZE (8192)
#endif
/* SCTP_DEFAULT_VALUES_H_ */
openair3/SCTP/sctp_eNB_task.c
View file @
46407ca4
...
...
@@ -943,10 +943,12 @@ sctp_eNB_read_from_socket(
&
sinfo
,
&
flags
);
if
(
n
<
0
)
{
if
(
errno
==
ENOTCONN
)
{
if
(
(
errno
==
ENOTCONN
)
||
(
errno
==
ECONNRESET
)
||
(
errno
==
ETIMEDOUT
)
||
(
errno
==
ECONNREFUSED
)
)
{
itti_unsubscribe_event_fd
(
TASK_SCTP
,
sctp_cnx
->
sd
);
SCTP_DEBUG
(
"Received not connected for sd %d
\n
"
,
sctp_cnx
->
sd
);
SCTP_ERROR
(
"sctp_recvmsg (fd %d, len %d ): %s:%d
\n
"
,
sctp_cnx
->
sd
,
n
,
strerror
(
errno
),
errno
);
sctp_itti_send_association_resp
(
sctp_cnx
->
task_id
,
sctp_cnx
->
instance
,
-
1
,
...
...
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