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
zzha zzha
OpenXG-RAN
Commits
afb2fd40
Commit
afb2fd40
authored
Sep 07, 2018
by
Cedric Roux
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/x2' into develop_integration_2018_w36
parents
62a1a3da
938e0242
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1461 additions
and
103 deletions
+1461
-103
cmake_targets/CMakeLists.txt
cmake_targets/CMakeLists.txt
+10
-10
common/utils/LOG/log.c
common/utils/LOG/log.c
+1
-0
openair2/COMMON/sctp_messages_def.h
openair2/COMMON/sctp_messages_def.h
+11
-8
openair2/COMMON/sctp_messages_types.h
openair2/COMMON/sctp_messages_types.h
+36
-7
openair2/COMMON/x2ap_messages_def.h
openair2/COMMON/x2ap_messages_def.h
+9
-9
openair2/ENB_APP/enb_app.c
openair2/ENB_APP/enb_app.c
+63
-12
openair2/X2AP/x2ap_common.h
openair2/X2AP/x2ap_common.h
+2
-0
openair2/X2AP/x2ap_eNB.c
openair2/X2AP/x2ap_eNB.c
+451
-0
openair2/X2AP/x2ap_eNB.h
openair2/X2AP/x2ap_eNB.h
+5
-3
openair2/X2AP/x2ap_eNB_defs.h
openair2/X2AP/x2ap_eNB_defs.h
+184
-0
openair2/X2AP/x2ap_eNB_handler.c
openair2/X2AP/x2ap_eNB_handler.c
+79
-0
openair2/X2AP/x2ap_eNB_handler.h
openair2/X2AP/x2ap_eNB_handler.h
+33
-0
openair2/X2AP/x2ap_eNB_management_procedures.c
openair2/X2AP/x2ap_eNB_management_procedures.c
+236
-0
openair2/X2AP/x2ap_eNB_management_procedures.h
openair2/X2AP/x2ap_eNB_management_procedures.h
+14
-39
openair3/SCTP/sctp_common.c
openair3/SCTP/sctp_common.c
+6
-0
openair3/SCTP/sctp_eNB_itti_messaging.c
openair3/SCTP/sctp_eNB_itti_messaging.c
+14
-0
openair3/SCTP/sctp_eNB_itti_messaging.h
openair3/SCTP/sctp_eNB_itti_messaging.h
+2
-0
openair3/SCTP/sctp_eNB_task.c
openair3/SCTP/sctp_eNB_task.c
+299
-15
targets/COMMON/create_tasks.c
targets/COMMON/create_tasks.c
+6
-0
No files found.
cmake_targets/CMakeLists.txt
View file @
afb2fd40
...
...
@@ -472,15 +472,15 @@ add_library(X2AP_LIB
include_directories
(
"
${
X2AP_C_DIR
}
"
)
include_directories
(
"
${
X2AP_DIR
}
"
)
#
add_library(X2AP_ENB
#
${X2AP_DIR}/x2ap_eNB.c
add_library
(
X2AP_ENB
${
X2AP_DIR
}
/x2ap_eNB.c
# ${X2AP_DIR}/x2ap_eNB_decoder.c
# ${X2AP_DIR}/x2ap_eNB_encoder.c
#
${X2AP_DIR}/x2ap_eNB_handler.c
${
X2AP_DIR
}
/x2ap_eNB_handler.c
# ${X2AP_DIR}/x2ap_eNB_itti_messaging.c
#
${X2AP_DIR}/x2ap_eNB_management_procedures.c
${
X2AP_DIR
}
/x2ap_eNB_management_procedures.c
# ${X2AP_DIR}/x2ap_eNB_generate_messages.c
#
)
)
# Hardware dependant options
###################################
...
...
@@ -1947,7 +1947,7 @@ add_executable(lte-softmodem
target_link_libraries
(
lte-softmodem
-Wl,--start-group
RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2
RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB
X2AP_ENB
GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2
${
MSC_LIB
}
${
RAL_LIB
}
${
NAS_UE_LIB
}
${
ITTI_LIB
}
${
FLPT_MSG_LIB
}
${
ASYNC_IF_LIB
}
${
FLEXRAN_AGENT_LIB
}
LFDS7
NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
-Wl,--end-group z dl
)
...
...
@@ -2023,7 +2023,7 @@ add_executable(lte-uesoftmodem
target_link_libraries
(
lte-uesoftmodem
-Wl,--start-group
RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE SIMU
RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB
X2AP_ENB
GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE SIMU
${
MSC_LIB
}
${
RAL_LIB
}
${
NAS_UE_LIB
}
${
ITTI_LIB
}
${
FLPT_MSG_LIB
}
${
ASYNC_IF_LIB
}
LFDS7
${
ATLAS_LIBRARIES
}
NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
-Wl,--end-group z dl
)
...
...
@@ -2140,7 +2140,7 @@ add_executable(test_epc_generate_scenario
${
OPENAIR3_DIR
}
/S1AP/s1ap_eNB_defs.h
)
target_link_libraries
(
test_epc_generate_scenario
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS
${
ITTI_LIB
}
L2 -Wl,--end-group pthread m rt crypt sctp
${
LIBXML2_LIBRARIES
}
${
LIBXSLT_LIBRARIES
}
${
CRYPTO_LIBRARIES
}
${
OPENSSL_LIBRARIES
}
${
NETTLE_LIBRARIES
}
${
CONFIG_LIBRARIES
}
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB
X2AP_ENB
GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS
${
ITTI_LIB
}
L2 -Wl,--end-group pthread m rt crypt sctp
${
LIBXML2_LIBRARIES
}
${
LIBXSLT_LIBRARIES
}
${
CRYPTO_LIBRARIES
}
${
OPENSSL_LIBRARIES
}
${
NETTLE_LIBRARIES
}
${
CONFIG_LIBRARIES
}
)
add_executable
(
test_epc_play_scenario
...
...
@@ -2160,7 +2160,7 @@ add_executable(test_epc_play_scenario
)
target_include_directories
(
test_epc_play_scenario PUBLIC /usr/local/share/asn1c
)
target_link_libraries
(
test_epc_play_scenario
-Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY_COMMON PHY PHY_UE LFDS
${
ITTI_LIB
}
${
MSC_LIB
}
-Wl,--end-group pthread m rt crypt sctp
${
LIBXML2_LIBRARIES
}
${
LIBXSLT_LIBRARIES
}
${
CRYPTO_LIBRARIES
}
${
OPENSSL_LIBRARIES
}
${
NETTLE_LIBRARIES
}
${
CONFIG_LIBRARIES
}
-Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB
X2AP_ENB
GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY_COMMON PHY PHY_UE LFDS
${
ITTI_LIB
}
${
MSC_LIB
}
-Wl,--end-group pthread m rt crypt sctp
${
LIBXML2_LIBRARIES
}
${
LIBXSLT_LIBRARIES
}
${
CRYPTO_LIBRARIES
}
${
OPENSSL_LIBRARIES
}
${
NETTLE_LIBRARIES
}
${
CONFIG_LIBRARIES
}
)
...
...
@@ -2196,7 +2196,7 @@ if (${T_TRACER})
dlsim_tm4 dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim
pdcchsim pucchsim prachsim syncsim ulsim
#all "add_library" definitions
ITTI RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB
ITTI RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB
X2AP_ENB
oai_exmimodevif oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif
oai_eth_transpro
FLPT_MSG ASYNC_IF FLEXRAN_AGENT HASHTABLE MSC UTIL OMG_SUMO SECU_OSA
...
...
common/utils/LOG/log.c
View file @
afb2fd40
...
...
@@ -410,6 +410,7 @@ int logInit (void)
register_log_component
(
"S1AP"
,
""
,
S1AP
);
register_log_component
(
"X2AP"
,
""
,
X2AP
);
register_log_component
(
"SCTP"
,
""
,
SCTP
);
...
...
openair2/COMMON/sctp_messages_def.h
View file @
afb2fd40
...
...
@@ -20,10 +20,13 @@
*/
MESSAGE_DEF
(
SCTP_NEW_ASSOCIATION_REQ
,
MESSAGE_PRIORITY_MED
,
sctp_new_association_req_t
,
sctp_new_association_req
)
MESSAGE_DEF
(
SCTP_NEW_ASSOCIATION_REQ_MULTI
,
MESSAGE_PRIORITY_MED
,
sctp_new_association_req_multi_t
,
sctp_new_association_req_multi
)
MESSAGE_DEF
(
SCTP_NEW_ASSOCIATION_RESP
,
MESSAGE_PRIORITY_MED
,
sctp_new_association_resp_t
,
sctp_new_association_resp
)
MESSAGE_DEF
(
SCTP_NEW_ASSOCIATION_IND
,
MESSAGE_PRIORITY_MED
,
sctp_new_association_ind_t
,
sctp_new_association_ind
)
MESSAGE_DEF
(
SCTP_REGISTER_UPPER_LAYER
,
MESSAGE_PRIORITY_MED
,
sctp_listener_register_upper_layer_t
,
sctp_listener_register_upper_layer
)
MESSAGE_DEF
(
SCTP_REGISTER_UPPER_LAYER
,
MESSAGE_PRIORITY_MED
,
sctp_listener_register_upper_layer_t
,
sctp_listener_register_upper_layer
)
MESSAGE_DEF
(
SCTP_DATA_REQ
,
MESSAGE_PRIORITY_MED
,
sctp_data_req_t
,
sctp_data_req
)
MESSAGE_DEF
(
SCTP_DATA_IND
,
MESSAGE_PRIORITY_MED
,
sctp_data_ind_t
,
sctp_data_ind
)
MESSAGE_DEF
(
SCTP_INIT_MSG
,
MESSAGE_PRIORITY_MED
,
sctp_init_t
,
sctp_init
)
MESSAGE_DEF
(
SCTP_INIT_MSG_MULTI_REQ
,
MESSAGE_PRIORITY_MED
,
sctp_init_t
,
sctp_init_multi
)
MESSAGE_DEF
(
SCTP_INIT_MSG_MULTI_CNF
,
MESSAGE_PRIORITY_MED
,
sctp_init_msg_multi_cnf_t
,
sctp_init_msg_multi_cnf
)
MESSAGE_DEF
(
SCTP_CLOSE_ASSOCIATION
,
MESSAGE_PRIORITY_MAX
,
sctp_close_association_t
,
sctp_close_association
)
openair2/COMMON/sctp_messages_types.h
View file @
afb2fd40
...
...
@@ -23,11 +23,14 @@
#define SCTP_MESSAGES_TYPES_H_
#define SCTP_NEW_ASSOCIATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_req
#define SCTP_NEW_ASSOCIATION_RESP(mSGpTR)(mSGpTR)->ittiMsg.sctp_new_association_resp
#define SCTP_NEW_ASSOCIATION_REQ_MULTI(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_req_multi
#define SCTP_NEW_ASSOCIATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_resp
#define SCTP_NEW_ASSOCIATION_IND(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_ind
#define SCTP_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.sctp_data_ind
#define SCTP_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_data_req
#define SCTP_INIT_MSG(mSGpTR) (mSGpTR)->ittiMsg.sctp_init
#define SCTP_INIT_MSG_MULTI_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_init_multi
#define SCTP_INIT_MSG_MULTI_CNF(mSGpTR) (mSGpTR)->ittiMsg.sctp_init_msg_multi_cnf
#define SCTP_CLOSE_ASSOCIATION(mSGpTR) (mSGpTR)->ittiMsg.sctp_close_association
enum
sctp_state_e
{
...
...
@@ -56,6 +59,32 @@ typedef struct sctp_new_association_req_s {
net_ip_address_t
remote_address
;
}
sctp_new_association_req_t
;
typedef
struct
sctp_new_association_req_multi_s
{
/* Upper layer connexion identifier */
uint16_t
ulp_cnx_id
;
/* The port to connect to */
uint16_t
port
;
/* Payload Protocol Identifier to use */
uint32_t
ppid
;
/* Number of streams used for this association */
uint16_t
in_streams
;
uint16_t
out_streams
;
/* Local address to bind to */
net_ip_address_t
local_address
;
/* Remote address to connect to */
net_ip_address_t
remote_address
;
/* Multi-socket descriptor */
int
multi_sd
;
}
sctp_new_association_req_multi_t
;
typedef
struct
sctp_init_msg_multi_cnf_s
{
int
multi_sd
;
}
sctp_init_msg_multi_cnf_t
;
typedef
struct
sctp_new_association_ind_s
{
/* Assoc id of the new association */
int32_t
assoc_id
;
...
...
openair2/COMMON/x2ap_messages_def.h
View file @
afb2fd40
openair2/ENB_APP/enb_app.c
View file @
afb2fd40
...
...
@@ -47,7 +47,7 @@
# define EPC_MODE_ENABLED 0
# endif
//
# include "x2ap_eNB.h"
# include "x2ap_eNB.h"
# include "x2ap_messages_types.h"
# define X2AP_ENB_REGISTER_RETRY_DELAY 10
...
...
@@ -157,7 +157,7 @@ static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end)
RCconfig_X2
(
msg_p
,
enb_id
);
//
itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
itti_send_msg_to_task
(
TASK_X2AP
,
ENB_MODULE_ID_TO_INSTANCE
(
enb_id
),
msg_p
);
register_enb_x2_pending
++
;
}
...
...
@@ -179,8 +179,8 @@ void *eNB_app_task(void *args_p)
long
enb_register_retry_timer_id
;
# endif
uint32_t
x2_register_enb_pending
;
//
uint32_t x2_registered_enb;
//
long x2_enb_register_retry_timer_id;
uint32_t
x2_registered_enb
;
long
x2_enb_register_retry_timer_id
;
uint32_t
enb_id
;
MessageDef
*
msg_p
=
NULL
;
instance_t
instance
;
...
...
@@ -227,7 +227,7 @@ void *eNB_app_task(void *args_p)
#endif
/* Try to register each eNB with each other */
//
x2_registered_enb = 0;
x2_registered_enb
=
0
;
x2_register_enb_pending
=
eNB_app_register_x2
(
enb_id_start
,
enb_id_end
);
do
{
...
...
@@ -309,9 +309,60 @@ void *eNB_app_task(void *args_p)
registered_enb
=
0
;
register_enb_pending
=
eNB_app_register
(
enb_id_start
,
enb_id_end
);
//, enb_properties_p);
}
#endif
if
(
TIMER_HAS_EXPIRED
(
msg_p
).
timer_id
==
x2_enb_register_retry_timer_id
)
{
/* Restart the registration process */
x2_registered_enb
=
0
;
x2_register_enb_pending
=
eNB_app_register_x2
(
enb_id_start
,
enb_id_end
);
}
# endif
break
;
case
X2AP_DEREGISTERED_ENB_IND
:
LOG_W
(
ENB_APP
,
"[eNB %d] Received %s: associated eNB %d
\n
"
,
instance
,
ITTI_MSG_NAME
(
msg_p
),
X2AP_DEREGISTERED_ENB_IND
(
msg_p
).
nb_x2
);
/* TODO handle recovering of registration */
break
;
case
X2AP_REGISTER_ENB_CNF
:
LOG_I
(
ENB_APP
,
"[eNB %d] Received %s: associated eNB %d
\n
"
,
instance
,
ITTI_MSG_NAME
(
msg_p
),
X2AP_REGISTER_ENB_CNF
(
msg_p
).
nb_x2
);
DevAssert
(
x2_register_enb_pending
>
0
);
x2_register_enb_pending
--
;
/* Check if at least eNB is registered with one target eNB */
if
(
X2AP_REGISTER_ENB_CNF
(
msg_p
).
nb_x2
>
0
)
{
x2_registered_enb
++
;
}
/* Check if all register eNB requests have been processed */
if
(
x2_register_enb_pending
==
0
)
{
if
(
x2_registered_enb
==
enb_nb
)
{
/* If all eNB are registered, start RRC HO task */
}
else
{
uint32_t
x2_not_associated
=
enb_nb
-
x2_registered_enb
;
LOG_W
(
ENB_APP
,
" %d eNB %s not associated with the target
\n
"
,
x2_not_associated
,
x2_not_associated
>
1
?
"are"
:
"is"
);
// timer to retry
/* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
if
(
timer_setup
(
X2AP_ENB_REGISTER_RETRY_DELAY
,
0
,
TASK_ENB_APP
,
INSTANCE_DEFAULT
,
TIMER_ONE_SHOT
,
NULL
,
&
x2_enb_register_retry_timer_id
)
<
0
)
{
LOG_E
(
ENB_APP
,
" Can not start eNB X2AP register: retry timer, use
\"
sleep
\"
instead!
\n
"
);
sleep
(
X2AP_ENB_REGISTER_RETRY_DELAY
);
/* Restart the registration process */
x2_registered_enb
=
0
;
x2_register_enb_pending
=
eNB_app_register_x2
(
enb_id_start
,
enb_id_end
);
}
}
}
break
;
default:
LOG_E
(
ENB_APP
,
"Received unexpected message %s
\n
"
,
ITTI_MSG_NAME
(
msg_p
));
...
...
openair2/X2AP/x2ap_common.h
View file @
afb2fd40
...
...
@@ -61,10 +61,12 @@ extern int asn1_xer_print;
#if defined(ENB_MODE)
# include "common/utils/LOG/log.h"
# define X2AP_INFO(x, args...) LOG_I(X2AP, x, ##args)
# define X2AP_ERROR(x, args...) LOG_E(X2AP, x, ##args)
# define X2AP_WARN(x, args...) LOG_W(X2AP, x, ##args)
# define X2AP_DEBUG(x, args...) LOG_D(X2AP, x, ##args)
#else
# define X2AP_INFO(x, args...) do { fprintf(stdout, "[X2AP][I]"x, ##args); } while(0)
# define X2AP_ERROR(x, args...) do { fprintf(stdout, "[X2AP][E]"x, ##args); } while(0)
# define X2AP_WARN(x, args...) do { fprintf(stdout, "[X2AP][W]"x, ##args); } while(0)
# define X2AP_DEBUG(x, args...) do { fprintf(stdout, "[X2AP][D]"x, ##args); } while(0)
...
...
openair2/X2AP/x2ap_eNB.c
0 → 100644
View file @
afb2fd40
/*
* 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 <stdint.h>
#include <arpa/inet.h>
#include "intertask_interface.h"
#include "x2ap_eNB.h"
#include "x2ap_eNB_defs.h"
#include "x2ap_eNB_management_procedures.h"
#include "x2ap_eNB_handler.h"
#include "x2ap_common.h"
#include "queue.h"
#include "assertions.h"
#include "conversions.h"
struct
x2ap_enb_map
;
struct
x2ap_eNB_data_s
;
RB_PROTOTYPE
(
x2ap_enb_map
,
x2ap_eNB_data_s
,
entry
,
x2ap_eNB_compare_assoc_id
);
//static
//void x2ap_eNB_handle_sctp_data_ind(instance_t instance,
// sctp_data_ind_t *sctp_data_ind);
static
void
x2ap_eNB_handle_sctp_association_resp
(
instance_t
instance
,
sctp_new_association_resp_t
*
sctp_new_association_resp
);
static
void
x2ap_eNB_handle_sctp_association_ind
(
instance_t
instance
,
sctp_new_association_ind_t
*
sctp_new_association_ind
);
static
void
x2ap_eNB_handle_register_eNB
(
instance_t
instance
,
x2ap_register_enb_req_t
*
x2ap_register_eNB
);
static
void
x2ap_eNB_register_eNB
(
x2ap_eNB_instance_t
*
instance_p
,
net_ip_address_t
*
target_eNB_ip_addr
,
net_ip_address_t
*
local_ip_addr
,
uint16_t
in_streams
,
uint16_t
out_streams
,
uint32_t
enb_port_for_X2C
,
int
multi_sd
);
/*
static
void x2ap_eNB_handle_sctp_data_ind(instance_t instance,
sctp_data_ind_t *sctp_data_ind) {
int result;
DevAssert(sctp_data_ind != NULL);
x2ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream,
sctp_data_ind->buffer, sctp_data_ind->buffer_length);
result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}*/
static
void
x2ap_eNB_handle_sctp_association_resp
(
instance_t
instance
,
sctp_new_association_resp_t
*
sctp_new_association_resp
)
{
x2ap_eNB_instance_t
*
instance_p
;
x2ap_eNB_data_t
*
x2ap_enb_data_p
;
DevAssert
(
sctp_new_association_resp
!=
NULL
);
printf
(
"x2ap_eNB_handle_sctp_association_resp at 1
\n
"
);
dump_trees
();
instance_p
=
x2ap_eNB_get_instance
(
instance
);
DevAssert
(
instance_p
!=
NULL
);
/* if the assoc_id is already known, it is certainly because an IND was received
* before. In this case, just update streams and return
*/
if
(
sctp_new_association_resp
->
assoc_id
!=
-
1
)
{
x2ap_enb_data_p
=
x2ap_get_eNB
(
instance_p
,
sctp_new_association_resp
->
assoc_id
,
sctp_new_association_resp
->
ulp_cnx_id
);
if
(
x2ap_enb_data_p
!=
NULL
)
{
/* some sanity check - to be refined at some point */
if
(
sctp_new_association_resp
->
sctp_state
!=
SCTP_STATE_ESTABLISHED
)
{
X2AP_ERROR
(
"x2ap_enb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?
\n
"
);
abort
();
}
x2ap_enb_data_p
->
in_streams
=
sctp_new_association_resp
->
in_streams
;
x2ap_enb_data_p
->
out_streams
=
sctp_new_association_resp
->
out_streams
;
return
;
}
}
x2ap_enb_data_p
=
x2ap_get_eNB
(
instance_p
,
-
1
,
sctp_new_association_resp
->
ulp_cnx_id
);
DevAssert
(
x2ap_enb_data_p
!=
NULL
);
printf
(
"x2ap_eNB_handle_sctp_association_resp at 2
\n
"
);
dump_trees
();
if
(
sctp_new_association_resp
->
sctp_state
!=
SCTP_STATE_ESTABLISHED
)
{
X2AP_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
);
x2ap_handle_x2_setup_message
(
x2ap_enb_data_p
,
sctp_new_association_resp
->
sctp_state
==
SCTP_STATE_SHUTDOWN
);
return
;
}
printf
(
"x2ap_eNB_handle_sctp_association_resp at 3
\n
"
);
dump_trees
();
/* Update parameters */
x2ap_enb_data_p
->
assoc_id
=
sctp_new_association_resp
->
assoc_id
;
x2ap_enb_data_p
->
in_streams
=
sctp_new_association_resp
->
in_streams
;
x2ap_enb_data_p
->
out_streams
=
sctp_new_association_resp
->
out_streams
;
printf
(
"x2ap_eNB_handle_sctp_association_resp at 4
\n
"
);
dump_trees
();
/* Prepare new x2 Setup Request */
//x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p);
}
static
void
x2ap_eNB_handle_sctp_association_ind
(
instance_t
instance
,
sctp_new_association_ind_t
*
sctp_new_association_ind
)
{
x2ap_eNB_instance_t
*
instance_p
;
x2ap_eNB_data_t
*
x2ap_enb_data_p
;
printf
(
"x2ap_eNB_handle_sctp_association_ind at 1 (called for instance %d)
\n
"
,
instance
);
dump_trees
();
DevAssert
(
sctp_new_association_ind
!=
NULL
);
instance_p
=
x2ap_eNB_get_instance
(
instance
);
DevAssert
(
instance_p
!=
NULL
);
x2ap_enb_data_p
=
x2ap_get_eNB
(
instance_p
,
sctp_new_association_ind
->
assoc_id
,
-
1
);
if
(
x2ap_enb_data_p
!=
NULL
)
abort
();
// DevAssert(x2ap_enb_data_p != NULL);
if
(
x2ap_enb_data_p
==
NULL
)
{
/* Create new eNB descriptor */
x2ap_enb_data_p
=
calloc
(
1
,
sizeof
(
*
x2ap_enb_data_p
));
DevAssert
(
x2ap_enb_data_p
!=
NULL
);
x2ap_enb_data_p
->
cnx_id
=
x2ap_eNB_fetch_add_global_cnx_id
();
x2ap_enb_data_p
->
x2ap_eNB_instance
=
instance_p
;
/* Insert the new descriptor in list of known eNB
* but not yet associated.
*/
RB_INSERT
(
x2ap_enb_map
,
&
instance_p
->
x2ap_enb_head
,
x2ap_enb_data_p
);
x2ap_enb_data_p
->
state
=
X2AP_ENB_STATE_CONNECTED
;
instance_p
->
x2_target_enb_nb
++
;
if
(
instance_p
->
x2_target_enb_pending_nb
>
0
)
{
instance_p
->
x2_target_enb_pending_nb
--
;
}
}
else
{
X2AP_WARN
(
"x2ap_enb_data_p already exists
\n
"
);
}
printf
(
"x2ap_eNB_handle_sctp_association_ind at 2
\n
"
);
dump_trees
();
/* Update parameters */
x2ap_enb_data_p
->
assoc_id
=
sctp_new_association_ind
->
assoc_id
;
x2ap_enb_data_p
->
in_streams
=
sctp_new_association_ind
->
in_streams
;
x2ap_enb_data_p
->
out_streams
=
sctp_new_association_ind
->
out_streams
;
printf
(
"x2ap_eNB_handle_sctp_association_ind at 3
\n
"
);
dump_trees
();
}
int
x2ap_eNB_init_sctp
(
x2ap_eNB_instance_t
*
instance_p
,
net_ip_address_t
*
local_ip_addr
,
uint32_t
enb_port_for_X2C
)
{
// Create and alloc new message
MessageDef
*
message
;
sctp_init_t
*
sctp_init
=
NULL
;
DevAssert
(
instance_p
!=
NULL
);
DevAssert
(
local_ip_addr
!=
NULL
);
message
=
itti_alloc_new_message
(
TASK_X2AP
,
SCTP_INIT_MSG_MULTI_REQ
);
sctp_init
=
&
message
->
ittiMsg
.
sctp_init_multi
;
sctp_init
->
port
=
enb_port_for_X2C
;
sctp_init
->
ppid
=
X2AP_SCTP_PPID
;
sctp_init
->
ipv4
=
1
;
sctp_init
->
ipv6
=
0
;
sctp_init
->
nb_ipv4_addr
=
1
;
#if 0
memcpy(&sctp_init->ipv4_address,
local_ip_addr,
sizeof(*local_ip_addr));
#endif
sctp_init
->
ipv4_address
[
0
]
=
inet_addr
(
local_ip_addr
->
ipv4_address
);
/*
* SR WARNING: ipv6 multi-homing fails sometimes for localhost.
* * * * Disable it for now.
*/
sctp_init
->
nb_ipv6_addr
=
0
;
sctp_init
->
ipv6_address
[
0
]
=
"0:0:0:0:0:0:0:1"
;
return
itti_send_msg_to_task
(
TASK_SCTP
,
instance_p
->
instance
,
message
);
}
static
void
x2ap_eNB_register_eNB
(
x2ap_eNB_instance_t
*
instance_p
,
net_ip_address_t
*
target_eNB_ip_address
,
net_ip_address_t
*
local_ip_addr
,
uint16_t
in_streams
,
uint16_t
out_streams
,
uint32_t
enb_port_for_X2C
,
int
multi_sd
)
{
MessageDef
*
message
=
NULL
;
sctp_new_association_req_multi_t
*
sctp_new_association_req
=
NULL
;
x2ap_eNB_data_t
*
x2ap_enb_data
=
NULL
;
DevAssert
(
instance_p
!=
NULL
);
DevAssert
(
target_eNB_ip_address
!=
NULL
);
message
=
itti_alloc_new_message
(
TASK_X2AP
,
SCTP_NEW_ASSOCIATION_REQ_MULTI
);
sctp_new_association_req
=
&
message
->
ittiMsg
.
sctp_new_association_req_multi
;
sctp_new_association_req
->
port
=
enb_port_for_X2C
;
sctp_new_association_req
->
ppid
=
X2AP_SCTP_PPID
;
sctp_new_association_req
->
in_streams
=
in_streams
;
sctp_new_association_req
->
out_streams
=
out_streams
;
sctp_new_association_req
->
multi_sd
=
multi_sd
;
memcpy
(
&
sctp_new_association_req
->
remote_address
,
target_eNB_ip_address
,
sizeof
(
*
target_eNB_ip_address
));
memcpy
(
&
sctp_new_association_req
->
local_address
,
local_ip_addr
,
sizeof
(
*
local_ip_addr
));
/* Create new eNB descriptor */
x2ap_enb_data
=
calloc
(
1
,
sizeof
(
*
x2ap_enb_data
));
DevAssert
(
x2ap_enb_data
!=
NULL
);
x2ap_enb_data
->
cnx_id
=
x2ap_eNB_fetch_add_global_cnx_id
();
sctp_new_association_req
->
ulp_cnx_id
=
x2ap_enb_data
->
cnx_id
;
x2ap_enb_data
->
assoc_id
=
-
1
;
x2ap_enb_data
->
x2ap_eNB_instance
=
instance_p
;
/* Insert the new descriptor in list of known eNB
* but not yet associated.
*/
RB_INSERT
(
x2ap_enb_map
,
&
instance_p
->
x2ap_enb_head
,
x2ap_enb_data
);
x2ap_enb_data
->
state
=
X2AP_ENB_STATE_WAITING
;
instance_p
->
x2_target_enb_nb
++
;
instance_p
->
x2_target_enb_pending_nb
++
;
itti_send_msg_to_task
(
TASK_SCTP
,
instance_p
->
instance
,
message
);
}
static
void
x2ap_eNB_handle_register_eNB
(
instance_t
instance
,
x2ap_register_enb_req_t
*
x2ap_register_eNB
)
{
x2ap_eNB_instance_t
*
new_instance
;
DevAssert
(
x2ap_register_eNB
!=
NULL
);
/* Look if the provided instance already exists */
new_instance
=
x2ap_eNB_get_instance
(
instance
);
if
(
new_instance
!=
NULL
)
{
/* Checks if it is a retry on the same eNB */
DevCheck
(
new_instance
->
eNB_id
==
x2ap_register_eNB
->
eNB_id
,
new_instance
->
eNB_id
,
x2ap_register_eNB
->
eNB_id
,
0
);
DevCheck
(
new_instance
->
cell_type
==
x2ap_register_eNB
->
cell_type
,
new_instance
->
cell_type
,
x2ap_register_eNB
->
cell_type
,
0
);
DevCheck
(
new_instance
->
tac
==
x2ap_register_eNB
->
tac
,
new_instance
->
tac
,
x2ap_register_eNB
->
tac
,
0
);
DevCheck
(
new_instance
->
mcc
==
x2ap_register_eNB
->
mcc
,
new_instance
->
mcc
,
x2ap_register_eNB
->
mcc
,
0
);
DevCheck
(
new_instance
->
mnc
==
x2ap_register_eNB
->
mnc
,
new_instance
->
mnc
,
x2ap_register_eNB
->
mnc
,
0
);
X2AP_WARN
(
"eNB[%d] already registered
\n
"
,
instance
);
}
else
{
new_instance
=
calloc
(
1
,
sizeof
(
x2ap_eNB_instance_t
));
DevAssert
(
new_instance
!=
NULL
);
RB_INIT
(
&
new_instance
->
x2ap_enb_head
);
/* Copy usefull parameters */
new_instance
->
instance
=
instance
;
new_instance
->
eNB_name
=
x2ap_register_eNB
->
eNB_name
;
new_instance
->
eNB_id
=
x2ap_register_eNB
->
eNB_id
;
new_instance
->
cell_type
=
x2ap_register_eNB
->
cell_type
;
new_instance
->
tac
=
x2ap_register_eNB
->
tac
;
new_instance
->
mcc
=
x2ap_register_eNB
->
mcc
;
new_instance
->
mnc
=
x2ap_register_eNB
->
mnc
;
new_instance
->
mnc_digit_length
=
x2ap_register_eNB
->
mnc_digit_length
;
DevCheck
(
x2ap_register_eNB
->
nb_x2
<=
X2AP_MAX_NB_ENB_IP_ADDRESS
,
X2AP_MAX_NB_ENB_IP_ADDRESS
,
x2ap_register_eNB
->
nb_x2
,
0
);
memcpy
(
new_instance
->
target_enb_x2_ip_address
,
x2ap_register_eNB
->
target_enb_x2_ip_address
,
x2ap_register_eNB
->
nb_x2
*
sizeof
(
net_ip_address_t
));
new_instance
->
nb_x2
=
x2ap_register_eNB
->
nb_x2
;
new_instance
->
enb_x2_ip_address
=
x2ap_register_eNB
->
enb_x2_ip_address
;
new_instance
->
sctp_in_streams
=
x2ap_register_eNB
->
sctp_in_streams
;
new_instance
->
sctp_out_streams
=
x2ap_register_eNB
->
sctp_out_streams
;
new_instance
->
enb_port_for_X2C
=
x2ap_register_eNB
->
enb_port_for_X2C
;
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
x2ap_eNB_insert_new_instance
(
new_instance
);
X2AP_INFO
(
"Registered new eNB[%d] and %s eNB id %u
\n
"
,
instance
,
x2ap_register_eNB
->
cell_type
==
CELL_MACRO_ENB
?
"macro"
:
"home"
,
x2ap_register_eNB
->
eNB_id
);
/* initiate the SCTP listener */
if
(
x2ap_eNB_init_sctp
(
new_instance
,
&
x2ap_register_eNB
->
enb_x2_ip_address
,
x2ap_register_eNB
->
enb_port_for_X2C
)
<
0
)
{
X2AP_ERROR
(
"Error while sending SCTP_INIT_MSG to SCTP
\n
"
);
return
;
}
X2AP_INFO
(
"eNB[%d] eNB id %u acting as a listner (server)
\n
"
,
instance
,
x2ap_register_eNB
->
eNB_id
);
}
}
static
void
x2ap_eNB_handle_sctp_init_msg_multi_cnf
(
instance_t
instance_id
,
sctp_init_msg_multi_cnf_t
*
m
)
{
x2ap_eNB_instance_t
*
instance
;
int
index
;
DevAssert
(
m
!=
NULL
);
instance
=
x2ap_eNB_get_instance
(
instance_id
);
DevAssert
(
instance
!=
NULL
);
instance
->
multi_sd
=
m
->
multi_sd
;
/* Exit if CNF message reports failure.
* Failure means multi_sd < 0.
*/
DevAssert
(
instance
->
multi_sd
>=
0
);
/* Trying to connect to the provided list of eNB ip address */
for
(
index
=
0
;
index
<
instance
->
nb_x2
;
index
++
)
{
X2AP_INFO
(
"eNB[%d] eNB id %u acting as an initiator (client)
\n
"
,
instance_id
,
instance
->
eNB_id
);
x2ap_eNB_register_eNB
(
instance
,
&
instance
->
target_enb_x2_ip_address
[
index
],
&
instance
->
enb_x2_ip_address
,
instance
->
sctp_in_streams
,
instance
->
sctp_out_streams
,
instance
->
enb_port_for_X2C
,
instance
->
multi_sd
);
}
}
void
*
x2ap_task
(
void
*
arg
)
{
MessageDef
*
received_msg
=
NULL
;
int
result
;
X2AP_DEBUG
(
"Starting X2AP layer
\n
"
);
x2ap_eNB_prepare_internal_data
();
itti_mark_task_ready
(
TASK_X2AP
);
while
(
1
)
{
itti_receive_msg
(
TASK_X2AP
,
&
received_msg
);
switch
(
ITTI_MSG_ID
(
received_msg
))
{
case
TERMINATE_MESSAGE
:
X2AP_WARN
(
" *** Exiting X2AP thread
\n
"
);
itti_exit_task
();
break
;
case
X2AP_REGISTER_ENB_REQ
:
x2ap_eNB_handle_register_eNB
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
&
X2AP_REGISTER_ENB_REQ
(
received_msg
));
break
;
case
SCTP_INIT_MSG_MULTI_CNF
:
x2ap_eNB_handle_sctp_init_msg_multi_cnf
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
&
received_msg
->
ittiMsg
.
sctp_init_msg_multi_cnf
);
break
;
case
SCTP_NEW_ASSOCIATION_RESP
:
x2ap_eNB_handle_sctp_association_resp
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
&
received_msg
->
ittiMsg
.
sctp_new_association_resp
);
break
;
case
SCTP_NEW_ASSOCIATION_IND
:
x2ap_eNB_handle_sctp_association_ind
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
&
received_msg
->
ittiMsg
.
sctp_new_association_ind
);
break
;
case
SCTP_DATA_IND
:
//x2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
// &received_msg->ittiMsg.sctp_data_ind);
break
;
default:
X2AP_ERROR
(
"Received unhandled message: %d:%s
\n
"
,
ITTI_MSG_ID
(
received_msg
),
ITTI_MSG_NAME
(
received_msg
));
break
;
}
result
=
itti_free
(
ITTI_MSG_ORIGIN_ID
(
received_msg
),
received_msg
);
AssertFatal
(
result
==
EXIT_SUCCESS
,
"Failed to free memory (%d)!
\n
"
,
result
);
received_msg
=
NULL
;
}
return
NULL
;
}
openair2/X2AP/x2ap.h
→
openair2/X2AP/x2ap
_eNB
.h
View file @
afb2fd40
...
...
@@ -30,10 +30,12 @@
#ifndef X2AP_H_
#define X2AP_H_
typedef
struct
x2ap_config_s
{
}
x2ap_config_t
;
#define X2AP_SCTP_PPID (27) ///< X2AP SCTP Payload Protocol Identifier (PPID)
#include "x2ap_eNB_defs.h"
extern
x2ap_config_t
x2ap_config
;
int
x2ap_eNB_init_sctp
(
x2ap_eNB_instance_t
*
instance_p
,
net_ip_address_t
*
local_ip_addr
,
uint32_t
enb_port_for_X2C
);
void
*
x2ap_task
(
void
*
arg
);
...
...
openair2/X2AP/x2ap_eNB_defs.h
0 → 100644
View file @
afb2fd40
/*
* 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 <stdint.h>
#include "queue.h"
#include "tree.h"
#include "sctp_eNB_defs.h"
#ifndef X2AP_ENB_DEFS_H_
#define X2AP_ENB_DEFS_H_
#define X2AP_ENB_NAME_LENGTH_MAX (150)
typedef
enum
{
/* Disconnected state: initial state for any association. */
X2AP_ENB_STATE_DISCONNECTED
=
0x0
,
/* State waiting for x2 Setup response message if the target eNB accepts or
* X2 Setup failure if rejects the eNB.
*/
X2AP_ENB_STATE_WAITING
=
0x1
,
/* The eNB is successfully connected to another eNB. */
X2AP_ENB_STATE_CONNECTED
=
0x2
,
/* X2AP is ready, and the eNB is successfully connected to another eNB. */
X2AP_ENB_STATE_READY
=
0x3
,
X2AP_ENB_STATE_OVERLOAD
=
0x4
,
X2AP_ENB_STATE_RESETTING
=
0x5
,
/* Max number of states available */
X2AP_ENB_STATE_MAX
,
}
x2ap_eNB_state_t
;
/* Served PLMN identity element */
struct
plmn_identity_s
{
uint16_t
mcc
;
uint16_t
mnc
;
uint8_t
mnc_digit_length
;
STAILQ_ENTRY
(
plmn_identity_s
)
next
;
};
/* Served group id element */
struct
served_group_id_s
{
uint16_t
enb_group_id
;
STAILQ_ENTRY
(
served_group_id_s
)
next
;
};
/* Served enn code for a particular eNB */
struct
enb_code_s
{
uint8_t
enb_code
;
STAILQ_ENTRY
(
enb_code_s
)
next
;
};
struct
x2ap_eNB_instance_s
;
/* This structure describes association of a eNB to another eNB */
typedef
struct
x2ap_eNB_data_s
{
/* eNB descriptors tree, ordered by sctp assoc id */
RB_ENTRY
(
x2ap_eNB_data_s
)
entry
;
/* This is the optional name provided by the MME */
char
*
eNB_name
;
/* target eNB ID */
uint32_t
eNB_id
;
/* Current eNB load information (if any). */
//x2ap_load_state_t overload_state;
/* Current eNB->eNB X2AP association state */
x2ap_eNB_state_t
state
;
/* Next usable stream for UE signalling */
int32_t
nextstream
;
/* Number of input/ouput streams */
uint16_t
in_streams
;
uint16_t
out_streams
;
/* Connexion id used between SCTP/X2AP */
uint16_t
cnx_id
;
/* SCTP association id */
int32_t
assoc_id
;
/* Only meaningfull in virtual mode */
struct
x2ap_eNB_instance_s
*
x2ap_eNB_instance
;
}
x2ap_eNB_data_t
;
typedef
struct
x2ap_eNB_instance_s
{
/* used in simulation to store multiple eNB instances*/
STAILQ_ENTRY
(
x2ap_eNB_instance_s
)
x2ap_eNB_entries
;
/* Number of target eNBs requested by eNB (tree size) */
uint32_t
x2_target_enb_nb
;
/* Number of target eNBs for which association is pending */
uint32_t
x2_target_enb_pending_nb
;
/* Number of target eNB successfully associated to eNB */
uint32_t
x2_target_enb_associated_nb
;
/* Tree of X2AP eNB associations ordered by association ID */
RB_HEAD
(
x2ap_enb_map
,
x2ap_eNB_data_s
)
x2ap_enb_head
;
/* Tree of UE ordered by eNB_ue_x2ap_id's */
// RB_HEAD(x2ap_ue_map, x2ap_eNB_ue_context_s) x2ap_ue_head;
/* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
instance_t
instance
;
/* Displayable name of eNB */
char
*
eNB_name
;
/* Unique eNB_id to identify the eNB within EPC.
* In our case the eNB is a macro eNB so the id will be 20 bits long.
* For Home eNB id, this field should be 28 bits long.
*/
uint32_t
eNB_id
;
/* The type of the cell */
cell_type_t
cell_type
;
/* Tracking area code */
uint16_t
tac
;
/* Mobile Country Code
* Mobile Network Code
*/
uint16_t
mcc
;
uint16_t
mnc
;
uint8_t
mnc_digit_length
;
net_ip_address_t
target_enb_x2_ip_address
[
X2AP_MAX_NB_ENB_IP_ADDRESS
];
uint8_t
nb_x2
;
net_ip_address_t
enb_x2_ip_address
;
uint16_t
sctp_in_streams
;
uint16_t
sctp_out_streams
;
uint32_t
enb_port_for_X2C
;
int
multi_sd
;
}
x2ap_eNB_instance_t
;
typedef
struct
{
/* List of served eNBs
* Only used for virtual mode
*/
STAILQ_HEAD
(
x2ap_eNB_instances_head_s
,
x2ap_eNB_instance_s
)
x2ap_eNB_instances_head
;
/* Nb of registered eNBs */
uint8_t
nb_registered_eNBs
;
/* Generate a unique connexion id used between X2AP and SCTP */
uint16_t
global_cnx_id
;
}
x2ap_eNB_internal_data_t
;
int
x2ap_eNB_compare_assoc_id
(
struct
x2ap_eNB_data_s
*
p1
,
struct
x2ap_eNB_data_s
*
p2
);
/* Generate the tree management functions */
struct
x2ap_eNB_map
;
struct
x2ap_eNB_data_s
;
RB_PROTOTYPE
(
x2ap_eNB_map
,
x2ap_eNB_data_s
,
entry
,
x2ap_eNB_compare_assoc_id
);
#endif
/* X2AP_ENB_DEFS_H_ */
openair2/X2AP/x2ap_eNB_handler.c
0 → 100644
View file @
afb2fd40
/*
* 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 <stdint.h>
#include "intertask_interface.h"
#include "asn1_conversions.h"
#include "x2ap_common.h"
#include "x2ap_eNB_defs.h"
#include "x2ap_eNB_handler.h"
#include "x2ap_eNB_management_procedures.h"
#include "assertions.h"
#include "conversions.h"
void
x2ap_handle_x2_setup_message
(
x2ap_eNB_data_t
*
enb_desc_p
,
int
sctp_shutdown
)
{
if
(
sctp_shutdown
)
{
/* A previously connected eNB has been shutdown */
/* TODO check if it was used by some eNB and send a message to inform these eNB if there is no more associated eNB */
if
(
enb_desc_p
->
state
==
X2AP_ENB_STATE_CONNECTED
)
{
enb_desc_p
->
state
=
X2AP_ENB_STATE_DISCONNECTED
;
if
(
enb_desc_p
->
x2ap_eNB_instance
->
x2_target_enb_associated_nb
>
0
)
{
/* Decrease associated eNB number */
enb_desc_p
->
x2ap_eNB_instance
->
x2_target_enb_associated_nb
--
;
}
/* If there are no more associated eNB, inform eNB app */
if
(
enb_desc_p
->
x2ap_eNB_instance
->
x2_target_enb_associated_nb
==
0
)
{
MessageDef
*
message_p
;
message_p
=
itti_alloc_new_message
(
TASK_X2AP
,
X2AP_DEREGISTERED_ENB_IND
);
X2AP_DEREGISTERED_ENB_IND
(
message_p
).
nb_x2
=
0
;
itti_send_msg_to_task
(
TASK_ENB_APP
,
enb_desc_p
->
x2ap_eNB_instance
->
instance
,
message_p
);
}
}
}
else
{
/* Check that at least one setup message is pending */
DevCheck
(
enb_desc_p
->
x2ap_eNB_instance
->
x2_target_enb_pending_nb
>
0
,
enb_desc_p
->
x2ap_eNB_instance
->
instance
,
enb_desc_p
->
x2ap_eNB_instance
->
x2_target_enb_pending_nb
,
0
);
if
(
enb_desc_p
->
x2ap_eNB_instance
->
x2_target_enb_pending_nb
>
0
)
{
/* Decrease pending messages number */
enb_desc_p
->
x2ap_eNB_instance
->
x2_target_enb_pending_nb
--
;
}
/* If there are no more pending messages, inform eNB app */
if
(
enb_desc_p
->
x2ap_eNB_instance
->
x2_target_enb_pending_nb
==
0
)
{
MessageDef
*
message_p
;
message_p
=
itti_alloc_new_message
(
TASK_X2AP
,
X2AP_REGISTER_ENB_CNF
);
X2AP_REGISTER_ENB_CNF
(
message_p
).
nb_x2
=
enb_desc_p
->
x2ap_eNB_instance
->
x2_target_enb_associated_nb
;
itti_send_msg_to_task
(
TASK_ENB_APP
,
enb_desc_p
->
x2ap_eNB_instance
->
instance
,
message_p
);
}
}
}
openair2/X2AP/x2ap_eNB_handler.h
0 → 100644
View file @
afb2fd40
/*
* 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 X2AP_ENB_HANDLERS_H_
#define X2AP_ENB_HANDLERS_H_
#include "x2ap_eNB_defs.h"
void
x2ap_handle_x2_setup_message
(
x2ap_eNB_data_t
*
mme_desc_p
,
int
sctp_shutdown
);
//int x2ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
// const uint8_t * const data, const uint32_t data_length);
#endif
/* X2AP_ENB_HANDLERS_H_ */
openair2/X2AP/x2ap_eNB_management_procedures.c
0 → 100644
View file @
afb2fd40
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "intertask_interface.h"
#include "assertions.h"
#include "conversions.h"
#include "x2ap_common.h"
#include "x2ap_eNB_defs.h"
#include "x2ap_eNB.h"
#define X2AP_DEBUG_LIST
#ifdef X2AP_DEBUG_LIST
# define X2AP_eNB_LIST_OUT(x, args...) X2AP_DEBUG("[eNB]%*s"x"\n", 4*indent, "", ##args)
#else
# define X2AP_eNB_LIST_OUT(x, args...)
#endif
static
int
indent
=
0
;
x2ap_eNB_internal_data_t
x2ap_eNB_internal_data
;
RB_GENERATE
(
x2ap_enb_map
,
x2ap_eNB_data_s
,
entry
,
x2ap_eNB_compare_assoc_id
);
int
x2ap_eNB_compare_assoc_id
(
struct
x2ap_eNB_data_s
*
p1
,
struct
x2ap_eNB_data_s
*
p2
)
{
if
(
p1
->
assoc_id
==
-
1
)
{
if
(
p1
->
cnx_id
<
p2
->
cnx_id
)
{
return
-
1
;
}
if
(
p1
->
cnx_id
>
p2
->
cnx_id
)
{
return
1
;
}
}
else
{
if
(
p1
->
assoc_id
<
p2
->
assoc_id
)
{
return
-
1
;
}
if
(
p1
->
assoc_id
>
p2
->
assoc_id
)
{
return
1
;
}
}
/* Matching reference */
return
0
;
}
uint16_t
x2ap_eNB_fetch_add_global_cnx_id
(
void
)
{
return
++
x2ap_eNB_internal_data
.
global_cnx_id
;
}
void
x2ap_eNB_prepare_internal_data
(
void
)
{
memset
(
&
x2ap_eNB_internal_data
,
0
,
sizeof
(
x2ap_eNB_internal_data
));
STAILQ_INIT
(
&
x2ap_eNB_internal_data
.
x2ap_eNB_instances_head
);
}
void
x2ap_eNB_insert_new_instance
(
x2ap_eNB_instance_t
*
new_instance_p
)
{
DevAssert
(
new_instance_p
!=
NULL
);
STAILQ_INSERT_TAIL
(
&
x2ap_eNB_internal_data
.
x2ap_eNB_instances_head
,
new_instance_p
,
x2ap_eNB_entries
);
}
void
dump_tree
(
x2ap_eNB_data_t
*
t
)
{
if
(
t
==
NULL
)
return
;
printf
(
"-----------------------
\n
"
);
printf
(
"eNB id %d %s
\n
"
,
t
->
eNB_id
,
t
->
eNB_name
);
printf
(
"state %d
\n
"
,
t
->
state
);
printf
(
"nextstream %d
\n
"
,
t
->
nextstream
);
printf
(
"in_streams %d out_streams %d
\n
"
,
t
->
in_streams
,
t
->
out_streams
);
printf
(
"cnx_id %d assoc_id %d
\n
"
,
t
->
cnx_id
,
t
->
assoc_id
);
dump_tree
(
t
->
entry
.
rbe_left
);
dump_tree
(
t
->
entry
.
rbe_right
);
}
void
dump_trees
(
void
)
{
x2ap_eNB_instance_t
*
zz
;
STAILQ_FOREACH
(
zz
,
&
x2ap_eNB_internal_data
.
x2ap_eNB_instances_head
,
x2ap_eNB_entries
)
{
printf
(
"here comes the tree (instance %d):
\n
---------------------------------------------
\n
"
,
zz
->
instance
);
dump_tree
(
zz
->
x2ap_enb_head
.
rbh_root
);
printf
(
"---------------------------------------------
\n
"
);
}
}
struct
x2ap_eNB_data_s
*
x2ap_get_eNB
(
x2ap_eNB_instance_t
*
instance_p
,
int32_t
assoc_id
,
uint16_t
cnx_id
)
{
struct
x2ap_eNB_data_s
temp
;
struct
x2ap_eNB_data_s
*
found
;
printf
(
"x2ap_get_eNB at 1 (looking for assoc_id %d cnx_id %d)
\n
"
,
assoc_id
,
cnx_id
);
dump_trees
();
memset
(
&
temp
,
0
,
sizeof
(
struct
x2ap_eNB_data_s
));
temp
.
assoc_id
=
assoc_id
;
temp
.
cnx_id
=
cnx_id
;
if
(
instance_p
==
NULL
)
{
STAILQ_FOREACH
(
instance_p
,
&
x2ap_eNB_internal_data
.
x2ap_eNB_instances_head
,
x2ap_eNB_entries
)
{
found
=
RB_FIND
(
x2ap_enb_map
,
&
instance_p
->
x2ap_enb_head
,
&
temp
);
if
(
found
!=
NULL
)
{
return
found
;
}
}
}
else
{
return
RB_FIND
(
x2ap_enb_map
,
&
instance_p
->
x2ap_enb_head
,
&
temp
);
}
return
NULL
;
}
x2ap_eNB_instance_t
*
x2ap_eNB_get_instance
(
instance_t
instance
)
{
x2ap_eNB_instance_t
*
temp
=
NULL
;
STAILQ_FOREACH
(
temp
,
&
x2ap_eNB_internal_data
.
x2ap_eNB_instances_head
,
x2ap_eNB_entries
)
{
if
(
temp
->
instance
==
instance
)
{
/* Matching occurence */
return
temp
;
}
}
return
NULL
;
}
/// utility functions
void
x2ap_dump_eNB
(
x2ap_eNB_data_t
*
eNB_ref
);
void
x2ap_dump_eNB_list
(
void
)
{
x2ap_eNB_instance_t
*
inst
=
NULL
;
struct
x2ap_eNB_data_s
*
found
=
NULL
;
struct
x2ap_eNB_data_s
temp
;
memset
(
&
temp
,
0
,
sizeof
(
struct
x2ap_eNB_data_s
));
STAILQ_FOREACH
(
inst
,
&
x2ap_eNB_internal_data
.
x2ap_eNB_instances_head
,
x2ap_eNB_entries
)
{
found
=
RB_FIND
(
x2ap_enb_map
,
&
inst
->
x2ap_enb_head
,
&
temp
);
x2ap_dump_eNB
(
found
);
}
}
void
x2ap_dump_eNB
(
x2ap_eNB_data_t
*
eNB_ref
)
{
if
(
eNB_ref
==
NULL
)
{
return
;
}
X2AP_eNB_LIST_OUT
(
""
);
X2AP_eNB_LIST_OUT
(
"eNB name: %s"
,
eNB_ref
->
eNB_name
==
NULL
?
"not present"
:
eNB_ref
->
eNB_name
);
X2AP_eNB_LIST_OUT
(
"eNB STATE: %07x"
,
eNB_ref
->
state
);
X2AP_eNB_LIST_OUT
(
"eNB ID: %07x"
,
eNB_ref
->
eNB_id
);
indent
++
;
X2AP_eNB_LIST_OUT
(
"SCTP cnx id: %d"
,
eNB_ref
->
cnx_id
);
X2AP_eNB_LIST_OUT
(
"SCTP assoc id: %d"
,
eNB_ref
->
assoc_id
);
X2AP_eNB_LIST_OUT
(
"SCTP instreams: %d"
,
eNB_ref
->
in_streams
);
X2AP_eNB_LIST_OUT
(
"SCTP outstreams: %d"
,
eNB_ref
->
out_streams
);
indent
--
;
}
x2ap_eNB_data_t
*
x2ap_is_eNB_id_in_list
(
const
uint32_t
eNB_id
)
{
x2ap_eNB_instance_t
*
inst
;
struct
x2ap_eNB_data_s
*
elm
;
STAILQ_FOREACH
(
inst
,
&
x2ap_eNB_internal_data
.
x2ap_eNB_instances_head
,
x2ap_eNB_entries
)
{
RB_FOREACH
(
elm
,
x2ap_enb_map
,
&
inst
->
x2ap_enb_head
)
{
if
(
elm
->
eNB_id
==
eNB_id
)
return
elm
;
}
}
return
NULL
;
}
x2ap_eNB_data_t
*
x2ap_is_eNB_assoc_id_in_list
(
const
uint32_t
sctp_assoc_id
)
{
x2ap_eNB_instance_t
*
inst
;
struct
x2ap_eNB_data_s
*
found
;
struct
x2ap_eNB_data_s
temp
;
temp
.
assoc_id
=
sctp_assoc_id
;
temp
.
cnx_id
=
-
1
;
STAILQ_FOREACH
(
inst
,
&
x2ap_eNB_internal_data
.
x2ap_eNB_instances_head
,
x2ap_eNB_entries
)
{
found
=
RB_FIND
(
x2ap_enb_map
,
&
inst
->
x2ap_enb_head
,
&
temp
);
if
(
found
!=
NULL
){
if
(
found
->
assoc_id
==
sctp_assoc_id
)
{
return
found
;
}
}
}
return
NULL
;
}
openair2/X2AP/x2ap
.c
→
openair2/X2AP/x2ap
_eNB_management_procedures.h
View file @
afb2fd40
...
...
@@ -19,53 +19,28 @@
* contact@openairinterface.org
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#ifndef X2AP_ENB_MANAGEMENT_PROCEDURES_H_
#define X2AP_ENB_MANAGEMENT_PROCEDURES_H
void
x2ap_eNB_prepare_internal_data
(
void
);
#include "intertask_interface.h"
void
dump_trees
(
void
);
#include "x2ap.h"
void
x2ap_eNB_insert_new_instance
(
x2ap_eNB_instance_t
*
new_instance_p
);
#include "assertions.h"
#include "conversions.h"
x2ap_eNB_instance_t
*
x2ap_eNB_get_instance
(
uint8_t
mod_id
);
uint16_t
x2ap_eNB_fetch_add_global_cnx_id
(
void
);
void
*
x2ap_task
(
void
*
arg
)
{
MessageDef
*
received_msg
=
NULL
;
int
result
;
void
x2ap_eNB_prepare_internal_data
(
void
);
X2AP_DEBUG
(
"Starting X2AP layer
\n
"
);
x2ap_eNB_data_t
*
x2ap_is_eNB_id_in_list
(
uint32_t
eNB_id
);
x2ap_prepare_internal_data
(
);
x2ap_eNB_data_t
*
x2ap_is_eNB_assoc_id_in_list
(
uint32_t
sctp_assoc_id
);
itti_mark_task_ready
(
TASK_X2AP
);
while
(
1
)
{
itti_receive_msg
(
TASK_X2AP
,
&
received_msg
);
switch
(
ITTI_MSG_ID
(
received_msg
))
{
case
TERMINATE_MESSAGE
:
X2AP_WARN
(
" *** Exiting X2AP thread
\n
"
);
itti_exit_task
();
break
;
default:
X2AP_ERROR
(
"Received unhandled message: %d:%s
\n
"
,
ITTI_MSG_ID
(
received_msg
),
ITTI_MSG_NAME
(
received_msg
));
break
;
}
result
=
itti_free
(
ITTI_MSG_ORIGIN_ID
(
received_msg
),
received_msg
);
AssertFatal
(
result
==
EXIT_SUCCESS
,
"Failed to free memory (%d)!
\n
"
,
result
);
received_msg
=
NULL
;
}
return
NULL
;
}
struct
x2ap_eNB_data_s
*
x2ap_get_eNB
(
x2ap_eNB_instance_t
*
instance_p
,
int32_t
assoc_id
,
uint16_t
cnx_id
);
#endif
/* X2AP_ENB_MANAGEMENT_PROCEDURES_H_ */
openair3/SCTP/sctp_common.c
View file @
afb2fd40
...
...
@@ -86,6 +86,12 @@ int sctp_get_sockinfo(int sock, uint16_t *instream, uint16_t *outstream,
memset
(
&
status
,
0
,
sizeof
(
struct
sctp_status
));
i
=
sizeof
(
struct
sctp_status
);
/* if sock refers to a multi SCTP endpoint, *assoc_id gives us
* the association ID that we want
*/
if
(
assoc_id
!=
NULL
)
status
.
sstat_assoc_id
=
*
assoc_id
;
if
(
getsockopt
(
sock
,
IPPROTO_SCTP
,
SCTP_STATUS
,
&
status
,
&
i
)
<
0
)
{
SCTP_ERROR
(
"Getsockopt SCTP_STATUS failed: %s
\n
"
,
strerror
(
errno
));
return
-
1
;
...
...
openair3/SCTP/sctp_eNB_itti_messaging.c
View file @
afb2fd40
...
...
@@ -24,6 +24,20 @@
#include "sctp_common.h"
#include "sctp_eNB_itti_messaging.h"
int
sctp_itti_send_init_msg_multi_cnf
(
task_id_t
task_id
,
instance_t
instance
,
int
multi_sd
)
{
MessageDef
*
message_p
;
sctp_init_msg_multi_cnf_t
*
sctp_init_msg_multi_cnf_p
;
message_p
=
itti_alloc_new_message
(
TASK_SCTP
,
SCTP_INIT_MSG_MULTI_CNF
);
sctp_init_msg_multi_cnf_p
=
&
message_p
->
ittiMsg
.
sctp_init_msg_multi_cnf
;
sctp_init_msg_multi_cnf_p
->
multi_sd
=
multi_sd
;
return
itti_send_msg_to_task
(
task_id
,
instance
,
message_p
);
}
int
sctp_itti_send_new_message_ind
(
task_id_t
task_id
,
uint32_t
assoc_id
,
uint8_t
*
buffer
,
uint32_t
buffer_length
,
uint16_t
stream
)
{
...
...
openair3/SCTP/sctp_eNB_itti_messaging.h
View file @
afb2fd40
...
...
@@ -22,6 +22,8 @@
#ifndef SCTP_ITTI_MESSAGING_H_
#define SCTP_ITTI_MESSAGING_H_
int
sctp_itti_send_init_msg_multi_cnf
(
task_id_t
task_id
,
instance_t
instance
,
int
multi_sd
);
int
sctp_itti_send_new_message_ind
(
task_id_t
task_id
,
uint32_t
assoc_id
,
uint8_t
*
buffer
,
uint32_t
buffer_length
,
uint16_t
stream
);
...
...
openair3/SCTP/sctp_eNB_task.c
View file @
afb2fd40
...
...
@@ -61,6 +61,7 @@
enum
sctp_connection_type_e
{
SCTP_TYPE_CLIENT
,
SCTP_TYPE_SERVER
,
SCTP_TYPE_MULTI_SERVER
,
SCTP_TYPE_MAX
};
...
...
@@ -91,7 +92,6 @@ typedef struct sctp_cnx_list_elm_s {
static
STAILQ_HEAD
(
sctp_cnx_list_head
,
sctp_cnx_list_elm_s
)
sctp_cnx_list
;
static
uint16_t
sctp_nb_cnx
=
0
;
//------------------------------------------------------------------------------
struct
sctp_cnx_list_elm_s
*
sctp_get_cnx
(
int32_t
assoc_id
,
int
sd
)
{
...
...
@@ -112,6 +112,242 @@ struct sctp_cnx_list_elm_s *sctp_get_cnx(int32_t assoc_id, int sd)
return
NULL
;
}
//------------------------------------------------------------------------------
static
inline
void
sctp_eNB_accept_associations_multi
(
struct
sctp_cnx_list_elm_s
*
sctp_cnx
)
{
int
ns
;
int
n
;
int
flags
=
0
;
socklen_t
from_len
;
struct
sctp_sndrcvinfo
sinfo
;
struct
sockaddr_in
addr
;
uint8_t
buffer
[
SCTP_RECV_BUFFER_SIZE
];
DevAssert
(
sctp_cnx
!=
NULL
);
memset
((
void
*
)
&
addr
,
0
,
sizeof
(
struct
sockaddr_in
));
from_len
=
(
socklen_t
)
sizeof
(
struct
sockaddr_in
);
memset
((
void
*
)
&
sinfo
,
0
,
sizeof
(
struct
sctp_sndrcvinfo
));
n
=
sctp_recvmsg
(
sctp_cnx
->
sd
,
(
void
*
)
buffer
,
SCTP_RECV_BUFFER_SIZE
,
(
struct
sockaddr
*
)
&
addr
,
&
from_len
,
&
sinfo
,
&
flags
);
if
(
n
<
0
)
{
if
(
errno
==
ENOTCONN
)
{
SCTP_DEBUG
(
"Received not connected for sd %d
\n
"
,
sctp_cnx
->
sd
);
close
(
sctp_cnx
->
sd
);
}
else
{
SCTP_DEBUG
(
"An error occured during read
\n
"
);
SCTP_ERROR
(
"sctp_recvmsg (fd %d, len %d ): %s:%d
\n
"
,
sctp_cnx
->
sd
,
n
,
strerror
(
errno
),
errno
);
}
return
;
}
if
(
flags
&
MSG_NOTIFICATION
)
{
union
sctp_notification
*
snp
;
snp
=
(
union
sctp_notification
*
)
buffer
;
SCTP_DEBUG
(
"Received notification for sd %d, type %u
\n
"
,
sctp_cnx
->
sd
,
snp
->
sn_header
.
sn_type
);
/* Association has changed. */
if
(
SCTP_ASSOC_CHANGE
==
snp
->
sn_header
.
sn_type
)
{
struct
sctp_assoc_change
*
sctp_assoc_changed
;
sctp_assoc_changed
=
&
snp
->
sn_assoc_change
;
SCTP_DEBUG
(
"Client association changed: %d
\n
"
,
sctp_assoc_changed
->
sac_state
);
/* New physical association requested by a peer */
switch
(
sctp_assoc_changed
->
sac_state
)
{
case
SCTP_COMM_UP
:
{
SCTP_DEBUG
(
"Comm up notified for sd %d, assigned assoc_id %d
\n
"
,
sctp_cnx
->
sd
,
sctp_assoc_changed
->
sac_assoc_id
);
struct
sctp_cnx_list_elm_s
*
new_cnx
;
new_cnx
=
calloc
(
1
,
sizeof
(
*
sctp_cnx
));
DevAssert
(
new_cnx
!=
NULL
);
new_cnx
->
connection_type
=
SCTP_TYPE_CLIENT
;
ns
=
sctp_peeloff
(
sctp_cnx
->
sd
,
sctp_assoc_changed
->
sac_assoc_id
);
new_cnx
->
sd
=
ns
;
new_cnx
->
task_id
=
sctp_cnx
->
task_id
;
new_cnx
->
cnx_id
=
0
;
new_cnx
->
ppid
=
sctp_cnx
->
ppid
;
new_cnx
->
instance
=
sctp_cnx
->
instance
;
new_cnx
->
local_port
=
sctp_cnx
->
local_port
;
new_cnx
->
assoc_id
=
sctp_assoc_changed
->
sac_assoc_id
;
if
(
sctp_get_sockinfo
(
ns
,
&
new_cnx
->
in_streams
,
&
new_cnx
->
out_streams
,
&
new_cnx
->
assoc_id
)
!=
0
)
{
SCTP_ERROR
(
"sctp_get_sockinfo failed
\n
"
);
close
(
ns
);
free
(
new_cnx
);
return
;
}
/* Insert new element at end of list */
STAILQ_INSERT_TAIL
(
&
sctp_cnx_list
,
new_cnx
,
entries
);
sctp_nb_cnx
++
;
/* Add the socket to list of fd monitored by ITTI */
itti_subscribe_event_fd
(
TASK_SCTP
,
ns
);
sctp_itti_send_association_ind
(
new_cnx
->
task_id
,
new_cnx
->
instance
,
new_cnx
->
assoc_id
,
new_cnx
->
local_port
,
new_cnx
->
out_streams
,
new_cnx
->
in_streams
);
}
break
;
default:
break
;
}
}
}
else
{
SCTP_DEBUG
(
"No notification from SCTP
\n
"
);
}
}
//------------------------------------------------------------------------------
void
sctp_handle_new_association_req_multi
(
const
instance_t
instance
,
const
task_id_t
requestor
,
const
sctp_new_association_req_multi_t
*
const
sctp_new_association_req_p
)
{
int
ns
;
int
sd
;
int32_t
assoc_id
=
0
;
struct
sctp_cnx_list_elm_s
*
sctp_cnx
=
NULL
;
enum
sctp_connection_type_e
connection_type
=
SCTP_TYPE_CLIENT
;
/* Prepare a new SCTP association as requested by upper layer and try to connect
* to remote host.
*/
DevAssert
(
sctp_new_association_req_p
!=
NULL
);
sd
=
sctp_new_association_req_p
->
multi_sd
;
/* Create new socket with IPv6 affinity */
//#warning "SCTP may Force IPv4 only, here"
/* Mark the socket as non-blocking */
//if (fcntl(sd, F_SETFL, O_NONBLOCK) < 0) {
//SCTP_ERROR("fcntl F_SETFL O_NONBLOCK failed: %s\n",
// strerror(errno));
//close(sd);
//return;
//}
/* SOCK_STREAM socket type requires an explicit connect to the remote host
* address and port.
* Only use IPv4 for the first connection attempt
*/
if
((
sctp_new_association_req_p
->
remote_address
.
ipv6
!=
0
)
||
(
sctp_new_association_req_p
->
remote_address
.
ipv4
!=
0
))
{
uint8_t
address_index
=
0
;
uint8_t
used_address
=
sctp_new_association_req_p
->
remote_address
.
ipv6
+
sctp_new_association_req_p
->
remote_address
.
ipv4
;
struct
sockaddr_in
addr
[
used_address
];
memset
(
addr
,
0
,
used_address
*
sizeof
(
struct
sockaddr_in
));
if
(
sctp_new_association_req_p
->
remote_address
.
ipv6
==
1
)
{
if
(
inet_pton
(
AF_INET6
,
sctp_new_association_req_p
->
remote_address
.
ipv6_address
,
&
addr
[
address_index
].
sin_addr
.
s_addr
)
!=
1
)
{
SCTP_ERROR
(
"Failed to convert ipv6 address %*s to network type
\n
"
,
(
int
)
strlen
(
sctp_new_association_req_p
->
remote_address
.
ipv6_address
),
sctp_new_association_req_p
->
remote_address
.
ipv6_address
);
//close(sd);
//return;
exit
(
1
);
}
SCTP_DEBUG
(
"Converted ipv6 address %*s to network type
\n
"
,
(
int
)
strlen
(
sctp_new_association_req_p
->
remote_address
.
ipv6_address
),
sctp_new_association_req_p
->
remote_address
.
ipv6_address
);
addr
[
address_index
].
sin_family
=
AF_INET6
;
addr
[
address_index
].
sin_port
=
htons
(
sctp_new_association_req_p
->
port
);
address_index
++
;
}
if
(
sctp_new_association_req_p
->
remote_address
.
ipv4
==
1
)
{
if
(
inet_pton
(
AF_INET
,
sctp_new_association_req_p
->
remote_address
.
ipv4_address
,
&
addr
[
address_index
].
sin_addr
.
s_addr
)
!=
1
)
{
SCTP_ERROR
(
"Failed to convert ipv4 address %*s to network type
\n
"
,
(
int
)
strlen
(
sctp_new_association_req_p
->
remote_address
.
ipv4_address
),
sctp_new_association_req_p
->
remote_address
.
ipv4_address
);
//close(sd);
//return;
exit
(
1
);
}
SCTP_DEBUG
(
"Converted ipv4 address %*s to network type
\n
"
,
(
int
)
strlen
(
sctp_new_association_req_p
->
remote_address
.
ipv4_address
),
sctp_new_association_req_p
->
remote_address
.
ipv4_address
);
addr
[
address_index
].
sin_family
=
AF_INET
;
addr
[
address_index
].
sin_port
=
htons
(
sctp_new_association_req_p
->
port
);
address_index
++
;
}
/* Connect to remote host and port */
if
(
sctp_connectx
(
sd
,
(
struct
sockaddr
*
)
addr
,
1
,
&
assoc_id
)
<
0
)
{
/* sctp_connectx on non-blocking socket return EINPROGRESS */
if
(
errno
!=
EINPROGRESS
)
{
SCTP_ERROR
(
"Connect failed: %s
\n
"
,
strerror
(
errno
));
sctp_itti_send_association_resp
(
requestor
,
instance
,
-
1
,
sctp_new_association_req_p
->
ulp_cnx_id
,
SCTP_STATE_UNREACHABLE
,
0
,
0
);
/* Add the socket to list of fd monitored by ITTI */
//itti_unsubscribe_event_fd(TASK_SCTP, sd);
//close(sd);
return
;
}
else
{
SCTP_DEBUG
(
"connectx assoc_id %d in progress..., used %d addresses
\n
"
,
assoc_id
,
used_address
);
}
}
else
{
SCTP_DEBUG
(
"sctp_connectx SUCCESS, used %d addresses assoc_id %d
\n
"
,
used_address
,
assoc_id
);
}
}
ns
=
sctp_peeloff
(
sd
,
assoc_id
);
sctp_cnx
=
calloc
(
1
,
sizeof
(
*
sctp_cnx
));
sctp_cnx
->
connection_type
=
connection_type
;
sctp_cnx
->
sd
=
ns
;
sctp_cnx
->
task_id
=
requestor
;
sctp_cnx
->
cnx_id
=
sctp_new_association_req_p
->
ulp_cnx_id
;
sctp_cnx
->
ppid
=
sctp_new_association_req_p
->
ppid
;
sctp_cnx
->
instance
=
instance
;
sctp_cnx
->
assoc_id
=
assoc_id
;
/* Add the socket to list of fd monitored by ITTI */
itti_subscribe_event_fd
(
TASK_SCTP
,
ns
);
/* Insert new element at end of list */
STAILQ_INSERT_TAIL
(
&
sctp_cnx_list
,
sctp_cnx
,
entries
);
sctp_nb_cnx
++
;
SCTP_DEBUG
(
"Inserted new descriptor for sd %d in list, nb elements %u, assoc_id %d
\n
"
,
ns
,
sctp_nb_cnx
,
assoc_id
);
}
//------------------------------------------------------------------------------
void
sctp_handle_new_association_req
(
...
...
@@ -441,7 +677,8 @@ static int sctp_close_association(
static
int
sctp_create_new_listener
(
const
instance_t
instance
,
const
task_id_t
requestor
,
sctp_init_t
*
init_p
)
sctp_init_t
*
init_p
,
int
server_type
)
{
struct
sctp_event_subscribe
event
;
struct
sockaddr
*
addr
=
NULL
;
...
...
@@ -501,10 +738,18 @@ static int sctp_create_new_listener(
}
}
if
(
server_type
)
{
if
((
sd
=
socket
(
PF_INET
,
SOCK_SEQPACKET
,
IPPROTO_SCTP
))
<
0
)
{
SCTP_ERROR
(
"socket: %s:%d
\n
"
,
strerror
(
errno
),
errno
);
return
-
1
;
}
}
else
{
if
((
sd
=
socket
(
AF_INET6
,
SOCK_STREAM
,
IPPROTO_SCTP
))
<
0
)
{
SCTP_ERROR
(
"socket: %s:%d
\n
"
,
strerror
(
errno
),
errno
);
return
-
1
;
}
}
memset
((
void
*
)
&
event
,
1
,
sizeof
(
struct
sctp_event_subscribe
));
...
...
@@ -516,7 +761,13 @@ static int sctp_create_new_listener(
sctp_cnx
=
calloc
(
1
,
sizeof
(
*
sctp_cnx
));
if
(
server_type
)
{
sctp_cnx
->
connection_type
=
SCTP_TYPE_MULTI_SERVER
;
}
else
{
sctp_cnx
->
connection_type
=
SCTP_TYPE_SERVER
;
}
sctp_cnx
->
sd
=
sd
;
sctp_cnx
->
local_port
=
init_p
->
port
;
sctp_cnx
->
in_streams
=
32
;
...
...
@@ -729,6 +980,7 @@ sctp_eNB_read_from_socket(
break
;
default:
SCTP_WARN
(
"unhandled: SCTP_ASSOC_CHANGE to %d
\n
"
,
sctp_assoc_changed
->
sac_state
);
break
;
}
}
...
...
@@ -777,7 +1029,11 @@ sctp_eNB_flush_sockets(
if
(
sctp_cnx
->
connection_type
==
SCTP_TYPE_CLIENT
)
{
sctp_eNB_read_from_socket
(
sctp_cnx
);
}
else
{
}
else
if
(
sctp_cnx
->
connection_type
==
SCTP_TYPE_MULTI_SERVER
)
{
sctp_eNB_accept_associations_multi
(
sctp_cnx
);
}
else
{
sctp_eNB_accept_associations
(
sctp_cnx
);
}
}
...
...
@@ -812,10 +1068,45 @@ void *sctp_eNB_task(void *arg)
if
(
sctp_create_new_listener
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
ITTI_MSG_ORIGIN_ID
(
received_msg
),
&
received_msg
->
ittiMsg
.
sctp_init
)
<
0
)
{
&
received_msg
->
ittiMsg
.
sctp_init
,
0
)
<
0
)
{
/* SCTP socket creation or bind failed... */
SCTP_ERROR
(
"Failed to create new SCTP listener
\n
"
);
}
}
break
;
case
SCTP_INIT_MSG_MULTI_REQ
:
{
int
multi_sd
;
SCTP_DEBUG
(
"Received SCTP_INIT_MSG_MULTI_REQ
\n
"
);
multi_sd
=
sctp_create_new_listener
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
ITTI_MSG_ORIGIN_ID
(
received_msg
),
&
received_msg
->
ittiMsg
.
sctp_init_multi
,
1
);
/* We received a new connection request */
if
(
multi_sd
<
0
)
{
/* SCTP socket creation or bind failed... */
SCTP_ERROR
(
"Failed to create new SCTP listener
\n
"
);
}
sctp_itti_send_init_msg_multi_cnf
(
ITTI_MSG_ORIGIN_ID
(
received_msg
),
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
multi_sd
);
}
break
;
case
SCTP_NEW_ASSOCIATION_REQ
:
{
sctp_handle_new_association_req
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
ITTI_MSG_ORIGIN_ID
(
received_msg
),
&
received_msg
->
ittiMsg
.
sctp_new_association_req
);
}
break
;
case
SCTP_NEW_ASSOCIATION_REQ_MULTI
:
{
sctp_handle_new_association_req_multi
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
ITTI_MSG_ORIGIN_ID
(
received_msg
),
&
received_msg
->
ittiMsg
.
sctp_new_association_req_multi
);
}
break
;
...
...
@@ -830,13 +1121,6 @@ void *sctp_eNB_task(void *arg)
itti_exit_task
();
break
;
case
SCTP_NEW_ASSOCIATION_REQ
:
{
sctp_handle_new_association_req
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
ITTI_MSG_ORIGIN_ID
(
received_msg
),
&
received_msg
->
ittiMsg
.
sctp_new_association_req
);
}
break
;
case
SCTP_DATA_REQ
:
{
sctp_send_data
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
ITTI_MSG_ORIGIN_ID
(
received_msg
),
...
...
targets/COMMON/create_tasks.c
View file @
afb2fd40
...
...
@@ -27,6 +27,7 @@
# ifdef OPENAIR2
# if defined(ENABLE_USE_MME)
# include "sctp_eNB_task.h"
# include "x2ap_eNB.h"
# include "s1ap_eNB.h"
# include "nas_ue_task.h"
# include "udp_eNB_task.h"
...
...
@@ -64,6 +65,11 @@ int create_tasks(uint32_t enb_nb)
# if defined(ENABLE_USE_MME)
if
(
EPC_MODE_ENABLED
)
{
if
(
enb_nb
>
0
)
{
if
(
itti_create_task
(
TASK_X2AP
,
x2ap_task
,
NULL
)
<
0
)
{
LOG_E
(
X2AP
,
"Create task for X2AP failed
\n
"
);
return
-
1
;
}
if
(
itti_create_task
(
TASK_SCTP
,
sctp_eNB_task
,
NULL
)
<
0
)
{
LOG_E
(
SCTP
,
"Create task for SCTP failed
\n
"
);
return
-
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