Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG UE
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
Michael Black
OpenXG UE
Commits
6cbd85f3
Commit
6cbd85f3
authored
Jun 26, 2014
by
Lionel Gauthier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
git-svn-id:
http://svn.eurecom.fr/openair4G/trunk@5438
818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent
2e698946
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
178 additions
and
32 deletions
+178
-32
openair-cn/SCTP/sctp_eNB_task.c
openair-cn/SCTP/sctp_eNB_task.c
+178
-32
No files found.
openair-cn/SCTP/sctp_eNB_task.c
View file @
6cbd85f3
...
...
@@ -55,51 +55,49 @@
#include "sctp_common.h"
#include "sctp_eNB_itti_messaging.h"
/* Used to format an uint32_t containing an ipv4 address */
#define IPV4_ADDR "%u.%u.%u.%u"
#define IPV4_ADDR_FORMAT(aDDRESS) \
(uint8_t)((aDDRESS) & 0x000000ff), \
(uint8_t)(((aDDRESS) & 0x0000ff00) >> 8 ), \
(uint8_t)(((aDDRESS) & 0x00ff0000) >> 16), \
(uint8_t)(((aDDRESS) & 0xff000000) >> 24)
enum
sctp_connection_type_e
{
SCTP_TYPE_CLIENT
,
SCTP_TYPE_SERVER
,
SCTP_TYPE_MAX
};
struct
sctp_cnx_list_elm_s
{
typedef
struct
sctp_cnx_list_elm_s
{
STAILQ_ENTRY
(
sctp_cnx_list_elm_s
)
entries
;
/* Type of this association
*/
enum
sctp_connection_type_e
connection_type
;
/* Socket descriptor of connection */
int
sd
;
/* local port used */
int
sd
;
///< Socket descriptor of connection */
uint16_t
local_port
;
uint16_t
in_streams
;
///< Number of input streams negociated for this connection
uint16_t
out_streams
;
///< Number of output streams negotiated for this connection
uint16_t
ppid
;
///< Payload protocol Identifier
int32_t
assoc_id
;
///< SCTP association id for the connection
uint32_t
messages_recv
;
///< Number of messages received on this connection
uint32_t
messages_sent
;
///< Number of messages sent on this connection
task_id_t
task_id
;
///< Task id of the task who asked for this connection
instance_t
instance
;
///< Instance
uint16_t
cnx_id
;
///< Upper layer identifier
/* IN/OUT streams */
uint16_t
in_streams
;
uint16_t
out_streams
;
/* Configured PPID */
uint16_t
ppid
;
/* Association id */
int32_t
assoc_id
;
/* Nb of messages received on interface */
uint32_t
nb_messages
;
/* Task id of the task who asked for this connection */
task_id_t
task_id
;
struct
sockaddr
*
peer_addresses
;
///< A list of peer addresses for server socket
int
nb_peer_addresses
;
///< For server socket
}
sctp_cnx_list_elm_t
;
/* Instance */
instance_t
instance
;
/* Upper layer identifier */
uint16_t
cnx_id
;
};
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
)
{
struct
sctp_cnx_list_elm_s
*
elm
;
...
...
@@ -144,7 +142,15 @@ void sctp_handle_new_association_req(
DevAssert
(
sctp_new_association_req_p
!=
NULL
);
/* Create new socket with IPv6 affinity */
#ifdef NO_VIRTUAL_MACHINE
// in init chunk appears a list of host addresses, IPv4 and IPv4 in an arbitrary (unsorted) order
// SCTP hearbeats starts with first ipv4 addresses then stop triyng with other ipv4 addresses
// if it encounters an IPv6 address in list, so we can force the building of IPv4 addresses only
// with AF_INET (of cource the working IPv4 address is the last in the list...)
if
((
sd
=
socket
(
AF_INET6
,
SOCK_STREAM
,
IPPROTO_SCTP
))
<
0
)
{
#else
if
((
sd
=
socket
(
AF_INET
,
SOCK_STREAM
,
IPPROTO_SCTP
))
<
0
)
{
#endif
SCTP_ERROR
(
"Socket creation failed: %s
\n
"
,
strerror
(
errno
));
return
;
}
...
...
@@ -193,7 +199,7 @@ void sctp_handle_new_association_req(
if
(
s
>
0
)
{
if
(((
struct
sockaddr_in
*
)
ifa
->
ifa_addr
)
->
sin_addr
.
s_addr
==
in
.
s_addr
)
{
memset
(
&
ifr
,
0
,
sizeof
(
ifr
));
snprintf
(
ifr
.
ifr_name
,
sizeof
(
ifr
.
ifr_name
),
ifa
->
ifa_name
);
snprintf
(
ifr
.
ifr_name
,
sizeof
(
ifr
.
ifr_name
),
"%s"
,
ifa
->
ifa_name
);
if
(
setsockopt
(
sd
,
SOL_SOCKET
,
SO_BINDTODEVICE
,
(
void
*
)
&
ifr
,
sizeof
(
ifr
))
<
0
)
{
SCTP_ERROR
(
"Setsockopt SOL_SOCKET failed: %s
\n
"
,
strerror
(
errno
));
...
...
@@ -213,7 +219,7 @@ void sctp_handle_new_association_req(
if
(
memcmp
(
&
((
struct
sockaddr_in6
*
)
ifa
->
ifa_addr
)
->
sin6_addr
,
&
in6
,
sizeof
(
in6
))
==
0
)
{
memset
(
&
ifr
,
0
,
sizeof
(
ifr
));
snprintf
(
ifr
.
ifr_name
,
sizeof
(
ifr
.
ifr_name
),
ifa
->
ifa_name
);
snprintf
(
ifr
.
ifr_name
,
sizeof
(
ifr
.
ifr_name
),
"%s"
,
ifa
->
ifa_name
);
if
(
setsockopt
(
sd
,
SOL_SOCKET
,
SO_BINDTODEVICE
,
(
void
*
)
&
ifr
,
sizeof
(
ifr
))
<
0
)
{
SCTP_ERROR
(
"Setsockopt SOL_SOCKET failed: %s
\n
"
,
strerror
(
errno
));
...
...
@@ -304,8 +310,13 @@ void sctp_handle_new_association_req(
close
(
sd
);
return
;
}
else
{
SCTP_DEBUG
(
"connectx %d in progress...
\n
"
,
assoc_id
);
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
);
}
}
else
{
/* No remote address provided -> only bind the socket for now.
...
...
@@ -347,7 +358,10 @@ void sctp_handle_new_association_req(
sd
,
sctp_nb_cnx
,
assoc_id
);
}
void
sctp_send_data
(
instance_t
instance
,
task_id_t
task_id
,
sctp_data_req_t
*
sctp_data_req_p
)
void
sctp_send_data
(
instance_t
instance
,
task_id_t
task_id
,
sctp_data_req_t
*
sctp_data_req_p
)
{
struct
sctp_cnx_list_elm_s
*
sctp_cnx
=
NULL
;
...
...
@@ -384,6 +398,122 @@ void sctp_send_data(instance_t instance, task_id_t task_id, sctp_data_req_t *sct
sctp_cnx
->
assoc_id
);
}
static
int
sctp_create_new_listener
(
const
instance_t
instance
,
const
task_id_t
requestor
,
sctp_init_t
*
init_p
)
{
struct
sctp_event_subscribe
event
;
struct
sockaddr
*
addr
=
NULL
;
struct
sctp_cnx_list_elm_s
*
sctp_cnx
=
NULL
;
uint16_t
i
=
0
,
j
=
0
;
int
sd
=
0
;
int
used_addresses
=
0
;
DevAssert
(
init_p
!=
NULL
);
if
(
init_p
->
ipv4
==
0
&&
init_p
->
ipv6
==
0
)
{
SCTP_ERROR
(
"Illegal IP configuration upper layer should request at"
"least ipv4 and/or ipv6 config
\n
"
);
return
-
1
;
}
if
((
used_addresses
=
init_p
->
nb_ipv4_addr
+
init_p
->
nb_ipv6_addr
)
==
0
)
{
SCTP_WARN
(
"No address provided...
\n
"
);
return
-
1
;
}
addr
=
calloc
(
used_addresses
,
sizeof
(
struct
sockaddr
));
SCTP_DEBUG
(
"Creating new listen socket on port %u with
\n
"
,
init_p
->
port
);
if
(
init_p
->
ipv4
==
1
)
{
struct
sockaddr_in
*
ip4_addr
;
SCTP_DEBUG
(
"ipv4 addresses:
\n
"
);
for
(
i
=
0
;
i
<
init_p
->
nb_ipv4_addr
;
i
++
)
{
SCTP_DEBUG
(
"
\t
- "
IPV4_ADDR
"
\n
"
,
IPV4_ADDR_FORMAT
(
init_p
->
ipv4_address
[
i
]));
ip4_addr
=
(
struct
sockaddr_in
*
)
&
addr
[
i
];
ip4_addr
->
sin_family
=
AF_INET
;
ip4_addr
->
sin_port
=
htons
(
init_p
->
port
);
ip4_addr
->
sin_addr
.
s_addr
=
init_p
->
ipv4_address
[
i
];
}
}
if
(
init_p
->
ipv6
==
1
)
{
struct
sockaddr_in6
*
ip6_addr
;
SCTP_DEBUG
(
"ipv6 addresses:
\n
"
);
for
(
j
=
0
;
j
<
init_p
->
nb_ipv6_addr
;
j
++
)
{
SCTP_DEBUG
(
"
\t
- %s
\n
"
,
init_p
->
ipv6_address
[
j
]);
ip6_addr
=
(
struct
sockaddr_in6
*
)
&
addr
[
i
+
j
];
ip6_addr
->
sin6_family
=
AF_INET6
;
ip6_addr
->
sin6_port
=
htons
(
init_p
->
port
);
if
(
inet_pton
(
AF_INET6
,
init_p
->
ipv6_address
[
j
],
ip6_addr
->
sin6_addr
.
s6_addr
)
<=
0
)
{
SCTP_WARN
(
"Provided ipv6 address %s is not valid
\n
"
,
init_p
->
ipv6_address
[
j
]);
}
}
}
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
));
if
(
setsockopt
(
sd
,
IPPROTO_SCTP
,
SCTP_EVENTS
,
&
event
,
sizeof
(
struct
sctp_event_subscribe
))
<
0
)
{
SCTP_ERROR
(
"setsockopt: %s:%d
\n
"
,
strerror
(
errno
),
errno
);
return
-
1
;
}
sctp_cnx
=
calloc
(
1
,
sizeof
(
*
sctp_cnx
));
sctp_cnx
->
connection_type
=
SCTP_TYPE_SERVER
;
sctp_cnx
->
sd
=
sd
;
sctp_cnx
->
local_port
=
init_p
->
port
;
sctp_cnx
->
in_streams
=
32
;
sctp_cnx
->
out_streams
=
32
;
sctp_cnx
->
ppid
=
init_p
->
ppid
;
sctp_cnx
->
task_id
=
requestor
;
sctp_cnx
->
instance
=
instance
;
/* Some pre-bind socket configuration */
if
(
sctp_set_init_opt
(
sd
,
sctp_cnx
->
in_streams
,
sctp_cnx
->
out_streams
,
0
,
0
)
<
0
)
{
goto
err
;
}
if
(
sctp_bindx
(
sd
,
addr
,
used_addresses
,
SCTP_BINDX_ADD_ADDR
)
!=
0
)
{
SCTP_ERROR
(
"sctp_bindx: %s:%d
\n
"
,
strerror
(
errno
),
errno
);
return
-
1
;
}
if
(
listen
(
sd
,
5
)
<
0
)
{
SCTP_ERROR
(
"listen: %s:%d
\n
"
,
strerror
(
errno
),
errno
);
return
-
1
;
}
/* Insert new element at end of list */
STAILQ_INSERT_TAIL
(
&
sctp_cnx_list
,
sctp_cnx
,
entries
);
sctp_nb_cnx
++
;
/* Add the socket to list of fd monitored by ITTI */
itti_subscribe_event_fd
(
TASK_SCTP
,
sd
);
return
sd
;
err:
if
(
sd
!=
-
1
)
{
close
(
sd
);
sd
=
-
1
;
}
return
-
1
;
}
static
inline
void
sctp_eNB_accept_associations
(
struct
sctp_cnx_list_elm_s
*
sctp_cnx
)
{
...
...
@@ -547,7 +677,7 @@ inline void sctp_eNB_read_from_socket(struct sctp_cnx_list_elm_s *sctp_cnx)
}
}
}
else
{
sctp_cnx
->
nb_messages
++
;
sctp_cnx
->
messages_recv
++
;
if
(
ntohl
(
sinfo
.
sinfo_ppid
)
!=
sctp_cnx
->
ppid
)
{
/* Mismatch in Payload Protocol Identifier,
...
...
@@ -590,6 +720,7 @@ void sctp_eNB_flush_sockets(struct epoll_event *events, int nb_events)
}
}
void
*
sctp_eNB_task
(
void
*
arg
)
{
int
nb_events
;
...
...
@@ -610,9 +741,24 @@ void *sctp_eNB_task(void *arg)
if
(
received_msg
!=
NULL
)
{
switch
(
ITTI_MSG_ID
(
received_msg
))
{
case
SCTP_INIT_MSG
:
{
SCTP_DEBUG
(
"Received SCTP_INIT_MSG
\n
"
);
/* We received a new connection request */
if
(
sctp_create_new_listener
(
ITTI_MESSAGE_GET_INSTANCE
(
received_msg
),
ITTI_MSG_ORIGIN_ID
(
received_msg
),
&
received_msg
->
ittiMsg
.
sctp_init
)
<
0
)
{
/* SCTP socket creation or bind failed... */
SCTP_ERROR
(
"Failed to create new SCTP listener
\n
"
);
}
}
break
;
case
SCTP_CLOSE_ASSOCIATION
:
break
;
case
TERMINATE_MESSAGE
:
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
),
...
...
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