aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-05-01 16:48:27 +0200
committerHarald Welte <laforge@gnumonks.org>2010-05-04 07:20:43 +0200
commit288be16587e83332e51c8ab1c876c235391c5655 (patch)
tree3eb26d769377da53a50c2a9d871580e73451427e /openbsc/src
parenta67cbd6f061e28ca0e4f6f10cf481b6685d84613 (diff)
[gprs] Build the SGSN stand-alone and not as part of bsc_hack
Instead of continuing to add more and more functionality to the bsc_hack binary, we should have the new SGSN code run as a separate executable. After this commit we now build a 'osmo_sgsn' executable, using its own osmo_sgsn.cfg config file. However, the SGSN is not yet functional, mainly due to the fact that the BSSGP and GMM code are written with the assumption that there is a msgb->trx->bts and the according 'sturct gsm_bts' data model around - which clearly is no longer the case outside of bsc_hack.
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/Makefile.am12
-rw-r--r--openbsc/src/gb_proxy_main.c2
-rw-r--r--openbsc/src/gprs_bssgp.c28
-rw-r--r--openbsc/src/gprs_sgsn.c32
-rw-r--r--openbsc/src/gsm_04_08_gprs.c8
-rw-r--r--openbsc/src/osmo_gbproxy.cfg13
-rw-r--r--openbsc/src/osmo_sgsn.cfg9
-rw-r--r--openbsc/src/sgsn_main.c141
-rw-r--r--openbsc/src/sgsn_vty.c146
9 files changed, 345 insertions, 46 deletions
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index 6e4e506ff..18245ed5e 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -3,7 +3,7 @@ AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS)
AM_LDFLAGS = $(LIBOSMOCORE_LIBS)
sbin_PROGRAMS = bsc_hack bs11_config ipaccess-find ipaccess-config \
- isdnsync bsc_mgcp ipaccess-proxy osmo-gb_proxy
+ isdnsync bsc_mgcp ipaccess-proxy osmo-gbproxy osmo-sgsn
noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libsccp.a libsgsn.a
noinst_HEADERS = vty/cardshell.h
@@ -33,7 +33,7 @@ libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c \
libsccp_a_SOURCES = sccp/sccp.c
bsc_hack_SOURCES = bsc_hack.c bsc_init.c vty_interface.c vty_interface_layer3.c
-bsc_hack_LDADD = libmsc.a libbsc.a libmsc.a libsgsn.a libvty.a -ldl -ldbi $(LIBCRYPT)
+bsc_hack_LDADD = libmsc.a libbsc.a libmsc.a libvty.a -ldl -ldbi $(LIBCRYPT)
bs11_config_SOURCES = bs11_config.c abis_nm.c gsm_data.c debug.c \
rs232.c bts_siemens_bs11.c
@@ -51,6 +51,10 @@ bsc_mgcp_LDADD = libvty.a
ipaccess_proxy_SOURCES = ipaccess/ipaccess-proxy.c debug.c
-osmo_gb_proxy_SOURCES = gb_proxy.c gb_proxy_main.c gb_proxy_vty.c \
+osmo_gbproxy_SOURCES = gb_proxy.c gb_proxy_main.c gb_proxy_vty.c \
gprs_ns.c socket.c debug.c
-osmo_gb_proxy_LDADD = libvty.a
+osmo_gbproxy_LDADD = libvty.a
+
+osmo_sgsn_SOURCES = sgsn_main.c sgsn_vty.c \
+ socket.c debug.c
+osmo_sgsn_LDADD = libvty.a libsgsn.a
diff --git a/openbsc/src/gb_proxy_main.c b/openbsc/src/gb_proxy_main.c
index 8f0306091..fe72e0214 100644
--- a/openbsc/src/gb_proxy_main.c
+++ b/openbsc/src/gb_proxy_main.c
@@ -64,7 +64,7 @@ const char *openbsc_copyright =
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n";
-static char *config_file = "gb_proxy.cfg";
+static char *config_file = "osmo_gbproxy.cfg";
static struct gbproxy_config gbcfg;
/* Pointer to the SGSN peer */
diff --git a/openbsc/src/gprs_bssgp.c b/openbsc/src/gprs_bssgp.c
index a2181b124..ab6d1a098 100644
--- a/openbsc/src/gprs_bssgp.c
+++ b/openbsc/src/gprs_bssgp.c
@@ -138,6 +138,25 @@ int bssgp_tx_status(u_int8_t cause, u_int16_t *bvci, struct msgb *orig_msg)
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
+/* Chapter 8.4 BVC-Reset Procedure */
+static int bssgp_rx_bvc_reset(struct msgb *msg, struct tlv_parsed *tp,
+ uint16_t ns_bvci)
+{
+ uint8_t bvci;
+ int rc;
+
+ bvci = ntohs(*(u_int16_t *)TLVP_VAL(tp, BSSGP_IE_BVCI));
+ DEBUGPC(DGPRS, "BVCI=%u, cause=%s\n", bvci,
+ bssgp_cause_str(*TLVP_VAL(tp, BSSGP_IE_CAUSE)));
+
+ /* When we receive a BVC-RESET PDU (at least of a PTP BVCI), the BSS
+ * informs us about its RAC + Cell ID, so we can create a mapping */
+
+ rc = bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_RESET_ACK,
+ msgb_nsei(msg), bvci, ns_bvci);
+ return 0;
+}
+
/* Uplink unit-data */
static int bssgp_rx_ul_ud(struct msgb *msg, u_int16_t bvci)
{
@@ -157,10 +176,12 @@ static int bssgp_rx_ul_ud(struct msgb *msg, u_int16_t bvci)
!TLVP_PRESENT(&tp, BSSGP_IE_LLC_PDU))
return -EIO;
+#if 0 //FIXME
/* Determine the BTS based on the Cell ID */
bts = gsm48_bts_by_ra_id(bsc_gsmnet,
TLVP_VAL(&tp, BSSGP_IE_CELL_ID),
TLVP_LEN(&tp, BSSGP_IE_CELL_ID));
+#endif
if (bts)
msg->trx = bts->c0;
@@ -229,6 +250,7 @@ static int bssgp_rx_fc_bvc(struct msgb *msg, struct tlv_parsed *tp,
return bssgp_tx_fc_bvc_ack(msgb_nsei(msg), *TLVP_VAL(tp, BSSGP_IE_TAG),
ns_bvci);
}
+
/* We expect msg->l3h to point to the BSSGP header */
int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t ns_bvci)
{
@@ -311,11 +333,7 @@ int gprs_bssgp_rcvmsg(struct msgb *msg, u_int16_t ns_bvci)
if (!TLVP_PRESENT(&tp, BSSGP_IE_BVCI) ||
!TLVP_PRESENT(&tp, BSSGP_IE_CAUSE))
goto err_mand_ie;
- bvci = ntohs(*(u_int16_t *)TLVP_VAL(&tp, BSSGP_IE_BVCI));
- DEBUGPC(DGPRS, "BVCI=%u, cause=%s\n", bvci,
- bssgp_cause_str(*TLVP_VAL(&tp, BSSGP_IE_CAUSE)));
- rc = bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_RESET_ACK,
- msgb_nsei(msg), bvci, ns_bvci);
+ rc = bssgp_rx_bvc_reset(msg, &tp, ns_bvci);
break;
case BSSGP_PDUT_STATUS:
/* Some exception has occurred */
diff --git a/openbsc/src/gprs_sgsn.c b/openbsc/src/gprs_sgsn.c
index 3f7f61e20..9844f8808 100644
--- a/openbsc/src/gprs_sgsn.c
+++ b/openbsc/src/gprs_sgsn.c
@@ -94,35 +94,3 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(u_int32_t tlli,
return ctx;
}
-
-/* call-back function for the NS protocol */
-static int gprs_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
- struct msgb *msg, u_int16_t bvci)
-{
- int rc = 0;
-
- switch (event) {
- case GPRS_NS_EVT_UNIT_DATA:
- /* hand the message into the BSSGP implementation */
- rc = gprs_bssgp_rcvmsg(msg, bvci);
- break;
- default:
- LOGP(DGPRS, LOGL_ERROR, "SGSN: Unknown event %u from NS\n", event);
- if (msg)
- talloc_free(msg);
- rc = -EIO;
- break;
- }
- return rc;
-}
-
-int sgsn_init(void)
-{
- struct gprs_ns_inst *nsi;
-
- nsi = gprs_ns_instantiate(&gprs_ns_cb);
- if (!nsi)
- return -EIO;
-
- return nsip_listen(nsi, 23000);
-}
diff --git a/openbsc/src/gsm_04_08_gprs.c b/openbsc/src/gsm_04_08_gprs.c
index ffc3303a3..db439daa7 100644
--- a/openbsc/src/gsm_04_08_gprs.c
+++ b/openbsc/src/gsm_04_08_gprs.c
@@ -153,7 +153,7 @@ static int gsm48_tx_gmm_att_ack(struct msgb *old_msg)
aa->att_result = 1; /* GPRS only */
aa->ra_upd_timer = GPRS_TMR_MINUTE | 10;
aa->radio_prio = 4; /* lowest */
- gsm48_ra_id_by_bts(aa->ra_id.digits, old_msg->trx->bts);
+ //FIXME gsm48_ra_id_by_bts(aa->ra_id.digits, old_msg->trx->bts);
/* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
return gsm48_gmm_sendmsg(msg, 0);
@@ -227,7 +227,7 @@ static int gsm48_rx_gmm_id_resp(struct msgb *msg)
DEBUGP(DMM, "GMM IDENTITY RESPONSE: mi_type=0x%02x MI(%s) ",
mi_type, mi_string);
- gprs_ra_id_by_bts(&ra_id, msg->trx->bts);
+ //FIXME gprs_ra_id_by_bts(&ra_id, msg->trx->bts);
ctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
if (!ctx) {
DEBUGP(DMM, "from unknown TLLI 0x%08x?!?\n", msgb_tlli(msg));
@@ -289,7 +289,7 @@ static int gsm48_rx_gmm_att_req(struct msgb *msg)
* with a foreign TLLI (P-TMSI that was allocated to the MS before),
* or with random TLLI. */
- gprs_ra_id_by_bts(&ra_id, msg->trx->bts);
+ //FIXME gprs_ra_id_by_bts(&ra_id, msg->trx->bts);
/* MS network capability 10.5.5.12 */
msnc_len = *cur++;
@@ -391,7 +391,7 @@ static int gsm48_tx_gmm_ra_upd_ack(struct msgb *old_msg)
rua->force_stby = 0; /* not indicated */
rua->upd_result = 0; /* RA updated */
rua->ra_upd_timer = GPRS_TMR_MINUTE | 10;
- gsm48_ra_id_by_bts(rua->ra_id.digits, old_msg->trx->bts);
+ //FIXME gsm48_ra_id_by_bts(rua->ra_id.digits, old_msg->trx->bts);
/* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
return gsm48_gmm_sendmsg(msg, 0);
diff --git a/openbsc/src/osmo_gbproxy.cfg b/openbsc/src/osmo_gbproxy.cfg
new file mode 100644
index 000000000..f2ef1411f
--- /dev/null
+++ b/openbsc/src/osmo_gbproxy.cfg
@@ -0,0 +1,13 @@
+!
+! OpenBSC configuration saved from vty
+! !
+!
+line vty
+ no login
+!
+gbproxy
+ nsip bss local port 23000
+ nsip sgsn remote ip 192.168.100.239
+ nsip sgsn remote port 23000
+ nsip sgsn nsei 1
+ nsip sgsn nsvci 11
diff --git a/openbsc/src/osmo_sgsn.cfg b/openbsc/src/osmo_sgsn.cfg
new file mode 100644
index 000000000..f39e8536f
--- /dev/null
+++ b/openbsc/src/osmo_sgsn.cfg
@@ -0,0 +1,9 @@
+!
+! OpenBSC configuration saved from vty
+! !
+!
+line vty
+ no login
+!
+sgsn
+ nsip local port 23000
diff --git a/openbsc/src/sgsn_main.c b/openbsc/src/sgsn_main.c
new file mode 100644
index 000000000..5c56ca7ff
--- /dev/null
+++ b/openbsc/src/sgsn_main.c
@@ -0,0 +1,141 @@
+/* GPRS SGSN Implementation */
+
+/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by On Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <osmocore/talloc.h>
+#include <osmocore/select.h>
+
+#include <openbsc/signal.h>
+#include <openbsc/debug.h>
+#include <openbsc/telnet_interface.h>
+#include <openbsc/vty.h>
+#include <openbsc/sgsn.h>
+#include <openbsc/gprs_ns.h>
+#include <openbsc/gprs_bssgp.h>
+
+#include "../bscconfig.h"
+
+/* this is here for the vty... it will never be called */
+void subscr_put() { abort(); }
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+void *tall_bsc_ctx;
+
+struct gprs_ns_inst *sgsn_nsi;
+
+const char *openbsc_version = "Osmocom NSIP Proxy " PACKAGE_VERSION;
+const char *openbsc_copyright =
+ "Copyright (C) 2010 Harald Welte and On-Waves\n"
+ "Contributions by Daniel Willmann, Jan Lübbe, Stefan Schmidt\n"
+ "Dieter Spaar, Andreas Eversberg, Holger Freyther\n\n"
+ "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n"
+ "This is free software: you are free to change and redistribute it.\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n";
+
+static char *config_file = "osmo_sgsn.cfg";
+static struct sgsn_config sgcfg;
+
+/* call-back function for the NS protocol */
+static int sgsn_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
+ struct msgb *msg, u_int16_t bvci)
+{
+ int rc = 0;
+
+ switch (event) {
+ case GPRS_NS_EVT_UNIT_DATA:
+ /* hand the message into the BSSGP implementation */
+ rc = gprs_bssgp_rcvmsg(msg, bvci);
+ break;
+ default:
+ LOGP(DGPRS, LOGL_ERROR, "SGSN: Unknown event %u from NS\n", event);
+ if (msg)
+ talloc_free(msg);
+ rc = -EIO;
+ break;
+ }
+ return rc;
+}
+
+
+int main(int argc, char **argv)
+{
+ struct gsm_network dummy_network;
+ struct log_target *stderr_target;
+ struct sockaddr_in sin;
+ int rc;
+
+ tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
+
+ log_init(&log_info);
+ stderr_target = log_target_create_stderr();
+ log_add_target(stderr_target);
+ log_set_all_filter(stderr_target, 1);
+
+ telnet_init(&dummy_network, 4245);
+ rc = sgsn_parse_config(config_file, &sgcfg);
+ if (rc < 0) {
+ LOGP(DGPRS, LOGL_FATAL, "Cannot parse config file\n");
+ exit(2);
+ }
+
+ sgsn_nsi = gprs_ns_instantiate(&sgsn_ns_cb);
+ if (!sgsn_nsi) {
+ LOGP(DGPRS, LOGL_ERROR, "Unable to instantiate NS\n");
+ exit(1);
+ }
+ sgcfg.nsi = sgsn_nsi;
+ nsip_listen(sgsn_nsi, sgcfg.nsip_listen_port);
+
+ while (1) {
+ rc = bsc_select_main(0);
+ if (rc < 0)
+ exit(3);
+ }
+
+ exit(0);
+}
+
+struct gsm_network;
+int bsc_vty_init(struct gsm_network *dummy)
+{
+ cmd_init(1);
+ vty_init();
+
+ openbsc_vty_add_cmds();
+ sgsn_vty_init();
+ return 0;
+}
+
diff --git a/openbsc/src/sgsn_vty.c b/openbsc/src/sgsn_vty.c
new file mode 100644
index 000000000..ec18fcbf9
--- /dev/null
+++ b/openbsc/src/sgsn_vty.c
@@ -0,0 +1,146 @@
+/*
+ * (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <osmocore/talloc.h>
+
+#include <openbsc/debug.h>
+#include <openbsc/sgsn.h>
+#include <openbsc/gprs_ns.h>
+
+#include <vty/command.h>
+#include <vty/vty.h>
+
+static struct sgsn_config *g_cfg = NULL;
+
+static struct cmd_node sgsn_node = {
+ SGSN_NODE,
+ "%s(sgsn)#",
+ 1,
+};
+
+static int config_write_sgsn(struct vty *vty)
+{
+ struct in_addr ia;
+
+ vty_out(vty, "sgsn%s", VTY_NEWLINE);
+
+ if (g_cfg->nsip_listen_ip) {
+ ia.s_addr = htonl(g_cfg->nsip_listen_ip);
+ vty_out(vty, " nsip local ip %s%s", inet_ntoa(ia),
+ VTY_NEWLINE);
+ }
+ vty_out(vty, " nsip local port %u%s", g_cfg->nsip_listen_port,
+ VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
+ SHOW_STR "Display information about the SGSN")
+{
+ /* FIXME: iterate over list of NS-VC's and display their state */
+ struct gprs_ns_inst *nsi = g_cfg->nsi;
+ struct gprs_nsvc *nsvc;
+
+ llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
+ vty_out(vty, "NSEI %5u, NS-VC %5u, %s-mode, %s %s%s",
+ nsvc->nsei, nsvc->nsvci,
+ nsvc->remote_end_is_sgsn ? "BSS" : "SGSN",
+ nsvc->state & NSE_S_ALIVE ? "ALIVE" : "DEAD",
+ nsvc->state & NSE_S_BLOCKED ? "BLOCKED" : "UNBLOCKED",
+ VTY_NEWLINE);
+ if (nsvc->nsi->ll == GPRS_NS_LL_UDP)
+ vty_out(vty, " remote peer %s:%u%s",
+ inet_ntoa(nsvc->ip.bts_addr.sin_addr),
+ ntohs(nsvc->ip.bts_addr.sin_port), VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_sgsn,
+ cfg_sgsn_cmd,
+ "sgsn",
+ "Configure the SGSN")
+{
+ vty->node = SGSN_NODE;
+ return CMD_SUCCESS;
+}
+
+
+DEFUN(cfg_nsip_local_ip,
+ cfg_nsip_local_ip_cmd,
+ "nsip local ip A.B.C.D",
+ "Set the IP address on which we listen for BSS connects")
+{
+ struct in_addr ia;
+
+ inet_aton(argv[0], &ia);
+ g_cfg->nsip_listen_ip = ntohl(ia.s_addr);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nsip_local_port,
+ cfg_nsip_local_port_cmd,
+ "nsip local port <0-65534>",
+ "Set the UDP port on which we listen for BSS connects")
+{
+ unsigned int port = atoi(argv[0]);
+
+ g_cfg->nsip_listen_port = port;
+ return CMD_SUCCESS;
+}
+
+
+
+
+int sgsn_vty_init(void)
+{
+ install_element(VIEW_NODE, &show_sgsn_cmd);
+
+ install_element(CONFIG_NODE, &cfg_sgsn_cmd);
+ install_node(&sgsn_node, config_write_sgsn);
+ install_default(SGSN_NODE);
+ install_element(SGSN_NODE, &cfg_nsip_local_ip_cmd);
+ install_element(SGSN_NODE, &cfg_nsip_local_port_cmd);
+
+ return 0;
+}
+
+int sgsn_parse_config(const char *config_file, struct sgsn_config *cfg)
+{
+ int rc;
+
+ g_cfg = cfg;
+ rc = vty_read_config_file(config_file);
+ if (rc < 0) {
+ fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
+ return rc;
+ }
+
+ return 0;
+}