forked from retronetworking/osmo-v5
Working on main.c
This commit is contained in:
parent
36dc03731a
commit
9c0893403d
311
src/main.c
311
src/main.c
|
@ -27,7 +27,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <osmocom/core/msgb.h>
|
#include <osmocom/core/msgb.h>
|
||||||
#include <osmocom/abis/e1_input.h>
|
|
||||||
|
|
||||||
#include <osmocom/core/application.h>
|
#include <osmocom/core/application.h>
|
||||||
#include <osmocom/core/msgb.h>
|
#include <osmocom/core/msgb.h>
|
||||||
|
@ -36,8 +35,6 @@
|
||||||
#include <osmocom/core/stats.h>
|
#include <osmocom/core/stats.h>
|
||||||
#include <osmocom/core/rate_ctr.h>
|
#include <osmocom/core/rate_ctr.h>
|
||||||
#include <osmocom/core/socket.h>
|
#include <osmocom/core/socket.h>
|
||||||
#include <osmocom/core/gsmtap.h>
|
|
||||||
#include <osmocom/core/gsmtap_util.h>
|
|
||||||
|
|
||||||
#include <osmocom/ctrl/control_vty.h>
|
#include <osmocom/ctrl/control_vty.h>
|
||||||
|
|
||||||
|
@ -49,222 +46,31 @@
|
||||||
#include <osmocom/vty/misc.h>
|
#include <osmocom/vty/misc.h>
|
||||||
#include <osmocom/vty/cpu_sched_vty.h>
|
#include <osmocom/vty/cpu_sched_vty.h>
|
||||||
|
|
||||||
|
#include <osmocom/abis/e1_input.h>
|
||||||
|
|
||||||
#include <osmocom/abis/abis.h>
|
#include <osmocom/abis/abis.h>
|
||||||
|
|
||||||
#include "v5x_internal.h"
|
#include "v5x_internal.h"
|
||||||
#include "v5x_protocol.h"
|
#include "v5x_protocol.h"
|
||||||
|
#include "layer1.h"
|
||||||
|
#include "v5x_l1_fsm.h"
|
||||||
|
#include "lapv5.h"
|
||||||
#include "v5x_le_ctrl_fsm.h"
|
#include "v5x_le_ctrl_fsm.h"
|
||||||
#include "v5x_le_port_fsm.h"
|
#include "v5x_le_port_fsm.h"
|
||||||
#include "v5x_le_pstn_fsm.h"
|
#include "v5x_le_pstn_fsm.h"
|
||||||
|
#include "v52_le_lcp_fsm.h"
|
||||||
|
#include "v52_le_bcc_fsm.h"
|
||||||
|
#include "v52_le_pp_fsm.h"
|
||||||
#include "v5x_le_management.h"
|
#include "v5x_le_management.h"
|
||||||
#include "v5x_le_provisioning.h"
|
#include "v5le_vty.h"
|
||||||
#include "v5x_vty.h"
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
|
||||||
/* can be changed once libosmocore 1.4.0 is released */
|
|
||||||
#ifndef OSMO_CTRL_PORT_MGW
|
|
||||||
#define OSMO_CTRL_PORT_MGW 4267
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* only temporarily until this is in libosmocore gsmtap.h */
|
|
||||||
#ifndef GSMTAP_E1T1_V5EF
|
|
||||||
#define GSMTAP_E1T1_V5EF 0x06
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *tall_v5le_ctx = NULL;
|
void *tall_v5le_ctx = NULL;
|
||||||
struct v5x_instance *v5i = NULL;
|
struct v5x_instance *v5i = NULL;
|
||||||
static struct gsmtap_inst *g_gti;
|
|
||||||
|
|
||||||
struct v5le_config {
|
|
||||||
};
|
|
||||||
|
|
||||||
struct v5le_config *v5le_config_alloc(void *ctx)
|
|
||||||
{
|
|
||||||
struct v5le_config *cfg = talloc_zero(ctx, struct v5le_config);
|
|
||||||
OSMO_ASSERT(cfg);
|
|
||||||
|
|
||||||
return cfg;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int v5le_rx_sign(struct msgb *msg)
|
|
||||||
{
|
|
||||||
LOGP(DLMI, LOGL_NOTICE, "Rx: %s\n", msgb_hexdump(msg));
|
|
||||||
|
|
||||||
msgb_free(msg);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct e1inp_line_ops v5le_e1_line_ops = {
|
|
||||||
.sign_link_up = NULL,
|
|
||||||
.sign_link_down = NULL,
|
|
||||||
.sign_link = v5le_rx_sign,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* data L1 -> L2 */
|
|
||||||
static void hdlc_rx_cb(struct e1inp_ts *ts, struct msgb *msg)
|
|
||||||
{
|
|
||||||
#warning HACKING
|
|
||||||
if (llist_empty(&v5i->interfaces)) {
|
|
||||||
msgb_free(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct v5x_interface *v5if = (struct v5x_interface *)v5i->interfaces.next;
|
|
||||||
|
|
||||||
LOGP(DLINP, LOGL_DEBUG, "L1->L2: %s\n", msgb_hexdump(msg));
|
|
||||||
|
|
||||||
/* send V5 data via gsmtap so wireshark can receive + decode it */
|
|
||||||
gsmtap_send_ex(g_gti, GSMTAP_TYPE_E1T1, 0, ts->num, GSMTAP_E1T1_V5EF,
|
|
||||||
0, 0, 0, 0, msgb_data(msg), msgb_length(msg));
|
|
||||||
|
|
||||||
lapv5ef_rx(v5if->primary_link, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void raw_rx_cb(struct e1inp_ts *ts, struct msgb *msg)
|
|
||||||
{
|
|
||||||
#warning HACKING
|
|
||||||
if (llist_empty(&v5i->interfaces)) {
|
|
||||||
msgb_free(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct v5x_interface *v5if = (struct v5x_interface *)v5i->interfaces.next;
|
|
||||||
struct v5x_user_port *v5up = v5if->links[0].ts[ts->num].v5up;
|
|
||||||
|
|
||||||
/* not used by any user port */
|
|
||||||
if (!v5up) {
|
|
||||||
msgb_free(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v5up->ts_nr[0] == ts->num && v5up->ts_activated[0])
|
|
||||||
ph_socket_tx_msg(&v5up->ph_socket, 1, PH_PRIM_DATA_IND, msg->data, msg->len);
|
|
||||||
if (v5up->ts_nr[1] == ts->num && v5up->ts_activated[1])
|
|
||||||
ph_socket_tx_msg(&v5up->ph_socket, 2, PH_PRIM_DATA_IND, msg->data, msg->len);
|
|
||||||
msgb_free(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* l2 -> L1 */
|
|
||||||
int ph_data_req(struct msgb *msg, void *cbdata)
|
|
||||||
{
|
|
||||||
msg->l2h = msgb_push(msg, 2);
|
|
||||||
msg->l2h[0] = msg->l2h[2] & 0xfd;
|
|
||||||
msg->l2h[1] = msg->l2h[3];
|
|
||||||
LOGP(DLINP, LOGL_DEBUG, "L2->L1: %s\n", msgb_hexdump(msg));
|
|
||||||
|
|
||||||
#warning hacking
|
|
||||||
struct e1inp_line *e1_line = e1inp_line_find(0);
|
|
||||||
struct e1inp_ts *ts = &e1_line->ts[16-1];
|
|
||||||
|
|
||||||
/* send V5 data via gsmtap so wireshark can receive + decode it */
|
|
||||||
gsmtap_send_ex(g_gti, GSMTAP_TYPE_E1T1, GSMTAP_ARFCN_F_UPLINK, ts->num, GSMTAP_E1T1_V5EF,
|
|
||||||
0, 0, 0, 0, msgb_data(msg), msgb_length(msg));
|
|
||||||
|
|
||||||
return e1inp_ts_send_hdlc(ts, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#warning hacking
|
|
||||||
int ph_data_req_hack(struct msgb *msg)
|
|
||||||
{
|
|
||||||
LOGP(DLINP, LOGL_DEBUG, "L2->L1: %s\n", msgb_hexdump(msg));
|
|
||||||
|
|
||||||
#warning hacking
|
|
||||||
struct e1inp_line *e1_line = e1inp_line_find(0);
|
|
||||||
struct e1inp_ts *ts = &e1_line->ts[16-1];
|
|
||||||
|
|
||||||
/* send V5 data via gsmtap so wireshark can receive + decode it */
|
|
||||||
gsmtap_send_ex(g_gti, GSMTAP_TYPE_E1T1, GSMTAP_ARFCN_F_UPLINK, ts->num, GSMTAP_E1T1_V5EF,
|
|
||||||
0, 0, 0, 0, msgb_data(msg), msgb_length(msg));
|
|
||||||
|
|
||||||
return e1inp_ts_send_hdlc(ts, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#warning hacking
|
|
||||||
int ph_data_req_raw(struct msgb *msg, int ts_nr)
|
|
||||||
{
|
|
||||||
#warning hacking
|
|
||||||
struct e1inp_line *e1_line = e1inp_line_find(0);
|
|
||||||
struct e1inp_ts *ts = &e1_line->ts[ts_nr-1];
|
|
||||||
|
|
||||||
return e1inp_ts_send_raw(ts, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#warning hacking
|
|
||||||
void ph_socket_rx_cb(ph_socket_t *s, int channel, uint8_t prim, uint8_t *data, int length)
|
|
||||||
{
|
|
||||||
struct v5x_user_port *v5up = s->priv;
|
|
||||||
|
|
||||||
switch (prim) {
|
|
||||||
case PH_PRIM_CTRL_REQ:
|
|
||||||
/* deactivate channels, if active */
|
|
||||||
if ((channel == 0 || channel == 3) && length && *data == PH_CTRL_BLOCK) {
|
|
||||||
v5up->ts_activated[0] = 0;
|
|
||||||
v5up->ts_activated[1] = 0;
|
|
||||||
}
|
|
||||||
v5x_mph_rcv_le(v5up, prim, data, length);
|
|
||||||
break;
|
|
||||||
case PH_PRIM_ACT_REQ:
|
|
||||||
if (channel == 1 || channel == 2) {
|
|
||||||
v5up->ts_activated[channel - 1] = 1;
|
|
||||||
ph_socket_tx_msg(s, channel, PH_PRIM_ACT_IND, NULL, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
v5x_mph_rcv_le(v5up, prim, data, length);
|
|
||||||
break;
|
|
||||||
case PH_PRIM_DACT_REQ:
|
|
||||||
if (channel == 1 || channel == 2) {
|
|
||||||
v5up->ts_activated[channel - 1] = 0;
|
|
||||||
ph_socket_tx_msg(s, channel, PH_PRIM_DACT_IND, NULL, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
v5x_mph_rcv_le(v5up, prim, data, length);
|
|
||||||
break;
|
|
||||||
case PH_PRIM_DATA_REQ:
|
|
||||||
if (v5up->type == V5X_USER_TYPE_PSTN && channel == 0) {
|
|
||||||
struct msgb *msg = msgb_alloc_headroom(length + 32, 32, "V5 PSTN MSG");
|
|
||||||
memcpy(msgb_put(msg, length), data, length);
|
|
||||||
v5x_nat_rcv_fe(v5up, msg);
|
|
||||||
} else if (v5up->type == V5X_USER_TYPE_ISDN && channel == 3) {
|
|
||||||
struct msgb *msg = msgb_alloc_headroom(length + 32, 32, "V5 EF MSG");
|
|
||||||
memcpy(msgb_put(msg, length), data, length);
|
|
||||||
lapv5ef_tx(v5up, msg);
|
|
||||||
} else if ((channel == 1 || channel == 2) && v5up->ts_nr[channel - 1]) {
|
|
||||||
struct msgb *msg = msgb_alloc_headroom(length + 32, 32, "B MSG");
|
|
||||||
memcpy(msgb_put(msg, length), data, length);
|
|
||||||
ph_data_req_raw(msg, v5up->ts_nr[channel - 1]);
|
|
||||||
}
|
|
||||||
/* always confirm */
|
|
||||||
ph_socket_tx_msg(s, channel, PH_PRIM_DATA_CNF, NULL, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int e1_init(void)
|
|
||||||
{
|
|
||||||
int line_nr = 1, ts;
|
|
||||||
struct e1inp_line *e1_line;
|
|
||||||
|
|
||||||
e1_line = e1inp_line_find(0);
|
|
||||||
OSMO_ASSERT(e1_line);
|
|
||||||
|
|
||||||
e1inp_line_bind_ops(e1_line, &v5le_e1_line_ops);
|
|
||||||
|
|
||||||
for (ts = 1; ts <= 31; ts++) {
|
|
||||||
struct e1inp_ts *e1_ts = &e1_line->ts[ts-1];
|
|
||||||
if (ts == 16) { // FIXME: make this depending on c_channel
|
|
||||||
//e1inp_ts_config_sign(e1_ts, e1_line);
|
|
||||||
//e1inp_sign_link_create(e1_ts, E1INP_SIGN_NONE, NULL, 115/*TEI*/, 0/*SAPI*/);
|
|
||||||
e1inp_ts_config_hdlc(e1_ts, e1_line, hdlc_rx_cb);
|
|
||||||
} else
|
|
||||||
e1inp_ts_config_raw(e1_ts, e1_line, raw_rx_cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
return e1inp_line_update(e1_line);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct v5le_config *g_cfg;
|
|
||||||
static int daemonize = 0;
|
static int daemonize = 0;
|
||||||
|
|
||||||
const char *v5le_copyright =
|
const char *v5le_copyright =
|
||||||
|
@ -367,9 +173,22 @@ static void handle_options(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int quit = 0;
|
||||||
|
|
||||||
|
static void sighandler(int sigset)
|
||||||
|
{
|
||||||
|
if (sigset == SIGHUP)
|
||||||
|
return;
|
||||||
|
if (sigset == SIGPIPE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fprintf(stderr, "Signal received: %d\n", sigset);
|
||||||
|
|
||||||
|
quit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
unsigned int flags;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
tall_v5le_ctx = talloc_named_const(NULL, 1, "v5le");
|
tall_v5le_ctx = talloc_named_const(NULL, 1, "v5le");
|
||||||
|
@ -381,18 +200,14 @@ int main(int argc, char **argv)
|
||||||
osmo_init_logging2(tall_v5le_ctx, &log_info);
|
osmo_init_logging2(tall_v5le_ctx, &log_info);
|
||||||
libosmo_abis_init(tall_v5le_ctx);
|
libosmo_abis_init(tall_v5le_ctx);
|
||||||
|
|
||||||
g_cfg = v5le_config_alloc(tall_v5le_ctx);
|
|
||||||
if (!g_cfg)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
vty_info.copyright = v5le_copyright;
|
vty_info.copyright = v5le_copyright;
|
||||||
|
|
||||||
vty_init(&vty_info);
|
vty_init(&vty_info);
|
||||||
logging_vty_add_cmds();
|
logging_vty_add_cmds();
|
||||||
osmo_talloc_vty_add_cmds();
|
osmo_talloc_vty_add_cmds();
|
||||||
osmo_stats_vty_add_cmds();
|
osmo_stats_vty_add_cmds();
|
||||||
v5x_vty_init();
|
v5le_vty_init();
|
||||||
ctrl_vty_init(g_cfg);
|
ctrl_vty_init(tall_v5le_ctx);
|
||||||
e1inp_vty_init();
|
e1inp_vty_init();
|
||||||
osmo_cpu_sched_vty_init(tall_v5le_ctx);
|
osmo_cpu_sched_vty_init(tall_v5le_ctx);
|
||||||
|
|
||||||
|
@ -402,10 +217,13 @@ int main(int argc, char **argv)
|
||||||
osmo_stats_init(tall_v5le_ctx);
|
osmo_stats_init(tall_v5le_ctx);
|
||||||
|
|
||||||
/* global inits of protocols */
|
/* global inits of protocols */
|
||||||
|
v5x_l1_init();
|
||||||
v5x_le_ctrl_init();
|
v5x_le_ctrl_init();
|
||||||
v5x_le_port_init();
|
v5x_le_port_init();
|
||||||
v5x_le_pstn_init();
|
v5x_le_pstn_init();
|
||||||
v5x_le_provisioning_init();
|
v52_le_lcp_init();
|
||||||
|
v52_le_bcc_init();
|
||||||
|
v52_le_pp_init();
|
||||||
v5x_le_mgmt_init();
|
v5x_le_mgmt_init();
|
||||||
|
|
||||||
/* create v5x instance */
|
/* create v5x instance */
|
||||||
|
@ -419,10 +237,6 @@ int main(int argc, char **argv)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_gti = gsmtap_source_init("224.0.0.1", GSMTAP_UDP_PORT, 0);
|
|
||||||
OSMO_ASSERT(g_gti);
|
|
||||||
gsmtap_source_add_sink(g_gti);
|
|
||||||
|
|
||||||
rc = e1_init();
|
rc = e1_init();
|
||||||
OSMO_ASSERT(rc == 0);
|
OSMO_ASSERT(rc == 0);
|
||||||
|
|
||||||
|
@ -432,46 +246,27 @@ int main(int argc, char **argv)
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
#if 0
|
/* start DL */
|
||||||
cfg->ctrl = v5le_ctrl_interface_setup(cfg, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_MGW);
|
if (!llist_empty(&v5i->interfaces)) {
|
||||||
if (!cfg->ctrl) {
|
struct v5x_interface *v5if;
|
||||||
fprintf(stderr, "Failed to init the control interface on %s:%u. Exiting\n",
|
v5if = (struct v5x_interface *)v5i->interfaces.next;
|
||||||
ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_MGW);
|
if (v5if->control.li)
|
||||||
|
lapv5_dl_est_req(v5if->control.li, V5X_DLADDR_CTRL);
|
||||||
|
if (v5if->pstn.li)
|
||||||
|
lapv5_dl_est_req(v5if->pstn.li, V5X_DLADDR_PSTN);
|
||||||
|
if (v5if->lcp.li)
|
||||||
|
lapv5_dl_est_req(v5if->lcp.li, V52_DLADDR_LCP);
|
||||||
|
if (v5if->bcc.li)
|
||||||
|
lapv5_dl_est_req(v5if->bcc.li, V52_DLADDR_BCC);
|
||||||
|
if (v5if->protection.li[0])
|
||||||
|
lapv5_dl_est_req(v5if->protection.li[0], V52_DLADDR_PROTECTION);
|
||||||
|
if (v5if->protection.li[1])
|
||||||
|
lapv5_dl_est_req(v5if->protection.li[1], V52_DLADDR_PROTECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the reset callback function. This functions is called when the
|
|
||||||
* mgcp-command "RSIP" (Reset in Progress) is received */
|
|
||||||
cfg->reset_cb = mgcp_rsip_cb;
|
|
||||||
|
|
||||||
/* we need to bind a socket */
|
|
||||||
flags = OSMO_SOCK_F_BIND;
|
|
||||||
if (strlen(cfg->call_agent_addr))
|
|
||||||
flags |= OSMO_SOCK_F_CONNECT;
|
|
||||||
|
|
||||||
rc = osmo_sock_init2_ofd(&cfg->gw_fd.bfd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
|
|
||||||
cfg->source_addr, cfg->source_port,
|
|
||||||
cfg->call_agent_addr, strlen(cfg->call_agent_addr) ? 2727 : 0, flags);
|
|
||||||
if (rc < 0) {
|
|
||||||
perror("Gateway failed to bind");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg->gw_fd.bfd.cb = read_call_agent;
|
|
||||||
cfg->gw_fd.bfd.data = msgb_alloc(4096, "mgcp-msg");
|
|
||||||
if (!cfg->gw_fd.bfd.data) {
|
|
||||||
fprintf(stderr, "Gateway memory error.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGP(DLMGCP, LOGL_NOTICE, "Configured for MGCP, listen on %s:%u\n",
|
|
||||||
cfg->source_addr, cfg->source_port);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* initialisation */
|
/* initialisation */
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (daemonize) {
|
if (daemonize) {
|
||||||
rc = osmo_daemonize();
|
rc = osmo_daemonize();
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
@ -480,11 +275,25 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* catch signals */
|
||||||
|
signal(SIGINT, sighandler);
|
||||||
|
signal(SIGHUP, sighandler);
|
||||||
|
signal(SIGTERM, sighandler);
|
||||||
|
signal(SIGPIPE, sighandler);
|
||||||
|
|
||||||
/* main loop */
|
/* main loop */
|
||||||
while (1) {
|
while (!quit) {
|
||||||
osmo_select_main(0);
|
osmo_select_main(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reset signals */
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
signal(SIGHUP, SIG_DFL);
|
||||||
|
signal(SIGTERM, SIG_DFL);
|
||||||
|
signal(SIGPIPE, SIG_DFL);
|
||||||
|
|
||||||
|
/* destroy the universe */
|
||||||
|
v5x_instance_free(v5i);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue