aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/configure.ac1
-rw-r--r--openbsc/include/openbsc/Makefile.am1
-rw-r--r--openbsc/include/openbsc/bsc_msc.h11
-rw-r--r--openbsc/include/openbsc/bsc_msc_data.h7
-rw-r--r--openbsc/include/openbsc/debug.h1
-rw-r--r--openbsc/include/openbsc/osmo_bsc.h3
-rw-r--r--openbsc/include/openbsc/osmo_bsc_sigtran.h39
-rw-r--r--openbsc/src/libcommon/debug.c6
-rw-r--r--openbsc/src/osmo-bsc/Makefile.am3
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_api.c14
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_bssap.c21
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_main.c22
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_msc.c62
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_sccp.c27
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_sigtran.c340
15 files changed, 519 insertions, 39 deletions
diff --git a/openbsc/configure.ac b/openbsc/configure.ac
index eccab2407..3875b1652 100644
--- a/openbsc/configure.ac
+++ b/openbsc/configure.ac
@@ -58,6 +58,7 @@ AC_ARG_ENABLE([osmo-bsc], [AS_HELP_STRING([--enable-osmo-bsc], [Build the Osmo B
[osmo_ac_build_bsc="$enableval"],[osmo_ac_build_bsc="no"])
if test "$osmo_ac_build_bsc" = "yes" ; then
PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.6)
+ PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran) # TODO version?
fi
AM_CONDITIONAL(BUILD_BSC, test "x$osmo_ac_build_bsc" = "xyes")
AC_SUBST(osmo_ac_build_bsc)
diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index 81c51aeba..1c31f743e 100644
--- a/openbsc/include/openbsc/Makefile.am
+++ b/openbsc/include/openbsc/Makefile.am
@@ -67,6 +67,7 @@ noinst_HEADERS = \
osmo_bsc_grace.h \
osmo_bsc_rf.h \
osmo_msc.h \
+ osmo_bsc_sigtran.h \
bsc_msc_data.h \
osmux.h \
paging.h \
diff --git a/openbsc/include/openbsc/bsc_msc.h b/openbsc/include/openbsc/bsc_msc.h
index 39258d364..8b9553bfa 100644
--- a/openbsc/include/openbsc/bsc_msc.h
+++ b/openbsc/include/openbsc/bsc_msc.h
@@ -24,6 +24,7 @@
#include <osmocom/core/write_queue.h>
#include <osmocom/core/timer.h>
+#include <osmocom/sigtran/sccp_sap.h>
#include <netinet/in.h>
@@ -37,6 +38,7 @@ struct bsc_msc_dest {
struct bsc_msc_connection {
+ /* FIXME: Remove stuff that is no longer needed! */
struct osmo_wqueue write_queue;
int is_connected;
int is_authenticated;
@@ -52,6 +54,15 @@ struct bsc_msc_connection {
struct osmo_timer_list timeout_timer;
struct msgb *pending_msg;
+
+ /* Sigtran connection data */
+ struct osmo_sccp_instance *sccp;
+ struct osmo_sccp_user *sccp_user;
+ struct osmo_sccp_addr g_calling_addr;
+ struct osmo_sccp_addr g_called_addr;
+ struct osmo_timer_list msc_reset_timer;
+ bool reset_ack;
+ int conn_id_counter;
};
struct bsc_msc_connection *bsc_msc_create(void *ctx, struct llist_head *dest);
diff --git a/openbsc/include/openbsc/bsc_msc_data.h b/openbsc/include/openbsc/bsc_msc_data.h
index 38e87cfb9..a819abab3 100644
--- a/openbsc/include/openbsc/bsc_msc_data.h
+++ b/openbsc/include/openbsc/bsc_msc_data.h
@@ -32,6 +32,13 @@
#include <osmocom/core/timer.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+#include <osmocom/sigtran/osmo_ss7.h>
+#include <osmocom/sigtran/sccp_sap.h>
+#include <osmocom/sigtran/sccp_helpers.h>
+#include <osmocom/sigtran/protocol/sua.h>
+#include <osmocom/sigtran/protocol/m3ua.h>
+
#include <regex.h>
struct osmo_bsc_rf;
diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h
index de00b2930..65e197d52 100644
--- a/openbsc/include/openbsc/debug.h
+++ b/openbsc/include/openbsc/debug.h
@@ -40,6 +40,7 @@ enum {
DPCU,
DVLR,
DIUCS,
+ DSIGTRAN,
Debug_LastEntry,
};
diff --git a/openbsc/include/openbsc/osmo_bsc.h b/openbsc/include/openbsc/osmo_bsc.h
index 9e688fd59..5d3ff6a7f 100644
--- a/openbsc/include/openbsc/osmo_bsc.h
+++ b/openbsc/include/openbsc/osmo_bsc.h
@@ -44,6 +44,9 @@ struct osmo_bsc_sccp_con {
uint8_t new_subscriber;
struct bsc_filter_state filter_state;
+
+ /* Sigtran connection ID */
+ int conn_id;
};
struct bsc_api *osmo_bsc_api();
diff --git a/openbsc/include/openbsc/osmo_bsc_sigtran.h b/openbsc/include/openbsc/osmo_bsc_sigtran.h
new file mode 100644
index 000000000..37085b653
--- /dev/null
+++ b/openbsc/include/openbsc/osmo_bsc_sigtran.h
@@ -0,0 +1,39 @@
+/* (C) 2017 by Sysmocom s.f.m.c. GmbH
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+/* Allocate resources to make a new connection oriented sigtran connection
+ * (not the connection ittself!) */
+enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, struct bsc_msc_data *msc);
+
+/* Open a new connection oriented sigtran connection */
+int osmo_bsc_sigtran_open_conn(struct osmo_bsc_sccp_con *conn, struct msgb *msg);
+
+/* Send data to MSC */
+int osmo_bsc_sigtran_send(struct osmo_bsc_sccp_con *conn, struct msgb *msg);
+
+/* Delete a connection from the list with open connections
+ * (called by osmo_bsc_api.c on failing open connections and
+ * locally, when a connection is closed by the MSC */
+int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *sccp);
+
+/* Initalize osmo sigtran backhaul */
+int osmo_bsc_sigtran_init(struct llist_head *mscs);
diff --git a/openbsc/src/libcommon/debug.c b/openbsc/src/libcommon/debug.c
index 7c12159c4..7ed1e2934 100644
--- a/openbsc/src/libcommon/debug.c
+++ b/openbsc/src/libcommon/debug.c
@@ -189,6 +189,12 @@ static const struct log_info_cat default_categories[] = {
.description = "Iu-CS Protocol",
.enabled = 1, .loglevel = LOGL_DEBUG,
},
+ [DSIGTRAN] = {
+ .name = "DSIGTRAN",
+ .description = "SIGTRAN Signalling Transport",
+ .color = "\033[1;29m",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
};
static int filter_fn(const struct log_context *ctx, struct log_target *tar)
diff --git a/openbsc/src/osmo-bsc/Makefile.am b/openbsc/src/osmo-bsc/Makefile.am
index 6f836b08c..d0d0e3afc 100644
--- a/openbsc/src/osmo-bsc/Makefile.am
+++ b/openbsc/src/osmo-bsc/Makefile.am
@@ -14,6 +14,7 @@ AM_CFLAGS = \
$(LIBOSMOSCCP_CFLAGS) \
$(COVERAGE_CFLAGS) \
$(LIBOSMOABIS_CFLAGS) \
+ $(LIBOSMOSIGTRAN_CFLAGS) \
$(NULL)
AM_LDFLAGS = \
@@ -31,6 +32,7 @@ osmo_bsc_SOURCES = \
osmo_bsc_grace.c \
osmo_bsc_msc.c \
osmo_bsc_sccp.c \
+ osmo_bsc_sigtran.c \
osmo_bsc_filter.c \
osmo_bsc_bssap.c \
osmo_bsc_audio.c \
@@ -53,4 +55,5 @@ osmo_bsc_LDADD = \
$(LIBOSMOCTRL_LIBS) \
$(COVERAGE_LDFLAGS) \
$(LIBOSMOABIS_LIBS) \
+ $(LIBOSMOSIGTRAN_LIBS) \
$(NULL)
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c
index 8c33e2b57..d15ec40cd 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_api.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_api.c
@@ -27,6 +27,7 @@
#include <osmocom/gsm/gsm0808.h>
#include <osmocom/sccp/sccp.h>
+#include <openbsc/osmo_bsc_sigtran.h>
#define return_when_not_connected(conn) \
if (!conn->sccp_con) {\
@@ -45,7 +46,7 @@
LOGP(DMSC, LOGL_ERROR, "Failed to allocate response.\n"); \
return; \
} \
- bsc_queue_for_msc(conn->sccp_con, resp);
+ osmo_bsc_sigtran_send(conn->sccp_con, resp);
static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause);
static int complete_layer3(struct gsm_subscriber_connection *conn,
@@ -263,7 +264,8 @@ static int complete_layer3(struct gsm_subscriber_connection *conn,
}
/* allocate resource for a new connection */
- ret = bsc_create_new_connection(conn, msc, send_ping);
+ //ret = bsc_create_new_connection(conn, msc, send_ping);
+ ret = osmo_bsc_sigtran_new_conn(conn, msc);
if (ret != BSC_CON_SUCCESS) {
/* allocation has failed */
@@ -292,13 +294,13 @@ static int complete_layer3(struct gsm_subscriber_connection *conn,
if (!resp) {
LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n");
sccp_connection_free(conn->sccp_con->sccp);
- bsc_delete_connection(conn->sccp_con);
+ osmo_bsc_sigtran_del_conn(conn->sccp_con);
return BSC_API_CONN_POL_REJECT;
}
- if (bsc_open_connection(conn->sccp_con, resp) != 0) {
+ if (osmo_bsc_sigtran_open_conn(conn->sccp_con, resp) != 0) {
sccp_connection_free(conn->sccp_con->sccp);
- bsc_delete_connection(conn->sccp_con);
+ osmo_bsc_sigtran_del_conn(conn->sccp_con);
msgb_free(resp);
return BSC_API_CONN_POL_REJECT;
}
@@ -474,7 +476,7 @@ static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t ca
return 1;
}
- bsc_queue_for_msc(sccp, resp);
+ osmo_bsc_sigtran_send(sccp, resp);
return 1;
}
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
index 100f66441..57a62a5eb 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
@@ -29,6 +29,7 @@
#include <osmocom/gsm/protocol/gsm_08_08.h>
#include <osmocom/gsm/gsm0808.h>
+#include <openbsc/osmo_bsc_sigtran.h>
/*
* helpers for the assignment command
@@ -92,7 +93,19 @@ enum gsm48_chan_mode gsm88_to_chan_mode(enum gsm0808_permitted_speech speech)
static int bssmap_handle_reset_ack(struct bsc_msc_data *msc,
struct msgb *msg, unsigned int length)
{
- LOGP(DMSC, LOGL_NOTICE, "Reset ACK from MSC\n");
+ LOGP(DMSC, LOGL_NOTICE, "Reset ACK from MSC No.: %i\n", msc->nr);
+ msc->msc_con->reset_ack = true;
+
+#if 0
+ struct msc_signal_data sig;
+ struct bsc_msc_data *data;
+
+ data = (struct bsc_msc_data *) msc;
+ sig.data = data;
+ osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, &sig);
+ osmo_signal_dispatch(SS_MSC, S_MSC_AUTHENTICATED, &sig);
+#endif
+
return 0;
}
@@ -199,7 +212,7 @@ static int bssmap_handle_clear_command(struct osmo_bsc_sccp_con *conn,
return -1;
}
- bsc_queue_for_msc(conn, resp);
+ osmo_bsc_sigtran_send(conn, resp);
return 0;
}
@@ -276,7 +289,7 @@ reject:
return -1;
}
- bsc_queue_for_msc(conn, resp);
+ osmo_bsc_sigtran_send(conn, resp);
return -1;
}
@@ -383,7 +396,7 @@ reject:
return -1;
}
- bsc_queue_for_msc(conn, resp);
+ osmo_bsc_sigtran_send(conn, resp);
return -1;
}
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_main.c b/openbsc/src/osmo-bsc/osmo_bsc_main.c
index ee094d670..1f8f645ac 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_main.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_main.c
@@ -28,6 +28,7 @@
#include <openbsc/vty.h>
#include <openbsc/ipaccess.h>
#include <openbsc/ctrl.h>
+#include <openbsc/osmo_bsc_sigtran.h>
#include <osmocom/ctrl/control_cmd.h>
#include <osmocom/ctrl/control_if.h>
@@ -269,8 +270,25 @@ int main(int argc, char **argv)
}
- if (osmo_bsc_sccp_init(bsc_gsmnet) != 0) {
- LOGP(DNM, LOGL_ERROR, "Failed to register SCCP.\n");
+ llist_for_each_entry(msc, &bsc_gsmnet->bsc_data->mscs, entry) {
+ /* FIXME: This has to come from a config file */
+ msc->msc_con->g_calling_addr.presence = OSMO_SCCP_ADDR_T_SSN | OSMO_SCCP_ADDR_T_PC;
+ msc->msc_con->g_calling_addr.ssn = SCCP_SSN_BSSAP;
+ msc->msc_con->g_calling_addr.ri = OSMO_SCCP_RI_SSN_PC;
+ msc->msc_con->g_calling_addr.pc = 23;
+ msc->msc_con->g_called_addr.presence = OSMO_SCCP_ADDR_T_SSN | OSMO_SCCP_ADDR_T_PC;
+ msc->msc_con->g_called_addr.ssn = SCCP_SSN_BSSAP;
+ msc->msc_con->g_called_addr.ri = OSMO_SCCP_RI_SSN_PC;
+ msc->msc_con->g_called_addr.pc = 1;
+ }
+
+// if (osmo_bsc_sccp_init(bsc_gsmnet) != 0) {
+// LOGP(DNM, LOGL_ERROR, "Failed to register SCCP.\n");
+// exit(1);
+// }
+
+ if (osmo_bsc_sigtran_init(&bsc_gsmnet->bsc_data->mscs) != 0) {
+ LOGP(DNM, LOGL_ERROR, "Failed to initalize sigtran backhaul.\n");
exit(1);
}
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_msc.c b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
index 8d02624b4..351fd2ced 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_msc.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
@@ -42,7 +42,7 @@
#include <netinet/tcp.h>
#include <unistd.h>
-
+#if 0
static void initialize_if_needed(struct bsc_msc_connection *conn);
static void send_lacs(struct gsm_network *net, struct bsc_msc_connection *conn);
static void send_id_get_response(struct bsc_msc_data *data, int fd, struct msgb *inp);
@@ -52,6 +52,8 @@ static void schedule_ping_pong(struct bsc_msc_data *data);
/*
* MGCP forwarding code
*/
+
+#endif
static int mgcp_do_read(struct osmo_fd *fd)
{
struct bsc_msc_data *data = (struct bsc_msc_data *) fd->data;
@@ -93,6 +95,7 @@ static int mgcp_do_write(struct osmo_fd *fd, struct msgb *msg)
return ret;
}
+#if 0
static void mgcp_forward(struct bsc_msc_data *data, struct msgb *msg)
{
struct msgb *mgcp;
@@ -115,6 +118,7 @@ static void mgcp_forward(struct bsc_msc_data *data, struct msgb *msg)
msgb_free(mgcp);
}
}
+#endif
static int mgcp_create_port(struct bsc_msc_data *data)
{
@@ -168,6 +172,7 @@ static int mgcp_create_port(struct bsc_msc_data *data)
return 0;
}
+
/*
* Send data to the network
*/
@@ -183,6 +188,7 @@ int msc_queue_write(struct bsc_msc_connection *conn, struct msgb *msg, int proto
return 0;
}
+#if 0
int msc_queue_write_with_ping(struct bsc_msc_connection *conn,
struct msgb *msg, int proto)
{
@@ -356,10 +362,10 @@ static void msc_ping_timeout_cb(void *_data)
static void msc_pong_timeout_cb(void *_data)
{
- struct bsc_msc_data *data = (struct bsc_msc_data *) _data;
+// struct bsc_msc_data *data = (struct bsc_msc_data *) _data;
LOGP(DMSC, LOGL_ERROR, "MSC didn't answer PING. Closing connection.\n");
- bsc_msc_lost(data->msc_con);
+// bsc_msc_lost(data->msc_con);
}
static void msc_connection_connected(struct bsc_msc_connection *con)
@@ -368,12 +374,12 @@ static void msc_connection_connected(struct bsc_msc_connection *con)
struct bsc_msc_data *data;
int ret, on;
on = 1;
- ret = setsockopt(con->write_queue.bfd.fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
- if (ret != 0)
- LOGP(DMSC, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
+// ret = setsockopt(con->write_queue.bfd.fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+// if (ret != 0)
+// LOGP(DMSC, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
- data = (struct bsc_msc_data *) con->write_queue.bfd.data;
- msc_ping_timeout_cb(data);
+// data = (struct bsc_msc_data *) con->write_queue.bfd.data;
+// msc_ping_timeout_cb(data);
sig.data = data;
osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, &sig);
@@ -385,20 +391,20 @@ static void msc_connection_connected(struct bsc_msc_connection *con)
*/
static void msc_connection_was_lost(struct bsc_msc_connection *msc)
{
- struct msc_signal_data sig;
- struct bsc_msc_data *data;
+// struct msc_signal_data sig;
+// struct bsc_msc_data *data;
LOGP(DMSC, LOGL_ERROR, "Lost MSC connection. Freing stuff.\n");
- data = (struct bsc_msc_data *) msc->write_queue.bfd.data;
- osmo_timer_del(&data->ping_timer);
- osmo_timer_del(&data->pong_timer);
-
- sig.data = data;
- osmo_signal_dispatch(SS_MSC, S_MSC_LOST, &sig);
+// data = (struct bsc_msc_data *) msc->write_queue.bfd.data;
+// osmo_timer_del(&data->ping_timer);
+// osmo_timer_del(&data->pong_timer);
+//
+// sig.data = data;
+// osmo_signal_dispatch(SS_MSC, S_MSC_LOST, &sig);
msc->is_authenticated = 0;
- bsc_msc_schedule_connect(msc);
+// bsc_msc_schedule_connect(msc);
}
static void send_lacs(struct gsm_network *net, struct bsc_msc_connection *conn)
@@ -515,6 +521,8 @@ static void send_id_get_response(struct bsc_msc_data *data, int fd, struct msgb
osmo_signal_dispatch(SS_MSC, S_MSC_AUTHENTICATED, &sig);
}
+#endif
+
int osmo_bsc_msc_init(struct bsc_msc_data *data)
{
if (mgcp_create_port(data) != 0)
@@ -526,19 +534,24 @@ int osmo_bsc_msc_init(struct bsc_msc_data *data)
return -1;
}
- osmo_timer_setup(&data->ping_timer, msc_ping_timeout_cb, data);
- osmo_timer_setup(&data->pong_timer, msc_pong_timeout_cb, data);
+// osmo_timer_setup(&data->ping_timer, msc_ping_timeout_cb, data);
+// osmo_timer_setup(&data->pong_timer, msc_pong_timeout_cb, data);
data->msc_con->write_queue.bfd.data = data;
- data->msc_con->connection_loss = msc_connection_was_lost;
- data->msc_con->connected = msc_connection_connected;
- data->msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
- data->msc_con->write_queue.write_cb = msc_alink_do_write;
- bsc_msc_connect(data->msc_con);
+// data->msc_con->connection_loss = msc_connection_was_lost;
+// data->msc_con->connected = msc_connection_connected;
+// data->msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
+// data->msc_con->write_queue.write_cb = msc_alink_do_write;
+// bsc_msc_connect(data->msc_con);
+
+ data->msc_con->is_connected = 1;
+ data->msc_con->is_authenticated = 1;
+
return 0;
}
+
struct bsc_msc_data *osmo_msc_data_find(struct gsm_network *net, int nr)
{
struct bsc_msc_data *msc_data;
@@ -584,3 +597,4 @@ struct bsc_msc_data *osmo_msc_data_alloc(struct gsm_network *net, int nr)
return msc_data;
}
+
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_sccp.c b/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
index e242390ef..f54dc31cb 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
@@ -37,6 +37,7 @@
/* SCCP helper */
#define SCCP_IT_TIMER 60
+#if 0
static LLIST_HEAD(active_connections);
static void free_queued(struct osmo_bsc_sccp_con *conn)
@@ -172,6 +173,9 @@ static int msc_sccp_read(struct msgb *msgb, unsigned int length, void *data)
int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
{
+
+ printf("==================> bsc_queue_for_msc()\n");
+#if 0
struct sccp_connection *sccp = conn->sccp;
if (sccp->connection_state > SCCP_CONNECTION_STATE_ESTABLISHED) {
@@ -189,6 +193,7 @@ int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
conn->sccp_queue_size += 1;
msgb_enqueue(&conn->sccp_queue, msg);
}
+#endif
return 0;
}
@@ -196,6 +201,9 @@ int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
enum bsc_con bsc_create_new_connection(struct gsm_subscriber_connection *conn,
struct bsc_msc_data *msc, int send_ping)
{
+
+ printf("==================> bsc_con bsc_create_new_connection()\n");
+#if 0
struct osmo_bsc_sccp_con *bsc_con;
struct sccp_connection *sccp;
@@ -243,18 +251,29 @@ enum bsc_con bsc_create_new_connection(struct gsm_subscriber_connection *conn,
llist_add_tail(&bsc_con->entry, &active_connections);
conn->sccp_con = bsc_con;
return BSC_CON_SUCCESS;
+
+#endif
+ return BSC_CON_SUCCESS;
}
int bsc_open_connection(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
{
- osmo_timer_schedule(&conn->sccp_cc_timeout, 10, 0);
- sccp_connection_connect(conn->sccp, &sccp_ssn_bssap, msg);
- msgb_free(msg);
+ printf("======================> bsc_open_connection()\n");
+
+
+// osmo_timer_schedule(&conn->sccp_cc_timeout, 10, 0);
+// sccp_connection_connect(conn->sccp, &sccp_ssn_bssap, msg);
+// msgb_free(msg);
return 0;
}
int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp)
{
+ printf("======================> bsc_delete_connection()\n");
+ return 0;
+
+#if 0
+
if (!sccp)
return 0;
@@ -266,6 +285,7 @@ int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp)
osmo_timer_del(&sccp->sccp_cc_timeout);
talloc_free(sccp);
return 0;
+#endif
}
static void bsc_notify_msc_lost(struct osmo_bsc_sccp_con *con)
@@ -326,3 +346,4 @@ int osmo_bsc_sccp_init(struct gsm_network *gsmnet)
return 0;
}
+#endif
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_sigtran.c b/openbsc/src/osmo-bsc/osmo_bsc_sigtran.c
new file mode 100644
index 000000000..b95ec9ddc
--- /dev/null
+++ b/openbsc/src/osmo-bsc/osmo_bsc_sigtran.c
@@ -0,0 +1,340 @@
+/* (C) 2017 by Sysmocom s.f.m.c. GmbH
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/sigtran/osmo_ss7.h>
+#include <osmocom/sigtran/sccp_sap.h>
+#include <osmocom/sccp/sccp_types.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/gsm0808.h>
+#include <osmocom/core/msgb.h>
+#include <openbsc/bsc_msc_data.h>
+#include <openbsc/debug.h>
+#include <openbsc/osmo_bsc.h>
+#include <openbsc/osmo_bsc_grace.h>
+#include <openbsc/osmo_bsc_sigtran.h>
+
+/* A pointer to a list with all involved MSCs
+ * (a copy of the pointer location submitted with osmo_bsc_sigtran_init() */
+static struct llist_head *msc_list;
+
+#define RESET_INTERVAL 1 /* sek */
+#define SCCP_MSG_MAXSIZE 1024
+
+static LLIST_HEAD(active_connections);
+
+/* Helper function to Check if the given connection id is already assigned */
+static struct osmo_bsc_sccp_con *get_bsc_conn_by_conn_id(int conn_id)
+{
+ conn_id &= 0xFFFFFF;
+ struct osmo_bsc_sccp_con *bsc_con;
+
+ llist_for_each_entry(bsc_con, &active_connections, entry) {
+ if (bsc_con->conn_id == conn_id)
+ return bsc_con;
+ }
+
+ return NULL;
+}
+
+/* Pick a free connection id */
+static int pick_free_conn_id(struct bsc_msc_data *msc)
+{
+ int conn_id = msc->msc_con->conn_id_counter;
+ int i;
+
+ for (i = 0; i < 0xFFFFFF; i++) {
+ conn_id++;
+ conn_id &= 0xFFFFFF;
+ if (get_bsc_conn_by_conn_id(conn_id) == false) {
+ msc->msc_con->conn_id_counter = conn_id;
+ return conn_id;
+ }
+ }
+
+ return -1;
+}
+
+/* Timer callback to handle the MSC reset procedure */
+static void msc_reset_timer_cb(void *data)
+{
+ /* FIXME: Probably the reset procedure should be moved to osmo_bsc_bssap.c,
+ * since it is clearly in the BSSAP's area of accountability */
+ struct bsc_msc_data *msc = (struct bsc_msc_data *)data;
+ struct msgb *msg = NULL;
+
+ /* Stop sending RESET messages as soon as the
+ * connection is marked as connected. */
+ if (msc->msc_con->reset_ack)
+ return;
+
+ LOGP(DMSC, LOGL_NOTICE, "Sending RESET to MSC No.: %i\n", msc->nr);
+
+ msg = gsm0808_create_reset();
+ osmo_sccp_tx_unitdata_msg(msc->msc_con->sccp_user, &msc->msc_con->g_calling_addr,
+ &msc->msc_con->g_called_addr, msg);
+
+ osmo_timer_schedule(&msc->msc_con->msc_reset_timer, RESET_INTERVAL, 0);
+}
+
+/* Perform MSC reset procedure */
+static void msc_reset(struct bsc_msc_data *msc)
+{
+ LOGP(DMSC, LOGL_NOTICE, "Starting RESET for MSC No.: %i\n", msc->nr);
+ msc->msc_con->msc_reset_timer.cb = msc_reset_timer_cb;
+ msc->msc_con->msc_reset_timer.data = msc;
+ msc->msc_con->reset_ack = false;
+ osmo_timer_schedule(&msc->msc_con->msc_reset_timer, RESET_INTERVAL, 0);
+}
+
+/* Find an MSC by its sigtran point code */
+static struct bsc_msc_data *get_msc_by_addr(struct osmo_sccp_addr *calling_addr)
+{
+ struct bsc_msc_data *msc;
+ llist_for_each_entry(msc, msc_list, entry) {
+ if (memcmp(calling_addr, &msc->msc_con->g_called_addr, sizeof(*calling_addr)) == 0)
+ return msc;
+ }
+
+ LOGP(DMSC, LOGL_ERROR, "Unable to find MSC data under address: %s\n", osmo_sccp_addr_dump(calling_addr));
+ return NULL;
+}
+
+/* Send data to MSC, use the connection id which MSC it is */
+static int handle_data_from_msc(int conn_id, struct msgb *msg)
+{
+ struct osmo_bsc_sccp_con *bsc_con = get_bsc_conn_by_conn_id(conn_id);
+ int rc = -EINVAL;
+
+ if (bsc_con) {
+ msg->l3h = msgb_l2(msg);
+ rc = bsc_handle_dt1(bsc_con, msg, msgb_l2len(msg));
+ } else
+ LOGP(DMSC, LOGL_NOTICE, "incoming data from unknown connection id: %i\n", conn_id);
+
+ return rc;
+}
+
+/* Sent unitdata to MSC, use the point code to determine which MSC it is */
+static int handle_unitdata_from_msc(struct osmo_sccp_addr *calling_addr, struct msgb *msg)
+{
+ struct bsc_msc_data *msc = get_msc_by_addr(calling_addr);
+ int rc = -EINVAL;
+
+ if (msc) {
+ msg->l3h = msgb_l2(msg);
+ rc = bsc_handle_udt(msc, msg, msgb_l2len(msg));
+ } else
+ LOGP(DMSC, LOGL_NOTICE, "incoming unitdata data from unknown remote address: %s\n",
+ osmo_sccp_addr_dump(calling_addr));
+
+ return rc;
+}
+
+/* Callback function, called by the SSCP stack when data arrives */
+static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
+{
+ struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *)oph;
+ struct osmo_sccp_user *scu = _scu;
+ int rc = 0;
+
+ switch (OSMO_PRIM_HDR(&scu_prim->oph)) {
+ case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION):
+ /* Handle inbound UNITDATA */
+ DEBUGP(DMSC, "N-UNITDATA.ind(%s)\n", osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
+ rc = handle_unitdata_from_msc(&scu_prim->u.unitdata.calling_addr, oph->msg);
+ break;
+
+ case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_INDICATION):
+ /* Handle (Reject) inbound connections */
+ DEBUGP(DMSC, "N-CONNECT.ind(X->%u)\n", scu_prim->u.connect.conn_id);
+ LOGP(DMSC, LOGL_DEBUG, "Rejecting inbound SCCP connection...\n");
+ rc = osmo_sccp_tx_disconn(scu, scu_prim->u.connect.conn_id, &scu_prim->u.connect.called_addr, 0);
+ break;
+
+ case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_CONFIRM):
+ /* Handle outbound connection confirmation */
+ if (msgb_l2len(oph->msg) > 0) {
+ DEBUGP(DMSC, "N-CONNECT.cnf(%u, %s)\n", scu_prim->u.connect.conn_id,
+ osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
+ rc = handle_data_from_msc(scu_prim->u.connect.conn_id, oph->msg);
+ } else
+ DEBUGP(DRANAP, "N-CONNECT.cnf(%u)\n", scu_prim->u.connect.conn_id);
+ break;
+
+ case OSMO_PRIM(OSMO_SCU_PRIM_N_DATA, PRIM_OP_INDICATION):
+ /* Handle incoming connection oriented data */
+ DEBUGP(DMSC, "N-DATA.ind(%u, %s)\n", scu_prim->u.data.conn_id,
+ osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
+ rc = handle_data_from_msc(scu_prim->u.data.conn_id, oph->msg);
+ break;
+
+ case OSMO_PRIM(OSMO_SCU_PRIM_N_DISCONNECT, PRIM_OP_INDICATION):
+ /* indication of disconnect */
+ if (msgb_l2len(oph->msg) > 0) {
+ DEBUGP(DMSC, "N-DISCONNECT.ind(%u, %s)\n", scu_prim->u.disconnect.conn_id,
+ osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
+ handle_data_from_msc(scu_prim->u.disconnect.conn_id, oph->msg);
+ } else
+ DEBUGP(DRANAP, "N-DISCONNECT.ind(%u)\n", scu_prim->u.disconnect.conn_id);
+
+ rc = osmo_bsc_sigtran_del_conn(get_bsc_conn_by_conn_id(scu_prim->u.disconnect.conn_id));
+ break;
+
+ default:
+ LOGP(DMSC, LOGL_ERROR, "Unhandled SIGTRAN primitive: %u:%u\n", oph->primitive, oph->operation);
+ break;
+ }
+
+ msgb_free(oph->msg);
+ return rc;
+}
+
+/* Allocate resources to make a new connection oriented sigtran connection
+ * (not the connection ittself!) */
+enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, struct bsc_msc_data *msc)
+{
+ struct osmo_bsc_sccp_con *bsc_con;
+ int conn_id;
+
+ OSMO_ASSERT(conn);
+ OSMO_ASSERT(msc);
+
+ LOGP(DMSC, LOGL_NOTICE, "Initalizing resources for new SIGTRAN connection to MSC No.: %i...\n", msc->nr);
+
+ /* This should not trigger */
+ if (!msc || !msc->msc_con->is_authenticated) {
+ LOGP(DMSC, LOGL_ERROR, "How did this happen? MSC is not connected. Dropping.\n");
+ return BSC_CON_REJECT_NO_LINK;
+ }
+
+ if (!bsc_grace_allow_new_connection(conn->bts->network, conn->bts)) {
+ LOGP(DMSC, LOGL_NOTICE, "BSC in grace period. No new connections.\n");
+ return BSC_CON_REJECT_RF_GRACE;
+ }
+
+ bsc_con = talloc_zero(conn->bts, struct osmo_bsc_sccp_con);
+ if (!bsc_con) {
+ LOGP(DMSC, LOGL_ERROR, "Failed to allocate new SIGTRAN connection.\n");
+ return BSC_CON_NO_MEM;
+ }
+
+ bsc_con->msc = msc;
+ bsc_con->conn = conn;
+ llist_add_tail(&bsc_con->entry, &active_connections);
+ conn->sccp_con = bsc_con;
+
+ /* Pick a free connection id */
+ conn_id = pick_free_conn_id(msc);
+ if (conn_id < 0)
+ return BSC_CON_REJECT_NO_LINK;
+ bsc_con->conn_id = conn_id;
+
+ LOGP(DMSC, LOGL_NOTICE, "Allocated new connection id: %i\n", conn_id);
+
+ return BSC_CON_SUCCESS;
+}
+
+/* Open a new connection oriented sigtran connection */
+int osmo_bsc_sigtran_open_conn(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
+{
+ struct bsc_msc_data *msc = conn->msc;
+ int conn_id = conn->conn_id;
+ int rc;
+
+ OSMO_ASSERT(conn);
+ OSMO_ASSERT(msg);
+
+ LOGP(DMSC, LOGL_NOTICE, "Opening new SIGTRAN connection (id=%i) to MSC No.: %i...\n", conn_id, msc->nr);
+
+ rc = osmo_sccp_tx_conn_req_msg(msc->msc_con->sccp_user, conn_id, &msc->msc_con->g_calling_addr,
+ &msc->msc_con->g_called_addr, msg);
+
+ return rc;
+}
+
+/* Send data to MSC */
+int osmo_bsc_sigtran_send(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
+{
+ int conn_id;
+ int rc;
+ struct bsc_msc_data *msc;
+
+ OSMO_ASSERT(conn);
+ OSMO_ASSERT(msg);
+
+ msc = conn->msc;
+ conn_id = conn->conn_id;
+
+ LOGP(DMSC, LOGL_DEBUG, "Sending connection (id=%i) oriented data to MSC No.: %i...\n", conn_id, msc->nr);
+ rc = osmo_sccp_tx_data_msg(msc->msc_con->sccp_user, conn_id, msg);
+
+ return rc;
+}
+
+/* Delete a connection from the list with open connections
+ * (called by osmo_bsc_api.c on failing open connections and
+ * locally, when a connection is closed by the MSC */
+int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *sccp)
+{
+ if (!sccp)
+ return 0;
+
+ if (sccp->conn)
+ LOGP(DMSC, LOGL_ERROR, "sccp connection not cleared -- forcefully clearing it now!\n");
+
+ llist_del(&sccp->entry);
+ talloc_free(sccp);
+
+ return 0;
+}
+
+/* Initalize osmo sigtran backhaul */
+int osmo_bsc_sigtran_init(struct llist_head *mscs)
+{
+ /* FIXME: Remove hardcoded IP-Addresses */
+ /* FIXME: Use STP! */
+ struct bsc_msc_data *msc;
+ char msc_name[256];
+
+ OSMO_ASSERT(mscs);
+
+ osmo_ss7_init();
+
+ msc_list = mscs;
+
+ llist_for_each_entry(msc, msc_list, entry) {
+ snprintf(msc_name, sizeof(msc_name), "MSC No.: %u", msc->nr);
+ LOGP(DMSC, LOGL_NOTICE, "Initalizing SCCP connection to %s\n", msc_name);
+
+ /* SCCP Protocol stack */
+ msc->msc_con->sccp =
+ osmo_sccp_simple_client(NULL, msc_name, msc->msc_con->g_calling_addr.pc,
+ OSMO_SS7_ASP_PROT_M3UA, 0, NULL, M3UA_PORT, "127.0.0.2");
+ msc->msc_con->sccp_user =
+ osmo_sccp_user_bind(msc->msc_con->sccp, msc_name, sccp_sap_up, SCCP_SSN_BSSAP);
+
+ /* Start MSC reset procedure */
+ msc_reset(msc);
+ }
+
+ return 0;
+}