summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte2010-12-22 19:35:28 +0100
committerAndreas Eversberg2011-02-20 11:30:27 +0100
commitd40eedaf166b92a428c01088ce05079f93d590bf (patch)
tree5dfe12e01c82895f0de71666fa50747f45e98a01
parent[GSM_BS] Added DTMF support. (diff)
downloadlcr-d40eedaf166b92a428c01088ce05079f93d590bf.tar.gz
lcr-d40eedaf166b92a428c01088ce05079f93d590bf.tar.xz
lcr-d40eedaf166b92a428c01088ce05079f93d590bf.zip
Modify GSM BS (OpenBTS) to use unix domain socket based MNCC
Author: Harald Welte <laforge@gnumonks.org>
-rw-r--r--Makefile.am4
-rw-r--r--gsm.cpp2
-rw-r--r--gsm.h12
-rw-r--r--gsm_bs.cpp305
-rw-r--r--main.c4
5 files changed, 169 insertions, 158 deletions
diff --git a/Makefile.am b/Makefile.am
index 622bc06..898c5e0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -64,9 +64,7 @@ if ENABLE_GSM_BS
GSM_INCLUDE += -DWITH_GSM_BS -I./openbsc/include -I./libosmocore/include -I./openbsc
-GSM_SOURCE += gsm_bs.cpp openbsc/src/bsc_init.c openbsc/src/bsc_vty.c openbsc/src/vty_interface_layer3.c openbsc/src/bsc_api.c openbsc/src/bsc_version.c
-
-GSM_LIB += ./openbsc/src/libbsc.a ./openbsc/src/libmsc.a ./openbsc/src/libvty.a -losmovty -losmocore -ldbi -lcrypt
+GSM_SOURCE += gsm_bs.cpp
endif
diff --git a/gsm.cpp b/gsm.cpp
index e7216dd..05ccca7 100644
--- a/gsm.cpp
+++ b/gsm.cpp
@@ -263,7 +263,7 @@ void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned
char msgtext[64];
/* select message and primitive text */
- SCPY(msgtext, get_mncc_name(msg_type));
+ //SCPY(msgtext, get_mncc_name(msg_type));
/* add direction */
if (port) {
diff --git a/gsm.h b/gsm.h
index de4c02b..875752e 100644
--- a/gsm.h
+++ b/gsm.h
@@ -12,9 +12,21 @@ struct gsm_conf {
int reject_cause; /* reject cause for unsubcribed IMSIs */
};
+struct mncc_q_entry {
+ struct mncc_q_entry *next;
+ unsigned int len;
+ char data[0]; /* struct gsm_mncc */
+};
+
struct lcr_gsm {
void *network; /* OpenBSC network handle */
struct gsm_conf conf; /* gsm.conf options */
+ int gsm_sock; /* loopback interface GSM side */
+ int gsm_port; /* loopback interface port number */
+
+ struct lcr_fd mncc_lfd; /* Unix domain socket to OpenBSC MNCC */
+ struct mncc_q_entry *mncc_q_hd;
+ struct mncc_q_entry *mncc_q_tail;
};
extern struct lcr_gsm *gsm;
diff --git a/gsm_bs.cpp b/gsm_bs.cpp
index 584b7e2..710c237 100644
--- a/gsm_bs.cpp
+++ b/gsm_bs.cpp
@@ -16,73 +16,14 @@
#define _GNU_SOURCE
#endif
extern "C" {
+#include <assert.h>
#include <getopt.h>
-#include <openbsc/db.h>
-#include <osmocore/select.h>
-#include <openbsc/debug.h>
-#include <openbsc/e1_input.h>
-#include <osmocore/talloc.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
#include <openbsc/mncc.h>
#include <openbsc/trau_frame.h>
-#include <openbsc/osmo_msc.h>
-//#include <osmocom/vty/command.h>
-struct gsm_network *bsc_gsmnet = 0;
-extern int ipacc_rtp_direct;
-extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *),
- const char *cfg_file);
-extern int bsc_shutdown_net(struct gsm_network *net);
-void talloc_ctx_init(void);
-void on_dso_load_token(void);
-void on_dso_load_rrlp(void);
-void on_dso_load_ho_dec(void);
-int bts_model_unknown_init(void);
-int bts_model_bs11_init(void);
-int bts_model_nanobts_init(void);
-static struct log_target *stderr_target;
-extern const char *openbsc_copyright;
-
-/* timer to store statistics */
-#define DB_SYNC_INTERVAL 60, 0
-static struct timer_list db_sync_timer;
-
-/* FIXME: copied from the include file, because it will con compile with C++ */
-struct vty_app_info {
- const char *name;
- const char *version;
- const char *copyright;
- void *tall_ctx;
- int (*go_parent_cb)(struct vty *vty);
- int (*is_config_node)(struct vty *vty, int node);
-};
-
-extern int bsc_vty_go_parent(struct vty *vty);
-extern int bsc_vty_is_config_node(struct vty *vty, int node);
-static struct vty_app_info vty_info = {
- "OpenBSC",
- PACKAGE_VERSION,
- NULL,
- NULL,
- bsc_vty_go_parent,
- bsc_vty_is_config_node,
-};
-
-void vty_init(struct vty_app_info *app_info);
-int bsc_vty_init(void);
-
-}
-
-/* timer handling */
-static int _db_store_counter(struct counter *counter, void *data)
-{
- return db_store_counter(counter);
-}
-
-static void db_sync_timer_cb(void *data)
-{
- /* store counters to database and re-schedule */
- counters_for_each(_db_store_counter, NULL);
- bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
}
/*
@@ -838,6 +779,7 @@ int Pgsm_bs::message_epoint(unsigned int epoint_id, int message_id, union parame
int gsm_bs_exit(int rc)
{
+#if 0
/* free gsm instance */
if (gsm) {
/* shutdown network */
@@ -848,110 +790,173 @@ int gsm_bs_exit(int rc)
// free((struct gsm_network *)gsm->network); /* TBD */
// }
}
-
+#endif
return(rc);
}
-int gsm_bs_init(void)
+extern "C" {
+
+static int mncc_q_enqueue(struct gsm_mncc *mncc, unsigned int len)
{
- char hlr[128], cfg[128], filename[128];
- mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
- int pcapfd, rc;
-
- vty_info.copyright = openbsc_copyright;
-
- log_init(&log_info);
- tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
- talloc_ctx_init();
- on_dso_load_token();
- on_dso_load_rrlp();
- on_dso_load_ho_dec();
- stderr_target = log_target_create_stderr();
- log_add_target(stderr_target);
-
- bts_model_unknown_init();
- bts_model_bs11_init();
- bts_model_nanobts_init();
-
- /* enable filters */
- log_set_all_filter(stderr_target, 1);
-
- /* Init VTY (need to preceed options) */
- vty_init(&vty_info);
- bsc_vty_init();
-
- /* set debug */
- if (gsm->conf.debug[0])
- log_parse_category_mask(stderr_target, gsm->conf.debug);
-
- /* open pcap file */
- if (gsm->conf.pcapfile[0]) {
- if (gsm->conf.pcapfile[0] == '/')
- SCPY(filename, gsm->conf.pcapfile);
- else
- SPRINT(filename, "%s/%s", CONFIG_DATA, gsm->conf.pcapfile);
- pcapfd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, mode);
- if (pcapfd < 0) {
- PERROR("Failed to open file for pcap\n");
- return gsm_exit(-1);
- }
- e1_set_pcap_fd(pcapfd);
- }
+ struct mncc_q_entry *qe;
- /* use RTP proxy for audio streaming */
- ipacc_rtp_direct = 0;
+ qe = (struct mncc_q_entry *) MALLOC(sizeof(*qe)+sizeof(*mncc)+len);
+ if (!qe)
+ return -ENOMEM;
- /* bootstrap network */
- if (gsm->conf.openbsc_cfg[0] == '/')
- SCPY(cfg, gsm->conf.openbsc_cfg);
- else
- SPRINT(cfg, "%s/%s", CONFIG_DATA, gsm->conf.openbsc_cfg);
- rc = bsc_bootstrap_network(&message_bsc, cfg);
- if (rc < 0) {
- PERROR("Failed to bootstrap GSM network.\n");
- return gsm_exit(-1);
- }
- bsc_api_init(bsc_gsmnet, msc_bsc_api());
- gsm->network = bsc_gsmnet;
-
- /* init database */
- if (gsm->conf.hlr[0] == '/')
- SCPY(hlr, gsm->conf.hlr);
- else
- SPRINT(hlr, "%s/%s", CONFIG_DATA, gsm->conf.hlr);
- if (db_init(hlr)) {
- PERROR("GSM DB: Failed to init database '%s'. Please check the option settings.\n", hlr);
- return gsm_exit(-1);
+ qe->next = NULL;
+ qe->len = len;
+ memcpy(qe->data, mncc, len);
+
+ /* in case of empty list ... */
+ if (!gsm->mncc_q_hd && !gsm->mncc_q_tail) {
+ /* the list head and tail both point to the new qe */
+ gsm->mncc_q_hd = gsm->mncc_q_tail = qe;
+ } else {
+ /* append to tail of list */
+ gsm->mncc_q_tail->next = qe;
}
- printf("DB: Database initialized.\n");
- if (db_prepare()) {
- PERROR("GSM DB: Failed to prepare database.\n");
- return gsm_exit(-1);
+
+ gsm->mncc_lfd.when |= LCR_FD_WRITE;
+
+ return 0;
+}
+
+static struct mncc_q_entry *mncc_q_dequeue(void)
+{
+ struct mncc_q_entry *qe = gsm->mncc_q_hd;
+ if (!qe)
+ return NULL;
+
+ /* dequeue the successfully sent message */
+ gsm->mncc_q_hd = qe->next;
+ if (!qe)
+ return NULL;
+ if (qe == gsm->mncc_q_tail)
+ gsm->mncc_q_tail = NULL;
+
+ return qe;
+}
+
+/* routine called by LCR code if it wants to send a message to OpenBSC */
+int mncc_send(struct gsm_network *instance, int msg_type, void *data)
+{
+ int len = 0;
+
+ /* FIXME: the caller should provide this */
+ switch (msg_type) {
+ case GSM_TCHF_FRAME:
+ len = 33;
+ break;
+ default:
+ len = sizeof(struct gsm_mncc);
+ break;
}
- printf("DB: Database prepared.\n");
+
+ return mncc_q_enqueue((struct gsm_mncc *)data, len);
+}
+
+} // extern "C"
+
+/* close MNCC socket */
+static int mncc_fd_close(struct lcr_fd *lfd)
+{
+ close(lfd->fd);
+ unregister_fd(lfd);
+ lfd->fd = -1;
+
+ /* flush the queue */
+ while (mncc_q_dequeue())
+ ;
+
+ /* FIXME: free all the calls that were running through the MNCC interface */
- /* setup the timer */
- db_sync_timer.cb = db_sync_timer_cb;
- db_sync_timer.data = NULL;
- bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
+ /* FIXME: start a re-connect timer */
generate_dtmf();
return 0;
}
-/*
- * handles bsc select function within LCR's main loop
- */
-int handle_gsm_bs(void)
+/* read from OpenBSC via MNCC socket */
+static int mncc_fd_write(struct lcr_fd *lfd, void *inst, int idx)
{
- int ret1, ret2;
+ struct mncc_q_entry *qe, *qe2;
+ int rc;
- ret1 = bsc_upqueue((struct gsm_network *)gsm->network);
- log_reset_context();
- ret2 = bsc_select_main(1); /* polling */
- if (ret1 || ret2)
- return 1;
+ while (1) {
+ qe = gsm->mncc_q_hd;
+ if (!qe) {
+ lfd->when &= ~LCR_FD_WRITE;
+ break;
+ }
+ rc = write(lfd->fd, qe->data, qe->len);
+ if (rc == 0)
+ return mncc_fd_close(lfd);
+ if (rc < 0)
+ return rc;
+ if (rc < qe->len)
+ return -1;
+ /* dequeue the successfully sent message */
+ qe2 = mncc_q_dequeue();
+ assert(qe == qe2);
+ free(qe);
+ }
return 0;
}
+/* read from OpenBSC via MNCC socket */
+static int mncc_fd_read(struct lcr_fd *lfd, void *inst, int idx)
+{
+ int rc;
+ static char buf[sizeof(struct gsm_mncc)+1024];
+ struct gsm_mncc *mncc_prim = (struct gsm_mncc *) buf;
+
+ memset(buf, 0, sizeof(buf));
+ rc = recv(lfd->fd, buf, sizeof(buf), 0);
+ if (rc == 0)
+ return mncc_fd_close(lfd);
+ if (rc < 0)
+ return rc;
+
+ /* Hand the MNCC message into LCR */
+ return message_bsc(NULL, mncc_prim->msg_type, mncc_prim);
+}
+
+/* file descriptor callback if we can read or write form MNCC socket */
+static int mncc_fd_cb(struct lcr_fd *lfd, unsigned int what, void *instance, int idx)
+{
+ int rc = 0;
+
+ if (what & LCR_FD_READ)
+ rc = mncc_fd_read(lfd, instance, idx);
+ if (rc < 0)
+ return rc;
+
+ if (what & LCR_FD_WRITE)
+ rc = mncc_fd_write(lfd, instance, idx);
+
+ return rc;
+}
+
+int gsm_bs_init(void)
+{
+ struct sockaddr_un sun;
+ int rc;
+
+ rc = socket(PF_UNIX, SOCK_SEQPACKET, 0);
+ if (rc < 0)
+ return rc;
+
+ gsm->mncc_lfd.fd = rc;
+
+ sun.sun_family = AF_UNIX;
+ strcpy(sun.sun_path, "/tmp/bsc_mncc");
+ rc = connect(rc, (struct sockaddr *)&sun, sizeof(sun));
+ if (rc < 0)
+ return rc;
+
+ rc = register_fd(&gsm->mncc_lfd, LCR_FD_READ, &mncc_fd_cb, NULL, 0);
+
+ return rc;
+}
diff --git a/main.c b/main.c
index d22ad68..b9e836c 100644
--- a/main.c
+++ b/main.c
@@ -469,10 +469,6 @@ int main(int argc, char *argv[])
if (options.gsm) {
if (handle_gsm())
all_idle = 0;
-#ifdef WITH_GSM_BS
- if (handle_gsm_bs())
- all_idle = 0;
-#endif
#ifdef WITH_GSM_MS
if (handle_gsm_ms())
all_idle = 0;