If SCTP use SOCK_STREAM, Use BUFFERING method.

Most of the time, an application wants to perform some amount of data buffering
in addition to just responding to events. When we want to write data,
for example, the usual pattern runs something like:

1. Decide that we want to write some data to a connection;
   put that data in a buffer.
2. Wait for the connection to become writable
3. Write as much of the data as we can
4. Remember how much we wrote, and if we still have more data to write,
   wait for the connection to become writable again.

Now, Open5GS implements the above method by default when transmitting data
in a stream type socket.
This commit is contained in:
Sukchan Lee 2020-11-11 13:21:32 -05:00
parent 9a1824f6aa
commit 6f11a78079
18 changed files with 283 additions and 173 deletions

View File

@ -37,6 +37,11 @@ typedef struct ogs_cluster_s {
typedef struct ogs_pkbuf_pool_s ogs_pkbuf_pool_t;
typedef struct ogs_pkbuf_s {
ogs_lnode_t lnode;
/* Currently it is used in SCTP stream number and PPID. */
uint64_t param[2];
ogs_cluster_t *cluster;
unsigned int len;

View File

@ -124,6 +124,12 @@ void ogs_pollset_remove(ogs_poll_t *poll)
ogs_pool_free(&pollset->pool, poll);
}
ogs_poll_t *ogs_pollset_cycle(ogs_pollset_t *pollset, ogs_poll_t *poll)
{
ogs_assert(pollset);
return ogs_pool_cycle(&pollset->pool, poll);
}
void *ogs_pollset_self_handler_data(void)
{
return &self_handler_data;

View File

@ -40,6 +40,7 @@ ogs_poll_t *ogs_pollset_add(ogs_pollset_t *pollset, short when,
ogs_socket_t fd, ogs_poll_handler_f handler, void *data);
void ogs_pollset_remove(ogs_poll_t *poll);
ogs_poll_t *ogs_pollset_cycle(ogs_pollset_t *pollset, ogs_poll_t *poll);
void *ogs_pollset_self_handler_data(void);
typedef struct ogs_pollset_actions_s {

View File

@ -20,9 +20,9 @@ libinc = include_directories('.')
subdir('core')
subdir('ipfw')
subdir('crypt')
subdir('app')
subdir('sctp')
subdir('dbi')
subdir('app')
subdir('diameter')
subdir('asn1c')
subdir('ngap')

View File

@ -59,10 +59,10 @@ libsctp = library('ogssctp',
version : libogslib_version,
c_args : '-DOGS_SCTP_COMPILATION',
include_directories : [libsctp_inc, libinc],
dependencies : [libcore_dep, sctp_dep],
dependencies : [libcore_dep, libapp_dep, sctp_dep],
install : true)
libsctp_dep = declare_dependency(
link_with : libsctp,
include_directories : [libsctp_inc, libinc],
dependencies : [libcore_dep, sctp_dep])
dependencies : [libcore_dep, libapp_dep, sctp_dep])

View File

@ -18,9 +18,12 @@
*/
#include "ogs-sctp.h"
#include "ogs-app.h"
int __ogs_sctp_domain;
static void sctp_write_callback(short when, ogs_socket_t fd, void *data);
void ogs_sctp_set_option(ogs_sockopt_t *option, ogs_socknode_t *node)
{
ogs_assert(option);
@ -99,3 +102,88 @@ int ogs_sctp_recvdata(ogs_sock_t *sock, void *msg, size_t len,
return size;
}
int ogs_sctp_senddata(ogs_sock_t *sock,
ogs_pkbuf_t *pkbuf, ogs_sockaddr_t *addr)
{
int sent;
ogs_assert(sock);
ogs_assert(pkbuf);
sent = ogs_sctp_sendmsg(sock, pkbuf->data, pkbuf->len, addr,
ogs_sctp_ppid_in_pkbuf(pkbuf), ogs_sctp_stream_no_in_pkbuf(pkbuf));
if (sent < 0 || sent != pkbuf->len) {
ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
"ogs_sctp_senddata(len:%d,ssn:%d)",
pkbuf->len, (int)ogs_sctp_stream_no_in_pkbuf(pkbuf));
ogs_pkbuf_free(pkbuf);
return OGS_ERROR;
}
ogs_pkbuf_free(pkbuf);
return OGS_OK;
}
void ogs_sctp_write_to_buffer(ogs_sctp_sock_t *sctp, ogs_pkbuf_t *pkbuf)
{
ogs_poll_t *poll = NULL;
ogs_assert(sctp);
ogs_assert(pkbuf);
ogs_list_add(&sctp->write_queue, pkbuf);
poll = ogs_pollset_cycle(ogs_app()->pollset, sctp->poll.write);
if (!poll) {
ogs_assert(sctp->sock);
sctp->poll.write = ogs_pollset_add(ogs_app()->pollset,
OGS_POLLOUT, sctp->sock->fd, sctp_write_callback, sctp);
}
}
static void sctp_write_callback(short when, ogs_socket_t fd, void *data)
{
ogs_sctp_sock_t *sctp = data;
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(sctp);
if (ogs_list_empty(&sctp->write_queue) == true) {
ogs_assert(sctp->poll.write);
ogs_pollset_remove(sctp->poll.write);
return;
}
pkbuf = ogs_list_first(&sctp->write_queue);
ogs_assert(pkbuf);
ogs_list_remove(&sctp->write_queue, pkbuf);
ogs_assert(sctp->sock);
ogs_sctp_senddata(sctp->sock, pkbuf, NULL);
}
void ogs_sctp_flush_and_destroy(ogs_sctp_sock_t *sctp)
{
ogs_poll_t *poll = NULL;
ogs_pkbuf_t *pkbuf = NULL, *next_pkbuf = NULL;
ogs_assert(sctp);
ogs_assert(sctp->addr);
ogs_free(sctp->addr);
if (sctp->type == SOCK_STREAM) {
poll = ogs_pollset_cycle(ogs_app()->pollset, sctp->poll.read);
ogs_assert(poll);
ogs_pollset_remove(poll);
poll = ogs_pollset_cycle(ogs_app()->pollset, sctp->poll.write);
if (poll)
ogs_pollset_remove(poll);
ogs_sctp_destroy(sctp->sock);
ogs_list_for_each_safe(&sctp->write_queue, next_pkbuf, pkbuf)
ogs_pkbuf_free(pkbuf);
}
}

View File

@ -48,6 +48,9 @@ extern int __ogs_sctp_domain;
#define OGS_SCTP_SGSAP_PPID 0
#define OGS_SCTP_NGAP_PPID 60
#define ogs_sctp_ppid_in_pkbuf(__pkBUF) (__pkBUF)->param[0]
#define ogs_sctp_stream_no_in_pkbuf(__pkBUF) (__pkBUF)->param[1]
#if HAVE_USRSCTP
#undef MSG_NOTIFICATION
@ -79,6 +82,20 @@ ogs_sock_t *ogs_sctp_accept(ogs_sock_t *sock);
#define DEFAULT_SCTP_MAX_NUM_OF_OSTREAMS 30
typedef struct ogs_sctp_sock_s {
int type; /* SOCK_STREAM or SOCK_SEQPACKET */
ogs_sock_t *sock; /* Socket */
ogs_sockaddr_t *addr; /* Address */
struct {
ogs_poll_t *read; /* Read Poll */
ogs_poll_t *write; /* Write Poll */
} poll;
ogs_list_t write_queue; /* Write Queue for Sending S1AP message */
} ogs_sctp_sock_t;
typedef struct ogs_sctp_info_s {
uint32_t ppid;
uint16_t stream_no;
@ -107,6 +124,11 @@ int ogs_sctp_recvmsg(ogs_sock_t *sock, void *msg, size_t len,
int ogs_sctp_recvdata(ogs_sock_t *sock, void *msg, size_t len,
ogs_sockaddr_t *from, ogs_sctp_info_t *sinfo);
int ogs_sctp_senddata(ogs_sock_t *sock,
ogs_pkbuf_t *pkbuf, ogs_sockaddr_t *addr);
void ogs_sctp_write_to_buffer(ogs_sctp_sock_t *sctp, ogs_pkbuf_t *pkbuf);
void ogs_sctp_flush_and_destroy(ogs_sctp_sock_t *sctp);
#ifdef __cplusplus
}
#endif

View File

@ -589,7 +589,7 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
ogs_min(max_num_of_ostreams, gnb->max_num_of_ostreams);
ogs_debug("gNB-N1 SCTP_COMM_UP[%s] Max Num of Outbound Streams[%d]",
OGS_ADDR(gnb->addr, buf), gnb->max_num_of_ostreams);
OGS_ADDR(gnb->sctp.addr, buf), gnb->max_num_of_ostreams);
break;

View File

@ -833,9 +833,15 @@ amf_gnb_t *amf_gnb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr)
ogs_assert(gnb);
memset(gnb, 0, sizeof *gnb);
gnb->sock = sock;
gnb->addr = addr;
gnb->sock_type = amf_gnb_sock_type(gnb->sock);
gnb->sctp.sock = sock;
gnb->sctp.addr = addr;
gnb->sctp.type = amf_gnb_sock_type(gnb->sctp.sock);
if (gnb->sctp.type == SOCK_STREAM) {
gnb->sctp.poll.read = ogs_pollset_add(ogs_app()->pollset,
OGS_POLLIN, sock->fd, ngap_recv_upcall, sock);
ogs_assert(gnb->sctp.poll.read);
}
gnb->max_num_of_ostreams = DEFAULT_SCTP_MAX_NUM_OF_OSTREAMS;
gnb->ostream_id = 0;
@ -847,13 +853,8 @@ amf_gnb_t *amf_gnb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr)
ogs_list_init(&gnb->ran_ue_list);
if (gnb->sock_type == SOCK_STREAM) {
gnb->poll = ogs_pollset_add(ogs_app()->pollset,
OGS_POLLIN, sock->fd, ngap_recv_upcall, sock);
ogs_assert(gnb->poll);
}
ogs_hash_set(self.gnb_addr_hash, gnb->addr, sizeof(ogs_sockaddr_t), gnb);
ogs_hash_set(self.gnb_addr_hash,
gnb->sctp.addr, sizeof(ogs_sockaddr_t), gnb);
memset(&e, 0, sizeof(e));
e.gnb = gnb;
@ -873,7 +874,7 @@ int amf_gnb_remove(amf_gnb_t *gnb)
amf_event_t e;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_list_remove(&self.gnb_list, gnb);
@ -882,15 +883,11 @@ int amf_gnb_remove(amf_gnb_t *gnb)
ogs_fsm_fini(&gnb->sm, &e);
ogs_fsm_delete(&gnb->sm);
ogs_hash_set(self.gnb_addr_hash, gnb->addr, sizeof(ogs_sockaddr_t), NULL);
ogs_hash_set(self.gnb_addr_hash,
gnb->sctp.addr, sizeof(ogs_sockaddr_t), NULL);
ogs_hash_set(self.gnb_id_hash, &gnb->gnb_id, sizeof(gnb->gnb_id), NULL);
if (gnb->sock_type == SOCK_STREAM) {
ogs_pollset_remove(gnb->poll);
ogs_sctp_destroy(gnb->sock);
}
ogs_free(gnb->addr);
ogs_sctp_flush_and_destroy(&gnb->sctp);
ogs_pool_free(&amf_gnb_pool, gnb);

View File

@ -120,10 +120,7 @@ typedef struct amf_gnb_s {
ogs_fsm_t sm; /* A state machine */
uint32_t gnb_id; /* gNB_ID received from gNB */
int sock_type; /* SOCK_STREAM or SOCK_SEQPACKET */
ogs_sock_t *sock; /* gNB NGAP Socket */
ogs_sockaddr_t *addr; /* gNB NGAP Address */
ogs_poll_t *poll; /* gNB NGAP Poll */
ogs_sctp_sock_t sctp; /* SCTP socket */
struct {
bool ng_setup_success; /* gNB NGAP Setup complete successfuly */
@ -132,7 +129,6 @@ typedef struct amf_gnb_s {
uint16_t max_num_of_ostreams;/* SCTP Max num of outbound streams */
uint16_t ostream_id; /* gnb_ostream_id generator */
uint8_t num_of_supported_ta_list;
struct {
ogs_uint24_t tac;

View File

@ -116,7 +116,7 @@ void ngap_handle_ng_setup_request(amf_gnb_t *gnb, ogs_ngap_message_t *message)
uint32_t gnb_id;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -169,7 +169,7 @@ void ngap_handle_ng_setup_request(amf_gnb_t *gnb, ogs_ngap_message_t *message)
}
ogs_ngap_GNB_ID_to_uint32(&globalGNB_ID->gNB_ID, &gnb_id);
ogs_debug(" IP[%s] GNB_ID[0x%x]", OGS_ADDR(gnb->addr, buf), gnb_id);
ogs_debug(" IP[%s] GNB_ID[0x%x]", OGS_ADDR(gnb->sctp.addr, buf), gnb_id);
if (PagingDRX)
ogs_debug(" PagingDRX[%ld]", *PagingDRX);
@ -336,7 +336,7 @@ void ngap_handle_initial_ue_message(amf_gnb_t *gnb, ogs_ngap_message_t *message)
NGAP_FiveG_S_TMSI_t *FiveG_S_TMSI = NULL;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -367,7 +367,8 @@ void ngap_handle_initial_ue_message(amf_gnb_t *gnb, ogs_ngap_message_t *message)
}
}
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
ogs_debug(" IP[%s] RAN_ID[%d]",
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
if (!RAN_UE_NGAP_ID) {
ogs_error("No RAN_UE_NGAP_ID");
@ -495,7 +496,7 @@ void ngap_handle_uplink_nas_transport(
NGAP_NAS_PDU_t *NAS_PDU = NULL;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -522,7 +523,8 @@ void ngap_handle_uplink_nas_transport(
}
}
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
ogs_debug(" IP[%s] RAN_ID[%d]",
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
if (!AMF_UE_NGAP_ID) {
ogs_error("No AMF_UE_NGAP_ID");
@ -581,7 +583,7 @@ void ngap_handle_ue_radio_capability_info_indication(
NGAP_UERadioCapability_t *UERadioCapability = NULL;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -610,7 +612,8 @@ void ngap_handle_ue_radio_capability_info_indication(
}
}
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
ogs_debug(" IP[%s] RAN_ID[%d]",
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
if (!AMF_UE_NGAP_ID) {
ogs_error("No AMF_UE_NGAP_ID");
@ -676,7 +679,7 @@ void ngap_handle_initial_context_setup_response(
OCTET_STRING_t *transfer = NULL;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
@ -705,7 +708,8 @@ void ngap_handle_initial_context_setup_response(
}
}
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
ogs_debug(" IP[%s] RAN_ID[%d]",
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
if (!AMF_UE_NGAP_ID) {
ogs_error("No AMF_UE_NGAP_ID");
@ -823,7 +827,7 @@ void ngap_handle_initial_context_setup_failure(
NGAP_Cause_t *Cause = NULL;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_assert(message);
unsuccessfulOutcome = message->choice.unsuccessfulOutcome;
@ -851,7 +855,8 @@ void ngap_handle_initial_context_setup_failure(
}
}
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
ogs_debug(" IP[%s] RAN_ID[%d]",
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
if (!AMF_UE_NGAP_ID) {
ogs_error("No AMF_UE_NGAP_ID");
@ -943,7 +948,7 @@ void ngap_handle_ue_context_release_request(
NGAP_Cause_t *Cause = NULL;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -974,7 +979,8 @@ void ngap_handle_ue_context_release_request(
}
}
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
ogs_debug(" IP[%s] RAN_ID[%d]",
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
if (!AMF_UE_NGAP_ID) {
ogs_error("No AMF_UE_NGAP_ID");
@ -1099,7 +1105,7 @@ void ngap_handle_ue_context_release_complete(
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
@ -1124,7 +1130,8 @@ void ngap_handle_ue_context_release_complete(
}
}
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
ogs_debug(" IP[%s] RAN_ID[%d]",
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
if (!AMF_UE_NGAP_ID) {
ogs_error("No AMF_UE_NGAP_ID");
@ -1234,7 +1241,7 @@ void ngap_handle_pdu_session_resource_setup_response(
OCTET_STRING_t *transfer = NULL;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
@ -1264,7 +1271,8 @@ void ngap_handle_pdu_session_resource_setup_response(
}
}
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
ogs_debug(" IP[%s] RAN_ID[%d]",
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
if (!AMF_UE_NGAP_ID) {
ogs_error("No AMF_UE_NGAP_ID");
@ -1398,7 +1406,7 @@ void ngap_handle_pdu_session_resource_release_response(
OCTET_STRING_t *transfer = NULL;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
@ -1428,7 +1436,8 @@ void ngap_handle_pdu_session_resource_release_response(
}
}
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
ogs_debug(" IP[%s] RAN_ID[%d]",
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
if (!AMF_UE_NGAP_ID) {
ogs_error("No AMF_UE_NGAP_ID");
@ -1573,7 +1582,7 @@ void ngap_handle_path_switch_request(
amf_nsmf_pdu_session_update_sm_context_param_t param;
ogs_assert(gnb);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -1607,7 +1616,8 @@ void ngap_handle_path_switch_request(
}
}
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
ogs_debug(" IP[%s] RAN_ID[%d]",
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
if (!AMF_UE_NGAP_ID) {
ogs_error("No AMF_UE_NGAP_ID");

View File

@ -46,40 +46,23 @@ void ngap_close()
ogs_socknode_remove_all(&amf_self()->ngap_list6);
}
int ngap_send(ogs_sock_t *sock, ogs_pkbuf_t *pkbuf,
ogs_sockaddr_t *addr, uint16_t stream_no)
{
int sent;
ogs_assert(sock);
ogs_assert(pkbuf);
sent = ogs_sctp_sendmsg(sock, pkbuf->data, pkbuf->len,
addr, OGS_SCTP_NGAP_PPID, stream_no);
if (sent < 0 || sent != pkbuf->len) {
ogs_error("ogs_sctp_sendmsg(len:%d,ssn:%d) error (%d:%s)",
pkbuf->len, stream_no, errno, strerror(errno));
ogs_pkbuf_free(pkbuf);
return OGS_ERROR;
}
ogs_pkbuf_free(pkbuf);
return OGS_OK;
}
int ngap_send_to_gnb(amf_gnb_t *gnb, ogs_pkbuf_t *pkbuf, uint16_t stream_no)
{
char buf[OGS_ADDRSTRLEN];
ogs_assert(gnb);
ogs_assert(pkbuf);
ogs_assert(gnb->sock);
ogs_assert(gnb->sctp.sock);
ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
ogs_debug(" IP[%s] RAN_ID[%d]",
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
return ngap_send(gnb->sock, pkbuf,
gnb->sock_type == SOCK_STREAM ? NULL : gnb->addr,
stream_no);
if (gnb->sctp.type == SOCK_STREAM) {
ogs_sctp_write_to_buffer(&gnb->sctp, pkbuf);
return OGS_OK;
} else {
return ogs_sctp_senddata(gnb->sctp.sock, pkbuf, gnb->sctp.addr);
}
}
int ngap_send_to_ran_ue(ran_ue_t *ran_ue, ogs_pkbuf_t *pkbuf)

View File

@ -1879,9 +1879,17 @@ mme_enb_t *mme_enb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr)
ogs_assert(enb);
memset(enb, 0, sizeof *enb);
enb->sock = sock;
enb->addr = addr;
enb->sock_type = mme_enb_sock_type(enb->sock);
enb->sctp.sock = sock;
enb->sctp.addr = addr;
enb->sctp.type = mme_enb_sock_type(enb->sctp.sock);
if (enb->sctp.type == SOCK_STREAM) {
enb->sctp.poll.read = ogs_pollset_add(ogs_app()->pollset,
OGS_POLLIN, sock->fd, s1ap_recv_upcall, sock);
ogs_assert(enb->sctp.poll.read);
ogs_list_init(&enb->sctp.write_queue);
}
enb->max_num_of_ostreams = DEFAULT_SCTP_MAX_NUM_OF_OSTREAMS;
enb->ostream_id = 0;
@ -1893,13 +1901,8 @@ mme_enb_t *mme_enb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr)
ogs_list_init(&enb->enb_ue_list);
if (enb->sock_type == SOCK_STREAM) {
enb->poll = ogs_pollset_add(ogs_app()->pollset,
OGS_POLLIN, sock->fd, s1ap_recv_upcall, sock);
ogs_assert(enb->poll);
}
ogs_hash_set(self.enb_addr_hash, enb->addr, sizeof(ogs_sockaddr_t), enb);
ogs_hash_set(self.enb_addr_hash,
enb->sctp.addr, sizeof(ogs_sockaddr_t), enb);
memset(&e, 0, sizeof(e));
e.enb = enb;
@ -1919,7 +1922,7 @@ int mme_enb_remove(mme_enb_t *enb)
mme_event_t e;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_list_remove(&self.enb_list, enb);
@ -1928,15 +1931,11 @@ int mme_enb_remove(mme_enb_t *enb)
ogs_fsm_fini(&enb->sm, &e);
ogs_fsm_delete(&enb->sm);
ogs_hash_set(self.enb_addr_hash, enb->addr, sizeof(ogs_sockaddr_t), NULL);
ogs_hash_set(self.enb_addr_hash,
enb->sctp.addr, sizeof(ogs_sockaddr_t), NULL);
ogs_hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), NULL);
if (enb->sock_type == SOCK_STREAM) {
ogs_pollset_remove(enb->poll);
ogs_sctp_destroy(enb->sock);
}
ogs_free(enb->addr);
ogs_sctp_flush_and_destroy(&enb->sctp);
ogs_pool_free(&mme_enb_pool, enb);

View File

@ -27,6 +27,7 @@
#include "ogs-gtp.h"
#include "ogs-nas-eps.h"
#include "ogs-app.h"
#include "ogs-sctp.h"
/* S1AP */
#include "S1AP_Cause.h"
@ -209,10 +210,7 @@ typedef struct mme_enb_s {
ogs_fsm_t sm; /* A state machine */
uint32_t enb_id; /* eNB_ID received from eNB */
int sock_type; /* SOCK_STREAM or SOCK_SEQPACKET */
ogs_sock_t *sock; /* eNB S1AP Socket */
ogs_sockaddr_t *addr; /* eNB S1AP Address */
ogs_poll_t *poll; /* eNB S1AP Poll */
ogs_sctp_sock_t sctp; /* SCTP socket */
struct {
bool s1_setup_success; /* eNB S1AP Setup complete successfuly */
@ -221,7 +219,6 @@ typedef struct mme_enb_s {
uint16_t max_num_of_ostreams;/* SCTP Max num of outbound streams */
uint16_t ostream_id; /* enb_ostream_id generator */
uint8_t num_of_supported_ta_list;
ogs_eps_tai_t supported_ta_list[OGS_MAX_NUM_OF_TAI*OGS_MAX_NUM_OF_BPLMN];

View File

@ -209,7 +209,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
ogs_min(max_num_of_ostreams, enb->max_num_of_ostreams);
ogs_debug("eNB-S1 SCTP_COMM_UP[%s] Max Num of Outbound Streams[%d]",
OGS_ADDR(enb->addr, buf), enb->max_num_of_ostreams);
OGS_ADDR(enb->sctp.addr, buf), enb->max_num_of_ostreams);
break;

View File

@ -82,7 +82,7 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
long cause = 0;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -112,7 +112,7 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
ogs_assert(Global_ENB_ID);
ogs_s1ap_ENB_ID_to_uint32(&Global_ENB_ID->eNB_ID, &enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->sctp.addr, buf), enb_id);
if (PagingDRX)
ogs_debug(" PagingDRX[%ld]", *PagingDRX);
@ -212,7 +212,7 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message)
enb_ue_t *enb_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -245,7 +245,8 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message)
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
if (!ENB_UE_S1AP_ID) {
ogs_error("No ENB_UE_S1AP_ID");
@ -359,7 +360,7 @@ void s1ap_handle_uplink_nas_transport(
enb_ue_t *enb_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -383,7 +384,8 @@ void s1ap_handle_uplink_nas_transport(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
if (!ENB_UE_S1AP_ID) {
ogs_error("No ENB_UE_S1AP_ID");
@ -426,7 +428,7 @@ void s1ap_handle_ue_capability_info_indication(
enb_ue_t *enb_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -451,7 +453,8 @@ void s1ap_handle_ue_capability_info_indication(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
ogs_assert(ENB_UE_S1AP_ID);
enb_ue = enb_ue_find_by_enb_ue_s1ap_id(enb, *ENB_UE_S1AP_ID);
@ -485,7 +488,7 @@ void s1ap_handle_initial_context_setup_response(
enb_ue_t *enb_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
@ -511,7 +514,8 @@ void s1ap_handle_initial_context_setup_response(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
if (!ENB_UE_S1AP_ID) {
ogs_error("No ENB_UE_S1AP_ID");
@ -622,7 +626,7 @@ void s1ap_handle_initial_context_setup_failure(
enb_ue_t *enb_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
unsuccessfulOutcome = message->choice.unsuccessfulOutcome;
@ -647,7 +651,8 @@ void s1ap_handle_initial_context_setup_failure(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
if (!ENB_UE_S1AP_ID) {
ogs_error("No ENB_UE_S1AP_ID");
@ -709,7 +714,7 @@ void s1ap_handle_ue_context_modification_response(
enb_ue_t *enb_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
@ -731,7 +736,8 @@ void s1ap_handle_ue_context_modification_response(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
if (!ENB_UE_S1AP_ID) {
ogs_error("No ENB_UE_S1AP_ID");
@ -777,7 +783,7 @@ void s1ap_handle_ue_context_modification_failure(
mme_ue_t *mme_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
unsuccessfulOutcome = message->choice.unsuccessfulOutcome;
@ -802,7 +808,8 @@ void s1ap_handle_ue_context_modification_failure(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
if (!ENB_UE_S1AP_ID) {
ogs_error("No ENB_UE_S1AP_ID");
@ -854,7 +861,7 @@ void s1ap_handle_e_rab_setup_response(
mme_ue_t *mme_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
@ -879,7 +886,8 @@ void s1ap_handle_e_rab_setup_response(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
if (!ENB_UE_S1AP_ID) {
ogs_error("No ENB_UE_S1AP_ID");
@ -980,7 +988,7 @@ void s1ap_handle_ue_context_release_request(
enb_ue_t *enb_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -1008,7 +1016,8 @@ void s1ap_handle_ue_context_release_request(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
if (!MME_UE_S1AP_ID) {
ogs_error("No MME_UE_S1AP_ID");
@ -1067,7 +1076,7 @@ void s1ap_handle_ue_context_release_complete(
enb_ue_t *enb_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
@ -1089,7 +1098,8 @@ void s1ap_handle_ue_context_release_complete(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
if (!MME_UE_S1AP_ID) {
ogs_error("No MME_UE_S1AP_ID");
@ -1204,7 +1214,7 @@ void s1ap_handle_path_switch_request(
ogs_pkbuf_t *s1apbuf = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -1241,7 +1251,8 @@ void s1ap_handle_path_switch_request(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
ogs_assert(EUTRAN_CGI);
pLMNidentity = &EUTRAN_CGI->pLMNidentity;
@ -1266,7 +1277,8 @@ void s1ap_handle_path_switch_request(
enb_ue = enb_ue_find_by_mme_ue_s1ap_id(*MME_UE_S1AP_ID);
if (!enb_ue) {
ogs_error("Cannot find UE from sourceMME-UE-S1AP-ID[%d] and eNB[%s:%d]",
(int)*MME_UE_S1AP_ID, OGS_ADDR(enb->addr, buf), enb->enb_id);
(int)*MME_UE_S1AP_ID,
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
s1apbuf = s1ap_build_path_switch_failure(
*ENB_UE_S1AP_ID, *MME_UE_S1AP_ID,
@ -1385,7 +1397,7 @@ void s1ap_handle_enb_configuration_transfer(
S1AP_SONConfigurationTransfer_t *SONConfigurationTransfer = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -1407,7 +1419,8 @@ void s1ap_handle_enb_configuration_transfer(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
if (SONConfigurationTransfer) {
S1AP_TargeteNB_ID_t *targeteNB_ID =
@ -1474,7 +1487,7 @@ void s1ap_handle_handover_required(mme_enb_t *enb, ogs_s1ap_message_t *message)
*Source_ToTarget_TransparentContainer = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -1515,7 +1528,8 @@ void s1ap_handle_handover_required(mme_enb_t *enb, ogs_s1ap_message_t *message)
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
ogs_assert(TargetID);
switch (TargetID->present) {
@ -1590,7 +1604,7 @@ void s1ap_handle_handover_request_ack(
mme_ue_t *mme_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
@ -1620,7 +1634,8 @@ void s1ap_handle_handover_request_ack(
break;
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
ogs_assert(MME_UE_S1AP_ID);
ogs_assert(ENB_UE_S1AP_ID);
@ -1714,7 +1729,7 @@ void s1ap_handle_handover_failure(mme_enb_t *enb, ogs_s1ap_message_t *message)
enb_ue_t *source_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
unsuccessfulOutcome = message->choice.unsuccessfulOutcome;
@ -1737,7 +1752,8 @@ void s1ap_handle_handover_failure(mme_enb_t *enb, ogs_s1ap_message_t *message)
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
ogs_assert(MME_UE_S1AP_ID);
ogs_assert(Cause);
@ -1778,7 +1794,7 @@ void s1ap_handle_handover_cancel(mme_enb_t *enb, ogs_s1ap_message_t *message)
enb_ue_t *target_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -1803,7 +1819,8 @@ void s1ap_handle_handover_cancel(mme_enb_t *enb, ogs_s1ap_message_t *message)
break;
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
ogs_assert(MME_UE_S1AP_ID);
ogs_assert(ENB_UE_S1AP_ID);
@ -1832,7 +1849,7 @@ void s1ap_handle_handover_cancel(mme_enb_t *enb, ogs_s1ap_message_t *message)
ogs_debug("[MME] Handover Cancel : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]",
source_ue->enb_ue_s1ap_id,
OGS_ADDR(enb->addr, buf), enb->enb_id);
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
}
void s1ap_handle_enb_status_transfer(mme_enb_t *enb, ogs_s1ap_message_t *message)
@ -1852,7 +1869,7 @@ void s1ap_handle_enb_status_transfer(mme_enb_t *enb, ogs_s1ap_message_t *message
enb_ue_t *source_ue = NULL, *target_ue = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -1878,7 +1895,8 @@ void s1ap_handle_enb_status_transfer(mme_enb_t *enb, ogs_s1ap_message_t *message
break;
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
ogs_assert(MME_UE_S1AP_ID);
ogs_assert(ENB_UE_S1AP_ID);
@ -1926,7 +1944,7 @@ void s1ap_handle_handover_notification(
mme_bearer_t *bearer = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -1954,7 +1972,8 @@ void s1ap_handle_handover_notification(
break;
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
ogs_assert(EUTRAN_CGI);
pLMNidentity = &EUTRAN_CGI->pLMNidentity;
@ -2050,7 +2069,7 @@ void s1ap_handle_s1_reset(
S1AP_UE_associatedLogicalS1_ConnectionListRes_t *partOfS1_Interface = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
@ -2074,7 +2093,8 @@ void s1ap_handle_s1_reset(
}
}
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
ogs_assert(Cause);
ogs_debug(" Cause[Group:%d Cause:%d]",
@ -2183,7 +2203,7 @@ void s1ap_handle_write_replace_warning_response(
S1AP_WriteReplaceWarningResponse_t *WriteReplaceWarningResponse = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
@ -2194,7 +2214,8 @@ void s1ap_handle_write_replace_warning_response(
ogs_debug("[MME] Write replace warning response");
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
}
@ -2207,7 +2228,7 @@ void s1ap_handle_kill_response(
S1AP_KillResponse_t *KillResponse = NULL;
ogs_assert(enb);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
@ -2218,5 +2239,6 @@ void s1ap_handle_kill_response(
ogs_debug("[MME] Kill response");
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
}

View File

@ -47,40 +47,26 @@ void s1ap_close()
ogs_socknode_remove_all(&mme_self()->s1ap_list6);
}
int s1ap_send(ogs_sock_t *sock, ogs_pkbuf_t *pkbuf,
ogs_sockaddr_t *addr, uint16_t stream_no)
{
int sent;
ogs_assert(sock);
ogs_assert(pkbuf);
sent = ogs_sctp_sendmsg(sock, pkbuf->data, pkbuf->len,
addr, OGS_SCTP_S1AP_PPID, stream_no);
if (sent < 0 || sent != pkbuf->len) {
ogs_error("ogs_sctp_sendmsg(len:%d,ssn:%d) error (%d:%s)",
pkbuf->len, stream_no, errno, strerror(errno));
ogs_pkbuf_free(pkbuf);
return OGS_ERROR;
}
ogs_pkbuf_free(pkbuf);
return OGS_OK;
}
int s1ap_send_to_enb(mme_enb_t *enb, ogs_pkbuf_t *pkbuf, uint16_t stream_no)
{
char buf[OGS_ADDRSTRLEN];
ogs_assert(enb);
ogs_assert(pkbuf);
ogs_assert(enb->sock);
ogs_assert(enb->sctp.sock);
ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->addr, buf), enb->enb_id);
ogs_debug(" IP[%s] ENB_ID[%d]",
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
return s1ap_send(enb->sock, pkbuf,
enb->sock_type == SOCK_STREAM ? NULL : enb->addr,
stream_no);
ogs_sctp_ppid_in_pkbuf(pkbuf) = OGS_SCTP_S1AP_PPID;
ogs_sctp_stream_no_in_pkbuf(pkbuf) = stream_no;
if (enb->sctp.type == SOCK_STREAM) {
ogs_sctp_write_to_buffer(&enb->sctp, pkbuf);
return OGS_OK;
} else {
return ogs_sctp_senddata(enb->sctp.sock, pkbuf, enb->sctp.addr);
}
}
int s1ap_send_to_enb_ue(enb_ue_t *enb_ue, ogs_pkbuf_t *pkbuf)

View File

@ -36,8 +36,6 @@ void s1ap_close(void);
ogs_sock_t *s1ap_server(ogs_socknode_t *node);
void s1ap_recv_upcall(short when, ogs_socket_t fd, void *data);
int s1ap_send(ogs_sock_t *sock,
ogs_pkbuf_t *pkbuf, ogs_sockaddr_t *addr, uint16_t stream_no);
int s1ap_send_to_enb(
mme_enb_t *enb, ogs_pkbuf_t *pkb, uint16_t stream_no);