forked from acouzens/open5gs
intermediate
This commit is contained in:
parent
03f50ca6a0
commit
02452852be
12
main.c
12
main.c
|
@ -189,6 +189,17 @@ int main(int argc, char *argv[])
|
|||
/* Parent */
|
||||
}
|
||||
|
||||
/* FIXME: Pass built symbol table to HypcerCell module. */
|
||||
{
|
||||
extern int _mme_sm;
|
||||
extern int _ctx;
|
||||
extern int _s1_path;
|
||||
|
||||
d_trace_level(&_mme_sm, 100);
|
||||
d_trace_level(&_ctx, 100);
|
||||
d_trace_level(&_s1_path, 100);
|
||||
}
|
||||
|
||||
signal_init();
|
||||
|
||||
if (cellwire_initialize(config_path) != CORE_OK)
|
||||
|
@ -196,7 +207,6 @@ int main(int argc, char *argv[])
|
|||
d_fatal("CellWire initialization failed. Aborted");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
show_version();
|
||||
d_info("CellWire daemon start");
|
||||
|
|
|
@ -3,14 +3,12 @@
|
|||
noinst_LTLIBRARIES = libcellwire.la
|
||||
|
||||
libcellwire_la_SOURCES = \
|
||||
cellwire.h event.h context.h \
|
||||
s1ap_message.h s1ap_conv.h \
|
||||
sm.h
|
||||
cellwire.h event.h context.h s1ap_message.h s1ap_conv.h s1_path.h \
|
||||
sm.h
|
||||
|
||||
|
||||
nodist_libcellwire_la_SOURCES = \
|
||||
init.c mme_main.c event.c context.c \
|
||||
s1ap_message.c s1ap_conv.c \
|
||||
init.c event.c context.c s1ap_message.c s1ap_conv.c s1_path.c \
|
||||
mme_sm.c
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
|
|
108
src/context.c
108
src/context.c
|
@ -9,8 +9,14 @@
|
|||
|
||||
static mme_ctx_t self;
|
||||
|
||||
pool_declare(enb_pool, enb_ctx_t, SIZE_OF_ENB_POOL);
|
||||
pool_declare(ue_pool, ue_ctx_t, SIZE_OF_UE_POOL);
|
||||
pool_declare(rab_pool, rab_ctx_t, SIZE_OF_RAB_POOL);
|
||||
|
||||
static int g_mme_ctx_initialized = 0;
|
||||
|
||||
static list_t g_enb_list;
|
||||
|
||||
static rwlock_id g_rwlock;
|
||||
static int g_cpath_post_q;
|
||||
|
||||
|
@ -19,12 +25,21 @@ status_t context_init()
|
|||
d_assert(g_mme_ctx_initialized == 0, return CORE_ERROR,
|
||||
"MME context already has been initialized");
|
||||
|
||||
pool_init(&enb_pool, SIZE_OF_ENB_POOL);
|
||||
pool_init(&ue_pool, SIZE_OF_UE_POOL);
|
||||
pool_init(&rab_pool, SIZE_OF_RAB_POOL);
|
||||
|
||||
list_init(&g_enb_list);
|
||||
|
||||
rwlock_create(&g_rwlock);
|
||||
d_assert(g_rwlock, return CORE_ERROR, "RW-lock creation failed");
|
||||
|
||||
/* Initialize MME context */
|
||||
memset(&self, 0, sizeof(mme_ctx_t));
|
||||
|
||||
self.enb_local_addr = inet_addr("127.0.0.1");
|
||||
self.enb_s1_port = S1_SCTP_PORT;
|
||||
|
||||
self.plmn_id.mnc_len = 2;
|
||||
self.plmn_id.mcc = 1; /* 001 */
|
||||
self.plmn_id.mnc = 1; /* 01 */
|
||||
|
@ -50,6 +65,12 @@ status_t context_final()
|
|||
d_assert(g_mme_ctx_initialized == 1, return CORE_ERROR,
|
||||
"HyperCell context already has been finalized");
|
||||
|
||||
enb_ctx_remove_all();
|
||||
|
||||
pool_final(&enb_pool);
|
||||
pool_final(&ue_pool);
|
||||
pool_final(&rab_pool);
|
||||
|
||||
g_mme_ctx_initialized = 0;
|
||||
|
||||
return CORE_OK;
|
||||
|
@ -90,3 +111,90 @@ mme_ctx_t* mme_self()
|
|||
{
|
||||
return &self;
|
||||
}
|
||||
|
||||
enb_ctx_t* enb_ctx_add()
|
||||
{
|
||||
|
||||
enb_ctx_t *enb = NULL;
|
||||
|
||||
/* Allocate new eNB context */
|
||||
pool_alloc_node(&enb_pool, &enb);
|
||||
d_assert(enb, return NULL, "eNB context allocation failed");
|
||||
|
||||
/* Initialize eNB context */
|
||||
memset(enb, 0, sizeof(enb_ctx_t));
|
||||
|
||||
/* Add new eNB context to list */
|
||||
list_append(&g_enb_list, enb);
|
||||
|
||||
return enb;
|
||||
}
|
||||
|
||||
status_t enb_ctx_remove(enb_ctx_t *enb)
|
||||
{
|
||||
d_assert(enb, return CORE_ERROR, "Null param");
|
||||
|
||||
list_remove(&g_enb_list, enb);
|
||||
pool_free_node(&enb_pool, enb);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t enb_ctx_remove_all()
|
||||
{
|
||||
enb_ctx_t *enb = NULL, *next_enb = NULL;
|
||||
|
||||
enb = list_first(&g_enb_list);
|
||||
while (enb)
|
||||
{
|
||||
next_enb = list_next(enb);
|
||||
|
||||
enb_ctx_remove(enb);
|
||||
|
||||
enb = next_enb;
|
||||
}
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
enb_ctx_t* enb_ctx_find_by_ip(c_uint32_t ip)
|
||||
{
|
||||
enb_ctx_t *enb = NULL;
|
||||
|
||||
enb = list_first(&g_enb_list);
|
||||
while (enb)
|
||||
{
|
||||
if (ip == enb->ip)
|
||||
break;
|
||||
|
||||
enb = list_next(enb);
|
||||
}
|
||||
|
||||
return enb;
|
||||
}
|
||||
|
||||
enb_ctx_t* enb_ctx_find_by_id(c_uint32_t id)
|
||||
{
|
||||
enb_ctx_t *enb = NULL;
|
||||
|
||||
enb = list_first(&g_enb_list);
|
||||
while (enb)
|
||||
{
|
||||
if (id == enb->id)
|
||||
break;
|
||||
|
||||
enb = list_next(enb);
|
||||
}
|
||||
|
||||
return enb;
|
||||
}
|
||||
|
||||
enb_ctx_t* enb_ctx_first()
|
||||
{
|
||||
return list_first(&g_enb_list);
|
||||
}
|
||||
|
||||
enb_ctx_t* enb_ctx_next(enb_ctx_t *enb)
|
||||
{
|
||||
return list_next(enb);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include "core_list.h"
|
||||
#include "core_errno.h"
|
||||
#include "core_net.h"
|
||||
|
||||
#include "sm.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -12,6 +15,16 @@ extern "C" {
|
|||
#define GRP_PER_MME 256 /* According to spec it is 65535 */
|
||||
#define CODE_PER_MME 256 /* According to spec it is 256*/
|
||||
|
||||
#define CELL_PER_ENB 8
|
||||
#define UE_PER_ENB 128
|
||||
#define RAB_PER_UE 16
|
||||
|
||||
#define SIZE_OF_ENB_POOL 128
|
||||
#define SIZE_OF_UE_POOL (SIZE_OF_ENB_POOL * UE_PER_ENB)
|
||||
#define SIZE_OF_RAB_POOL (SIZE_OF_UE_POOL * RAB_PER_UE)
|
||||
|
||||
typedef list_t rab_list_t;
|
||||
|
||||
typedef struct _plmn_id_t {
|
||||
c_uint16_t mcc;
|
||||
c_uint16_t mnc;
|
||||
|
@ -31,12 +44,54 @@ typedef struct _served_gummei {
|
|||
/**
|
||||
* This structure represents HypcerCell */
|
||||
typedef struct _mme_ctx_t {
|
||||
net_sock_t *enb_s1_sock;
|
||||
c_uint16_t enb_s1_port;
|
||||
c_uint32_t enb_local_addr; /** Network byte order */
|
||||
|
||||
plmn_id_t plmn_id;
|
||||
c_uint8_t relative_capacity;
|
||||
srvd_gummei_t srvd_gummei;
|
||||
|
||||
c_uint8_t relative_capacity;
|
||||
c_uint16_t tac;
|
||||
} mme_ctx_t;
|
||||
|
||||
/**
|
||||
* This structure represents eNB */
|
||||
typedef struct _enb_ctx_t {
|
||||
lnode_t node; /**< A node of list_t */
|
||||
|
||||
enb_s1_sm_t s1_sm; /**< eNB S1 state machine */
|
||||
|
||||
net_sock_t *s1_sock;
|
||||
|
||||
c_uint32_t ip; /** Network byte order */
|
||||
c_uint32_t id;
|
||||
} enb_ctx_t;
|
||||
|
||||
/**
|
||||
* This structure represents UE-S1 */
|
||||
typedef struct _ue_ctx_t {
|
||||
lnode_t node; /**< A node of list_t */
|
||||
|
||||
c_uint32_t enb_id; /** eNB-UE-S1AP-ID received from eNB */
|
||||
c_uint32_t mme_id; /** MME-UE-S1AP-ID received from MME */
|
||||
|
||||
rab_list_t rab_list;
|
||||
|
||||
enb_ctx_t *enb;
|
||||
mme_ctx_t *mme;
|
||||
} ue_ctx_t;
|
||||
|
||||
/**
|
||||
* This structure represents RAB */
|
||||
typedef struct _rab_ctx_t {
|
||||
lnode_t node; /**< A node of list_t */
|
||||
|
||||
c_uint32_t id;
|
||||
|
||||
ue_ctx_t *ue;
|
||||
} rab_ctx_t;
|
||||
|
||||
CORE_DECLARE(status_t) context_init(void);
|
||||
CORE_DECLARE(status_t) context_final(void);
|
||||
|
||||
|
@ -48,6 +103,14 @@ CORE_DECLARE(void) context_post_cpath(void);
|
|||
CORE_DECLARE(int) context_fetch_cpath(void);
|
||||
|
||||
CORE_DECLARE(mme_ctx_t*) mme_self(void);
|
||||
|
||||
CORE_DECLARE(enb_ctx_t*) enb_ctx_add(void);
|
||||
CORE_DECLARE(status_t) enb_ctx_remove(enb_ctx_t *enb);
|
||||
CORE_DECLARE(status_t) enb_ctx_remove_all(void);
|
||||
CORE_DECLARE(enb_ctx_t*) enb_ctx_find_by_ip(c_uint32_t ip);
|
||||
CORE_DECLARE(enb_ctx_t*) enb_ctx_find_by_id(c_uint32_t id);
|
||||
CORE_DECLARE(enb_ctx_t*) enb_ctx_first(void);
|
||||
CORE_DECLARE(enb_ctx_t*) enb_ctx_next(enb_ctx_t *enb);
|
||||
#define self() mme_self()
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -20,7 +20,7 @@ msgq_id event_create(void)
|
|||
queue_id = msgq_create(EVT_Q_DEPTH, EVENT_SIZE, MSGQ_O_BLOCK);
|
||||
d_assert(queue_id != 0, return CORE_ERROR, "Message queue creation failed");
|
||||
|
||||
return CORE_OK;
|
||||
return queue_id;
|
||||
}
|
||||
|
||||
status_t event_delete(msgq_id queue_id)
|
||||
|
|
101
src/init.c
101
src/init.c
|
@ -10,22 +10,10 @@
|
|||
#include "context.h"
|
||||
#include "event.h"
|
||||
|
||||
#define EVENT_WAIT_TIMEOUT 10000 /* 10 msec */
|
||||
|
||||
static thread_id mme_thread;
|
||||
extern void *THREAD_FUNC mme_main(void *data);
|
||||
|
||||
void threads_start()
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = thread_create(&mme_thread, NULL, mme_main, NULL);
|
||||
d_assert(rv == CORE_OK, return,
|
||||
"MME State machine thread creation failed");
|
||||
}
|
||||
|
||||
void threads_stop()
|
||||
{
|
||||
thread_delete(mme_thread);
|
||||
}
|
||||
static thread_id path_thread;
|
||||
|
||||
status_t cellwire_initialize(char *config_path)
|
||||
{
|
||||
|
@ -44,3 +32,86 @@ void cellwire_terminate(void)
|
|||
{
|
||||
context_final();
|
||||
}
|
||||
|
||||
void *THREAD_FUNC mme_main(void *data)
|
||||
{
|
||||
event_t event;
|
||||
msgq_id queue_id;
|
||||
mme_sm_t mme_sm;
|
||||
c_time_t prev_tm, now_tm;
|
||||
int r;
|
||||
|
||||
memset(&event, 0, sizeof(event_t));
|
||||
|
||||
queue_id = event_create();
|
||||
d_assert(queue_id, return NULL, "MME event queue creation failed");
|
||||
|
||||
fsm_create(&mme_sm.fsm, mme_state_initial, mme_state_final);
|
||||
d_assert(&mme_sm.fsm, return NULL, "MME state machine creation failed");
|
||||
mme_sm.queue_id = queue_id;
|
||||
tm_service_init(&mme_sm.tm_service);
|
||||
|
||||
fsm_init((fsm_t*)&mme_sm, 0);
|
||||
|
||||
prev_tm = time_now();
|
||||
|
||||
while (!thread_should_stop())
|
||||
{
|
||||
r = event_timedrecv(queue_id, &event, EVENT_WAIT_TIMEOUT);
|
||||
|
||||
d_assert(r != CORE_ERROR, continue,
|
||||
"While receiving a event message, error occurs");
|
||||
|
||||
now_tm = time_now();
|
||||
|
||||
/* if the gap is over 10 ms, execute preriodic jobs */
|
||||
if (now_tm - prev_tm > EVENT_WAIT_TIMEOUT)
|
||||
{
|
||||
event_timer_execute(&mme_sm.tm_service);
|
||||
|
||||
prev_tm = now_tm;
|
||||
}
|
||||
|
||||
if (r == CORE_TIMEUP)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fsm_dispatch((fsm_t*)&mme_sm, (fsm_event_t*)&event);
|
||||
}
|
||||
|
||||
fsm_final((fsm_t*)&mme_sm, 0);
|
||||
fsm_clear((fsm_t*)&mme_sm);
|
||||
|
||||
event_delete(queue_id);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *THREAD_FUNC path_main(void *data)
|
||||
{
|
||||
while (!thread_should_stop())
|
||||
{
|
||||
net_fds_read_run(50);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void threads_start()
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = thread_create(&mme_thread, NULL, mme_main, NULL);
|
||||
d_assert(rv == CORE_OK, return,
|
||||
"MME State machine thread creation failed");
|
||||
rv = thread_create(&path_thread, NULL, path_main, NULL);
|
||||
d_assert(rv == CORE_OK, return,
|
||||
"Network PATH thread creation failed");
|
||||
}
|
||||
|
||||
void threads_stop()
|
||||
{
|
||||
thread_delete(mme_thread);
|
||||
thread_delete(path_thread);
|
||||
}
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
/**
|
||||
* @file cp_main.c
|
||||
*/
|
||||
|
||||
/* Server */
|
||||
#include "event.h"
|
||||
#include "sm.h"
|
||||
|
||||
/* Core library */
|
||||
#include "core.h"
|
||||
#define TRACE_MODULE _smmain
|
||||
#include "core_debug.h"
|
||||
#include "core_thread.h"
|
||||
#include "core_msgq.h"
|
||||
|
||||
#include "context.h"
|
||||
|
||||
#define EVENT_WAIT_TIMEOUT 10000 /* 10 msec */
|
||||
|
||||
void *THREAD_FUNC mme_main(void *data)
|
||||
{
|
||||
event_t event;
|
||||
msgq_id queue_id;
|
||||
mme_sm_t mme_sm;
|
||||
c_time_t prev_tm, now_tm;
|
||||
int r;
|
||||
|
||||
memset(&event, 0, sizeof(event_t));
|
||||
|
||||
queue_id = event_create();
|
||||
d_assert(queue_id, return NULL, "MME event queue creation failed");
|
||||
|
||||
fsm_create(&mme_sm.fsm, mme_state_initial, mme_state_final);
|
||||
d_assert(&mme_sm.fsm, return NULL, "MME state machine creation failed");
|
||||
mme_sm.queue_id = queue_id;
|
||||
tm_service_init(&mme_sm.tm_service);
|
||||
|
||||
fsm_init((fsm_t*)&mme_sm, 0);
|
||||
|
||||
prev_tm = time_now();
|
||||
|
||||
while (!thread_should_stop())
|
||||
{
|
||||
r = event_timedrecv(queue_id, &event, EVENT_WAIT_TIMEOUT);
|
||||
|
||||
d_assert(r != CORE_ERROR, continue,
|
||||
"While receiving a event message, error occurs");
|
||||
|
||||
now_tm = time_now();
|
||||
|
||||
/* if the gap is over 10 ms, execute preriodic jobs */
|
||||
if (now_tm - prev_tm > EVENT_WAIT_TIMEOUT)
|
||||
{
|
||||
event_timer_execute(&mme_sm.tm_service);
|
||||
|
||||
prev_tm = now_tm;
|
||||
}
|
||||
|
||||
if (r == CORE_TIMEUP)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fsm_dispatch((fsm_t*)&mme_sm, (fsm_event_t*)&event);
|
||||
}
|
||||
|
||||
fsm_final((fsm_t*)&mme_sm, 0);
|
||||
fsm_clear((fsm_t*)&mme_sm);
|
||||
|
||||
event_delete(queue_id);
|
||||
|
||||
return NULL;
|
||||
}
|
50
src/mme_sm.c
50
src/mme_sm.c
|
@ -1,9 +1,10 @@
|
|||
#define TRACE_MODULE _master_sm
|
||||
#define TRACE_MODULE _mme_sm
|
||||
#include "core_debug.h"
|
||||
|
||||
#include "sm.h"
|
||||
#include "context.h"
|
||||
#include "event.h"
|
||||
#include "s1_path.h"
|
||||
|
||||
void mme_state_initial(mme_sm_t *s, event_t *e)
|
||||
{
|
||||
|
@ -23,22 +24,65 @@ void mme_state_final(mme_sm_t *s, event_t *e)
|
|||
|
||||
void mme_state_operational(mme_sm_t *s, event_t *e)
|
||||
{
|
||||
#if 0
|
||||
status_t rv;
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
#endif
|
||||
|
||||
sm_trace(1, e);
|
||||
|
||||
d_assert(s, return, "Null param");
|
||||
d_assert(s->queue_id, return, "Null param");
|
||||
|
||||
switch (event_get(e))
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
{
|
||||
rv = s1_open(s->queue_id);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("Can't establish S1 path");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FSM_EXIT_SIG:
|
||||
{
|
||||
rv = s1_close();
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("Can't close S1 path");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVT_LO_ENB_S1_CONNREFUSED:
|
||||
{
|
||||
net_sock_t *sock = (net_sock_t *)event_get_param1(e);
|
||||
d_assert(sock, break, "Null param");
|
||||
|
||||
c_uint32_t ip_addr = (c_uint32_t)event_get_param2(e);
|
||||
d_info("Socket[%s] connection refused", INET_NTOP(&ip_addr, buf));
|
||||
|
||||
net_unregister_sock(sock);
|
||||
net_close(sock);
|
||||
|
||||
enb_ctx_t *enb = enb_ctx_find_by_ip(ip_addr);
|
||||
if (enb)
|
||||
{
|
||||
/* Remove eNB S1 state machine if exist */
|
||||
if (FSM_STATE(&enb->s1_sm))
|
||||
{
|
||||
fsm_final((fsm_t*)&enb->s1_sm, 0);
|
||||
fsm_clear((fsm_t*)&enb->s1_sm);
|
||||
}
|
||||
|
||||
enb_ctx_remove(enb);
|
||||
d_info("eNB-S1[%x] connection refused!!!", enb->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("Can't find eNB-S1 for [%s]!!!",
|
||||
INET_NTOP(&ip_addr, buf));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
#define TRACE_MODULE _s1_path
|
||||
|
||||
#include "core.h"
|
||||
#include "core_debug.h"
|
||||
#include "core_net.h"
|
||||
|
||||
#include "event.h"
|
||||
#include "s1_path.h"
|
||||
|
||||
#define MAX_S1_PKBUF_SIZE 8192
|
||||
|
||||
static int _s1_accept_cb(net_sock_t *net_sock, void *data);
|
||||
|
||||
status_t s1_open(msgq_id queue_id)
|
||||
{
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
int rc;
|
||||
|
||||
rc = net_listen_with_addr(&mme_self()->enb_s1_sock,
|
||||
SOCK_STREAM, IPPROTO_SCTP, mme_self()->enb_s1_port,
|
||||
mme_self()->enb_local_addr);
|
||||
if (rc != 0)
|
||||
{
|
||||
d_error("Can't establish S1-ENB(port:%d) path(%d:%s)",
|
||||
mme_self()->enb_s1_port, errno, strerror(errno));
|
||||
mme_self()->enb_s1_sock = NULL;
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
rc = net_register_sock(
|
||||
mme_self()->enb_s1_sock, _s1_accept_cb, (void *)queue_id);
|
||||
if (rc != 0)
|
||||
{
|
||||
d_error("Can't establish S1-ENB path(%d:%s)",
|
||||
errno, strerror(errno));
|
||||
net_close(mme_self()->enb_s1_sock);
|
||||
mme_self()->enb_s1_sock = NULL;
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
d_trace(1, "s1_enb_listen() %s:%d\n",
|
||||
INET_NTOP(&mme_self()->enb_local_addr, buf), mme_self()->enb_s1_port);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t s1_close()
|
||||
{
|
||||
d_assert(mme_self(), return CORE_ERROR, "Null param");
|
||||
d_assert(mme_self()->enb_s1_sock != NULL, return CORE_ERROR,
|
||||
"S1-ENB path already opened");
|
||||
net_unregister_sock(mme_self()->enb_s1_sock);
|
||||
net_close(mme_self()->enb_s1_sock);
|
||||
mme_self()->enb_s1_sock = NULL;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
static int _s1_accept_cb(net_sock_t *net_sock, void *data)
|
||||
{
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
ssize_t r;
|
||||
net_sock_t *remote_sock;
|
||||
msgq_id queue_id = (msgq_id)data;
|
||||
|
||||
d_assert(net_sock, return -1, "Null param");
|
||||
d_assert(queue_id, return -1, "Null param");
|
||||
|
||||
r = net_accept(&remote_sock, net_sock, 0);
|
||||
if (r > 0)
|
||||
{
|
||||
d_trace(1, "eNB-S1 accepted[%s] in s1_path module\n",
|
||||
INET_NTOP(&remote_sock->remote.sin_addr.s_addr, buf));
|
||||
|
||||
event_t e;
|
||||
event_set(&e, EVT_LO_ENB_S1_ACCEPT, (c_uintptr_t)remote_sock);
|
||||
event_send(queue_id, &e);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("net_accept failed(r = %d, errno = %d)", r, errno);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static status_t s1_recv(net_sock_t *net_sock, pkbuf_t *pkb,
|
||||
msgq_id queue_id, event_e event)
|
||||
{
|
||||
event_t e;
|
||||
|
||||
d_assert(net_sock, return CORE_ERROR, "Null param");
|
||||
d_assert(pkb, return CORE_ERROR, "Null param");
|
||||
d_assert(event == EVT_S1_ENB_INF,
|
||||
return CORE_ERROR, "Invalid event = %d", event);
|
||||
d_assert(queue_id, return -1, "Null param");
|
||||
|
||||
d_trace(1, "S1AP_PDU is received from eNB-Inf\n");
|
||||
d_trace_hex(1, pkb->payload, pkb->len);
|
||||
|
||||
event_set(&e, event, 0);
|
||||
event_set_msg(&e, pkb, net_sock->remote.sin_addr.s_addr);
|
||||
|
||||
return event_send(queue_id, &e);
|
||||
}
|
||||
|
||||
int _s1_recv_cb(net_sock_t *net_sock, msgq_id queue_id, event_e event)
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *pkb;
|
||||
ssize_t r;
|
||||
c_uint32_t ip_addr = net_sock->remote.sin_addr.s_addr;
|
||||
|
||||
d_assert(net_sock, return -1, "Null param");
|
||||
d_assert(event, return -1, "Null param");
|
||||
d_assert(queue_id, return -1, "Null param");
|
||||
|
||||
pkb = pkbuf_alloc(0, MAX_S1_PKBUF_SIZE);
|
||||
d_assert(pkb, return -1, "Can't allocate pkbuf");
|
||||
|
||||
r = net_read(net_sock, pkb->payload, pkb->len, 0);
|
||||
if (r == -2)
|
||||
{
|
||||
pkbuf_free(pkb);
|
||||
}
|
||||
else if (r <= 0)
|
||||
{
|
||||
pkbuf_free(pkb);
|
||||
|
||||
if (net_sock->sndrcv_errno == EAGAIN)
|
||||
{
|
||||
d_warn("net_read(event:%d) failed(%d:%s)", event,
|
||||
net_sock->sndrcv_errno, strerror(net_sock->sndrcv_errno));
|
||||
return 0;
|
||||
}
|
||||
else if (net_sock->sndrcv_errno == ECONNREFUSED)
|
||||
{
|
||||
d_warn("net_read(event:%d) failed(%d:%s)", event,
|
||||
net_sock->sndrcv_errno, strerror(net_sock->sndrcv_errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("net_read(event:%d) failed(%d:%s)", event,
|
||||
net_sock->sndrcv_errno, strerror(net_sock->sndrcv_errno));
|
||||
}
|
||||
|
||||
event_t e;
|
||||
|
||||
d_assert(event == EVT_S1_ENB_INF, return -1,
|
||||
"Invalid event = %d", event);
|
||||
event_set(&e, EVT_LO_ENB_S1_CONNREFUSED, (c_uintptr_t)net_sock);
|
||||
event_set_param2(&e, (c_uintptr_t)ip_addr);
|
||||
event_send(queue_id, &e);
|
||||
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pkb->len = r;
|
||||
|
||||
rv = s1_recv(net_sock, pkb, queue_id, event);
|
||||
if (rv == CORE_ERROR)
|
||||
{
|
||||
pkbuf_free(pkb);
|
||||
d_error("s1_recv() failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t s1_send(net_sock_t *s, pkbuf_t *pkb)
|
||||
{
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
|
||||
ssize_t sent;
|
||||
|
||||
d_assert(s, return CORE_ERROR, "Null param");
|
||||
d_assert(pkb, return CORE_ERROR, "Null param");
|
||||
|
||||
sent = net_send(s, pkb->payload, pkb->len);
|
||||
d_trace(1,"Sent %d->%d bytes to [%s:%d]\n",
|
||||
pkb->len, sent, INET_NTOP(&s->remote.sin_addr.s_addr, buf),
|
||||
ntohs(s->remote.sin_port));
|
||||
d_trace_hex(1, pkb->payload, pkb->len);
|
||||
if (sent < 0 || sent != pkb->len)
|
||||
{
|
||||
d_error("net_send error (%d:%s)",
|
||||
s->sndrcv_errno, strerror(s->sndrcv_errno));
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t s1_send_to_enb(enb_ctx_t *enb, pkbuf_t *pkb)
|
||||
{
|
||||
d_assert(enb, return CORE_ERROR, "Null param");
|
||||
d_assert(pkb, return CORE_ERROR, "Null param");
|
||||
d_assert(enb->s1_sock, return CORE_ERROR, "No S1 path with ENB");
|
||||
|
||||
return s1_send(enb->s1_sock, pkb);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef __S1_PATH_H__
|
||||
#define __S1_PATH_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_pkbuf.h"
|
||||
#include "core_msgq.h"
|
||||
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
CORE_DECLARE(status_t) s1_open(msgq_id queue_id);
|
||||
CORE_DECLARE(status_t) s1_close();
|
||||
|
||||
CORE_DECLARE(status_t) s1_send(net_sock_t *s, pkbuf_t *pkb);
|
||||
CORE_DECLARE(status_t) s1_send_to_enb(enb_ctx_t *enb, pkbuf_t *pkb);
|
||||
|
||||
int _s1_recv_cb(net_sock_t *net_sock, msgq_id queue_id, event_e event);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* !__S1_PATH_H__ */
|
Loading…
Reference in New Issue