aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2017-06-23 14:43:55 +0200
committerPhilipp Maier <pmaier@sysmocom.de>2017-06-28 13:35:10 +0200
commit40703dd1f441ee754a3b9b8b838feb66bc8e032d (patch)
tree7f870f861931021464144bc2f59e4c19640d1384
parent030312043a84b0bfaf35c36790e56e3016c68661 (diff)
a_iface: use vty to configure BSC/MSC connections
Use the VTY to configure the connections between BSC and MSC on both sides. We now can add new connections, we also can write the config, removing existing connections is implemented on the MSC side, but not yet on the BSC side.
-rw-r--r--openbsc/include/openbsc/a_iface.h16
-rw-r--r--openbsc/include/openbsc/a_reset.h5
-rw-r--r--openbsc/include/openbsc/bsc_msc.h7
-rw-r--r--openbsc/include/openbsc/bsc_msc_data.h10
-rw-r--r--openbsc/include/openbsc/gsm_data.h5
-rw-r--r--openbsc/src/libcommon-cs/a_reset.c37
-rw-r--r--openbsc/src/libcommon-cs/common_cs.c2
-rw-r--r--openbsc/src/libmsc/a_iface.c131
-rw-r--r--openbsc/src/libmsc/msc_vty.c104
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_bssap.c2
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_main.c22
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_sigtran.c45
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_vty.c89
-rw-r--r--openbsc/src/osmo-msc/msc_main.c2
14 files changed, 367 insertions, 110 deletions
diff --git a/openbsc/include/openbsc/a_iface.h b/openbsc/include/openbsc/a_iface.h
index 6da2715e9..22651625f 100644
--- a/openbsc/include/openbsc/a_iface.h
+++ b/openbsc/include/openbsc/a_iface.h
@@ -31,13 +31,19 @@ struct bsc_context {
struct osmo_sccp_addr calling_addr; /* MSC (local) */
/* Automatically filled up by a_init() */
- struct a_reset_ctx reset; /* Reset FSM (one per BSC) */
- struct osmo_sccp_user *sccp_user; /* SCCP user (the same for all) */
+ char name[512];
+ struct a_reset_ctx *reset; /* Reset FSM */
+ struct osmo_ss7_instance *ss7;
+ struct osmo_sccp_instance *sccp;
+ struct osmo_sccp_user *sccp_user;
};
-/* Initalize A interface connection between to MSC and BSC */
-int a_init(void *ctx, const char *name, uint32_t local_pc, const char *listen_addr,
- const char *remote_addr, uint16_t local_port, struct gsm_network *network);
+/* Initalize a new A connection for a remote bsc (called by VTY) */
+int a_init(struct gsm_network *network, struct osmo_sccp_addr *calling_addr, struct osmo_sccp_addr *called_addr,
+ struct osmo_ss7_instance *ss7);
+
+/* Drop a no longer used A connection (called by VTY) */
+void a_drop(struct osmo_sccp_addr *calling_addr, struct osmo_sccp_addr *called_addr);
/* Send DTAP message via A-interface */
int a_iface_tx_dtap(struct msgb *msg);
diff --git a/openbsc/include/openbsc/a_reset.h b/openbsc/include/openbsc/a_reset.h
index 124cf13f1..343454a28 100644
--- a/openbsc/include/openbsc/a_reset.h
+++ b/openbsc/include/openbsc/a_reset.h
@@ -45,7 +45,10 @@ struct a_reset_ctx {
};
/* Create and start state machine which handles the reset/reset-ack procedure */
-void a_reset_start(struct a_reset_ctx *reset);
+struct a_reset_ctx *a_reset_alloc(void *ctx, char *name, void *cb, void *priv);
+
+/* Tear down state machine */
+void a_reset_free(struct a_reset_ctx *reset);
/* Confirm that we sucessfully received a reset acknowlege message */
void a_reset_ack_confirm(struct a_reset_ctx *reset);
diff --git a/openbsc/include/openbsc/bsc_msc.h b/openbsc/include/openbsc/bsc_msc.h
index 35b8654d5..e52d92e77 100644
--- a/openbsc/include/openbsc/bsc_msc.h
+++ b/openbsc/include/openbsc/bsc_msc.h
@@ -55,13 +55,6 @@ 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 a_reset_ctx reset;
};
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 0d7ec224d..e97ab13fc 100644
--- a/openbsc/include/openbsc/bsc_msc_data.h
+++ b/openbsc/include/openbsc/bsc_msc_data.h
@@ -111,6 +111,16 @@ struct bsc_msc_data {
char *ussd_grace_txt;
char *acc_lst_name;
+
+ /* Sigtran connection data */
+ struct {
+ struct osmo_ss7_instance *ss7;
+ 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 a_reset_ctx *reset;
+ } a;
};
/*
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 84855aca3..9053f07e7 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -479,8 +479,9 @@ struct gsm_network {
enum nsap_addr_enc rab_assign_addr_enc;
} iu;
- /* A list with all associated BSCs */
- struct llist_head bscs;
+ struct {
+ struct llist_head bscs;
+ } a;
};
struct osmo_esme;
diff --git a/openbsc/src/libcommon-cs/a_reset.c b/openbsc/src/libcommon-cs/a_reset.c
index 7eebb152d..a6110a22b 100644
--- a/openbsc/src/libcommon-cs/a_reset.c
+++ b/openbsc/src/libcommon-cs/a_reset.c
@@ -132,18 +132,47 @@ static struct osmo_fsm fsm = {
};
/* Create and start state machine which handles the reset/reset-ack procedure */
-void a_reset_start(struct a_reset_ctx *reset)
+struct a_reset_ctx *a_reset_alloc(void *ctx, char *name, void *cb, void *priv)
{
- OSMO_ASSERT(reset);
+ OSMO_ASSERT(name);
+
+ struct a_reset_ctx *reset;
- osmo_fsm_register(&fsm);
+ /* Register the fsm description (if not already done) */
+ if (osmo_fsm_find_by_name(fsm.name) != &fsm)
+ osmo_fsm_register(&fsm);
+
+ /* Allocate and configure a new fsm instance */
+ reset = talloc_zero(ctx, struct a_reset_ctx);
+ OSMO_ASSERT(reset);
+ reset->priv = priv;
+ reset->cb = cb;
+ strncpy(reset->name, name, sizeof(reset->name));
+ reset->conn_loss_counter = 0;
reset->fsm = osmo_fsm_inst_alloc(&fsm, NULL, NULL, LOGL_DEBUG, "FSM RESET INST");
OSMO_ASSERT(reset->fsm);
-
reset->fsm->priv = reset;
+ LOGP(DMSC, LOGL_NOTICE, "(%s) reset handler fsm created.\n", reset->name);
/* kick off reset-ack sending mechanism */
osmo_fsm_inst_state_chg(reset->fsm, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
+
+ return reset;
+}
+
+/* Tear down state machine */
+void a_reset_free(struct a_reset_ctx *reset)
+{
+ OSMO_ASSERT(reset);
+ OSMO_ASSERT(reset->fsm);
+
+ osmo_fsm_inst_free(reset->fsm);
+ reset->fsm = NULL;
+
+ memset(reset, 0, sizeof(*reset));
+ talloc_free(reset);
+
+ LOGP(DMSC, LOGL_NOTICE, "(%s) reset handler fsm destroyed.\n", reset->name);
}
/* Confirm that we sucessfully received a reset acknowlege message */
diff --git a/openbsc/src/libcommon-cs/common_cs.c b/openbsc/src/libcommon-cs/common_cs.c
index 59d496d28..6e9bb4c33 100644
--- a/openbsc/src/libcommon-cs/common_cs.c
+++ b/openbsc/src/libcommon-cs/common_cs.c
@@ -65,7 +65,7 @@ struct gsm_network *gsm_network_init(void *ctx,
INIT_LLIST_HEAD(&net->trans_list);
INIT_LLIST_HEAD(&net->upqueue);
INIT_LLIST_HEAD(&net->subscr_conns);
- INIT_LLIST_HEAD(&net->bscs);
+ INIT_LLIST_HEAD(&net->a.bscs);
net->bsc_subscribers = talloc_zero(net, struct llist_head);
INIT_LLIST_HEAD(net->bsc_subscribers);
diff --git a/openbsc/src/libmsc/a_iface.c b/openbsc/src/libmsc/a_iface.c
index fbd5b9329..1ebb645fa 100644
--- a/openbsc/src/libmsc/a_iface.c
+++ b/openbsc/src/libmsc/a_iface.c
@@ -115,9 +115,9 @@ static struct a_reset_ctx *get_reset_ctx_by_sccp_addr(struct osmo_sccp_addr *add
if (!addr)
return NULL;
- llist_for_each_entry(bsc_ctx, &gsm_network->bscs, list) {
+ llist_for_each_entry(bsc_ctx, &gsm_network->a.bscs, list) {
if (memcmp(&bsc_ctx->called_addr, addr, sizeof(*addr)) == 0)
- return &bsc_ctx->reset;
+ return bsc_ctx->reset;
}
LOGP(DMSC, LOGL_ERROR, "The calling BSC (%s) is unknown to this MSC ...\n",
@@ -199,8 +199,8 @@ int a_iface_tx_paging(const char *imsi, uint32_t tmsi, uint16_t lac)
cil.id_list_len = 1;
/* Deliver paging request to all known BSCs */
- llist_for_each_entry(bsc_ctx, &gsm_network->bscs, list) {
- if (a_reset_conn_ready(&bsc_ctx->reset)) {
+ llist_for_each_entry(bsc_ctx, &gsm_network->a.bscs, list) {
+ if (a_reset_conn_ready(bsc_ctx->reset)) {
LOGP(DMSC, LOGL_DEBUG,
"Passing paging message from MSC %s to BSC %s (imsi=%s, tmsi=0x%08x, lac=%u)\n",
osmo_sccp_addr_dump(&bsc_ctx->calling_addr),
@@ -444,7 +444,6 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
a_conn_info.called_addr = &scu_prim->u.unitdata.called_addr;
a_conn_info.calling_addr = &scu_prim->u.unitdata.calling_addr;
a_conn_info.reset = get_reset_ctx_by_sccp_addr(&scu_prim->u.unitdata.calling_addr);
-
DEBUGP(DMSC, "N-UNITDATA.ind(%s)\n", osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
sccp_rx_udt(scu, &a_conn_info, oph->msg);
break;
@@ -487,61 +486,105 @@ static void a_reset_cb(void *priv)
struct msgb *msg;
struct bsc_context *bsc_ctx = (struct bsc_context*) priv;
+ /* Skip if the A interface is not properly initalized yet */
+ if (!gsm_network)
+ return;
+
/* Clear all now orphaned subscriber connections */
a_clear_all(bsc_ctx->sccp_user, &bsc_ctx->called_addr);
+ /* Send reset to the remote BSC */
LOGP(DMSC, LOGL_NOTICE, "Sending RESET to BSC %s\n", osmo_sccp_addr_dump(&bsc_ctx->called_addr));
msg = gsm0808_create_reset();
osmo_sccp_tx_unitdata_msg(bsc_ctx->sccp_user, &bsc_ctx->calling_addr,
&bsc_ctx->called_addr, msg);
}
-/* Initalize A interface connection between to MSC and BSC */
-int a_init(void *ctx, const char *name, uint32_t local_pc,
- const char *listen_addr, const char *remote_addr, uint16_t local_port, struct gsm_network *network)
+/* Initalize a new A connection for a remote bsc (called by VTY) */
+int a_init(struct gsm_network *network, struct osmo_sccp_addr *calling_addr, struct osmo_sccp_addr *called_addr,
+ struct osmo_ss7_instance *ss7)
{
+ struct bsc_context *bsc_ctx;
+ OSMO_ASSERT(network);
+ OSMO_ASSERT(calling_addr);
+ OSMO_ASSERT(called_addr);
+ OSMO_ASSERT(ss7);
-#define SSN_BSSAP 254 /* SCCP_SSN_BSSAP */
-#define SENDER_PC 1 /* Our local point code */
-
- /* FIXME: Remove hardcoded parameters, use parameters in parameter list */
- struct osmo_sccp_instance *sccp;
- struct osmo_sccp_user *scu;
- struct bsc_context *bsc_ctx;
+ /* Set GSM network variable */
+ /* NOTE: There can only be one gsm network! */
+ if (gsm_network != NULL) {
+ OSMO_ASSERT(gsm_network == network);
+ } else
+ gsm_network = network;
- LOGP(DMSC, LOGL_NOTICE, "Initalizing SCCP connection to stp...\n");
+ /* Generate and fill up a new bsc context */
+ bsc_ctx = talloc_zero(gsm_network, struct bsc_context);
+ OSMO_ASSERT(bsc_ctx);
- gsm_network = network;
- osmo_ss7_init();
+ snprintf(bsc_ctx->name, sizeof(bsc_ctx->name), "%s/%s", osmo_sccp_name_by_addr(calling_addr, ss7),
+ osmo_sccp_name_by_addr(called_addr, ss7));
- /* SCCP Protocol stack */
- sccp =
- osmo_sccp_simple_client(NULL, "osmo-msc", SENDER_PC, OSMO_SS7_ASP_PROT_M3UA, 0, NULL, M3UA_PORT,
+ bsc_ctx->ss7 = ss7;
+ bsc_ctx->sccp =
+ osmo_sccp_simple_client(NULL, bsc_ctx->name, calling_addr->pc, OSMO_SS7_ASP_PROT_M3UA, 0, NULL, M3UA_PORT,
"127.0.0.1");
- scu = osmo_sccp_user_bind(sccp, "osmo-msc", sccp_sap_up, SSN_BSSAP);
-
- /* Add some BSCs to the context list */
- /* FIXME: Make this configurable (VTY!) */
- bsc_ctx = talloc_zero(NULL, struct bsc_context);
- bsc_ctx->reset.priv = bsc_ctx;
- bsc_ctx->reset.cb = a_reset_cb;
- llist_add_tail(&bsc_ctx->list, &gsm_network->bscs);
- bsc_ctx->called_addr.presence = OSMO_SCCP_ADDR_T_SSN | OSMO_SCCP_ADDR_T_PC;
- bsc_ctx->called_addr.ssn = SCCP_SSN_BSSAP;
- bsc_ctx->called_addr.ri = OSMO_SCCP_RI_SSN_PC;
- bsc_ctx->called_addr.pc = 23;
- bsc_ctx->calling_addr.presence = OSMO_SCCP_ADDR_T_SSN | OSMO_SCCP_ADDR_T_PC;
- bsc_ctx->calling_addr.ssn = SCCP_SSN_BSSAP;
- bsc_ctx->calling_addr.ri = OSMO_SCCP_RI_SSN_PC;
- bsc_ctx->calling_addr.pc = 1;
- bsc_ctx->sccp_user = scu;
- bsc_ctx = NULL;
-
- /* Start reset procedure for all BSC connections */
- llist_for_each_entry(bsc_ctx, &gsm_network->bscs, list) {
- a_reset_start(&bsc_ctx->reset);
- }
+ bsc_ctx->sccp_user = osmo_sccp_user_bind(bsc_ctx->sccp, bsc_ctx->name, sccp_sap_up, SCCP_SSN_BSSAP);
+
+ memcpy(&bsc_ctx->called_addr, called_addr, sizeof(*called_addr));
+ memcpy(&bsc_ctx->calling_addr, calling_addr, sizeof(*calling_addr));
+
+ llist_add_tail(&bsc_ctx->list, &gsm_network->a.bscs);
+
+ /* Start reset procedure to make the new connection active */
+ bsc_ctx->reset = a_reset_alloc(bsc_ctx, bsc_ctx->name, a_reset_cb, bsc_ctx);
+
+ LOGP(DMSC, LOGL_NOTICE, "Adding new MSC/BSC connection (%s), MSC=%s,", bsc_ctx->name,
+ osmo_sccp_addr_dump(calling_addr));
+ LOGPC(DMSC, LOGL_NOTICE, " BSC=%s...\n", osmo_sccp_addr_dump(called_addr));
return 0;
}
+
+/* Drop a no longer used A connection (called by VTY) */
+void a_drop(struct osmo_sccp_addr *calling_addr, struct osmo_sccp_addr *called_addr)
+{
+ struct bsc_context *bsc_ctx;
+ struct bsc_context *bsc_ctx_temp;
+
+ OSMO_ASSERT(calling_addr);
+ OSMO_ASSERT(called_addr);
+
+ /* Find the BSC context depending on the given addresses */
+ llist_for_each_entry_safe(bsc_ctx, bsc_ctx_temp, &gsm_network->a.bscs, list) {
+ if (memcmp(&bsc_ctx->calling_addr, calling_addr, sizeof(*calling_addr)) == 0
+ && memcmp(&bsc_ctx->called_addr, called_addr, sizeof(*called_addr)) == 0) {
+
+ OSMO_ASSERT(bsc_ctx->ss7);
+ OSMO_ASSERT(bsc_ctx->sccp);
+ OSMO_ASSERT(bsc_ctx->sccp_user);
+
+ LOGP(DMSC, LOGL_NOTICE, "Removing MSC/BSC connection (%s), MSC=%s,", bsc_ctx->name,
+ osmo_sccp_addr_dump(calling_addr));
+ LOGPC(DMSC, LOGL_NOTICE, " BSC=%s...\n", osmo_sccp_addr_dump(called_addr));
+
+ /* Perform the reset procedure one last time. This will also tear
+ * down all currently open connections. */
+ bsc_ctx->reset->cb(bsc_ctx->reset->priv);
+
+ /* Destroy reset handler FSM, reconnecting is no longer impossible */
+ a_reset_free(bsc_ctx->reset);
+
+ /* Destroy ss7 connection */
+ osmo_sccp_user_unbind(bsc_ctx->sccp_user);
+ osmo_sccp_instance_destroy(bsc_ctx->sccp);
+
+ /* Exterminate bsc context */
+ llist_del(&bsc_ctx->list);
+ memset(bsc_ctx, 0, sizeof(*bsc_ctx));
+ talloc_free(bsc_ctx);
+
+ return;
+ }
+ }
+}
diff --git a/openbsc/src/libmsc/msc_vty.c b/openbsc/src/libmsc/msc_vty.c
index b6fff56af..b9519ceeb 100644
--- a/openbsc/src/libmsc/msc_vty.c
+++ b/openbsc/src/libmsc/msc_vty.c
@@ -32,6 +32,8 @@
#include <openbsc/gsm_subscriber.h>
#include <openbsc/vlr.h>
#include <openbsc/iu.h>
+#include <openbsc/a_iface.h>
+#include <osmocom/sccp/sccp_types.h>
static struct cmd_node msc_node = {
MSC_NODE,
@@ -105,9 +107,96 @@ DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_msc_register_bsc, cfg_msc_register_bsc_cmd,
+ "bsc cs7-instance <0-15> calling-addr NAME called-addr NAME",
+ "Register a new BSC connection to this MSC.\n"
+ "Associated SS7 instance\n"
+ "SS7 instance reference number\n"
+ "Calling Address (local address of this MSC)\n"
+ "SCCP address name\n"
+ "Called Address (remote address of the BSC)\n" "SCCP address name\n")
+{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct osmo_sccp_addr *calling_addr;
+ struct osmo_sccp_addr *called_addr;
+ struct osmo_ss7_instance *inst;
+
+ uint32_t inst_id = atoi(argv[0]);
+ const char *calling_addr_name = argv[1];
+ const char *called_addr_name = argv[2];
+
+ inst = osmo_ss7_instance_find(inst_id);
+ if (!inst) {
+ vty_out(vty, "No SS7 instance %d found%s", inst_id,
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ calling_addr = osmo_sccp_addr_by_name(calling_addr_name, inst);
+ if (!calling_addr) {
+ vty_out(vty, "No sccp address %s found%s", calling_addr_name,
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ called_addr = osmo_sccp_addr_by_name(called_addr_name, inst);
+ if (!called_addr) {
+ vty_out(vty, "No sccp address %s found%s", called_addr_name,
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ a_init(gsmnet, calling_addr, called_addr, inst);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_msc_no_register_bsc, cfg_msc_no_register_bsc_cmd,
+ "no bsc cs7-instance <0-15> calling-addr NAME called-addr NAME",
+ NO_STR
+ "Remove a BSC connection to this MSC.\n"
+ "Associated SS7 instance\n"
+ "SS7 instance reference number\n"
+ "Calling Address (local address of this MSC)\n"
+ "SCCP address name\n"
+ "Called Address (remote address of the BSC)\n" "SCCP address name\n")
+{
+ struct osmo_sccp_addr *calling_addr;
+ struct osmo_sccp_addr *called_addr;
+ struct osmo_ss7_instance *inst;
+
+ uint32_t inst_id = atoi(argv[0]);
+ const char *calling_addr_name = argv[1];
+ const char *called_addr_name = argv[2];
+
+ inst = osmo_ss7_instance_find(inst_id);
+ if (!inst) {
+ vty_out(vty, "No SS7 instance %d found%s", inst_id,
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ calling_addr = osmo_sccp_addr_by_name(calling_addr_name, inst);
+ if (!calling_addr) {
+ vty_out(vty, "No sccp address %s found%s", calling_addr_name,
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ called_addr = osmo_sccp_addr_by_name(called_addr_name, inst);
+ if (!called_addr) {
+ vty_out(vty, "No sccp address %s found%s", called_addr_name,
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ a_drop(calling_addr, called_addr);
+ return CMD_SUCCESS;
+}
+
static int config_write_msc(struct vty *vty)
{
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct bsc_context *bsc_ctx;
vty_out(vty, "msc%s", VTY_NEWLINE);
if (!gsmnet->auto_create_subscr)
@@ -127,6 +216,18 @@ static int config_write_msc(struct vty *vty)
mgcpgw_client_config_write(vty, " ");
iu_vty_config_write(vty, " ");
+ /* write sccp connection configuration */
+ llist_for_each_entry(bsc_ctx, &gsmnet->a.bscs, list) {
+ OSMO_ASSERT(bsc_ctx->ss7);
+ vty_out(vty,
+ " bsc cs7-instance %u calling-addr %s called-addr %s%s",
+ bsc_ctx->ss7->cfg.id,
+ osmo_sccp_name_by_addr(&bsc_ctx->calling_addr,
+ bsc_ctx->ss7),
+ osmo_sccp_name_by_addr(&bsc_ctx->called_addr,
+ bsc_ctx->ss7), VTY_NEWLINE);
+ }
+
return CMD_SUCCESS;
}
@@ -176,6 +277,9 @@ void msc_vty_init(struct gsm_network *msc_network)
install_element(MSC_NODE, &cfg_msc_no_subscr_create_cmd);
install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
+ install_element(MSC_NODE, &cfg_msc_register_bsc_cmd);
+ install_element(MSC_NODE, &cfg_msc_no_register_bsc_cmd);
+
mgcpgw_client_vty_init(MSC_NODE, &msc_network->mgcpgw.conf);
iu_vty_init(MSC_NODE, &msc_network->iu.rab_assign_addr_enc);
}
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
index afb984799..f37caa0d4 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
@@ -198,7 +198,7 @@ static int bssmap_handle_reset_ack(struct bsc_msc_data *msc,
/* Inform the FSM that controls the RESET/RESET-ACK procedure
* that we have successfully received the reset-ack message */
- a_reset_ack_confirm(&msc->msc_con->reset);
+ a_reset_ack_confirm(msc->a.reset);
return 0;
}
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_main.c b/openbsc/src/osmo-bsc/osmo_bsc_main.c
index 1f8f645ac..68f8b492d 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_main.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_main.c
@@ -217,6 +217,10 @@ int main(int argc, char **argv)
bsc_msg_lst_vty_init(tall_bsc_ctx, &access_lists, BSC_NODE);
ctrl_vty_init(tall_bsc_ctx);
+ /* Initalize SS7 */
+ osmo_ss7_init();
+ osmo_ss7_vty_init_sg();
+
INIT_LLIST_HEAD(&access_lists);
/* parse options */
@@ -269,24 +273,6 @@ int main(int argc, char **argv)
}
}
-
- 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_sigtran.c b/openbsc/src/osmo-bsc/osmo_bsc_sigtran.c
index 8364d2aad..1d2a37528 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_sigtran.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_sigtran.c
@@ -88,8 +88,8 @@ static void osmo_bsc_sigtran_tx_reset(struct bsc_msc_data *msc)
struct msgb *msg;
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_sccp_tx_unitdata_msg(msc->a.sccp_user, &msc->a.g_calling_addr,
+ &msc->a.g_called_addr, msg);
}
/* Send reset-ack to MSC */
@@ -98,8 +98,8 @@ void osmo_bsc_sigtran_tx_reset_ack(struct bsc_msc_data *msc)
struct msgb *msg;
LOGP(DMSC, LOGL_NOTICE, "Sending RESET ACK to MSC No.: %i\n", msc->nr);
msg = gsm0808_create_reset_ack();
- osmo_sccp_tx_unitdata_msg(msc->msc_con->sccp_user, &msc->msc_con->g_calling_addr,
- &msc->msc_con->g_called_addr, msg);
+ osmo_sccp_tx_unitdata_msg(msc->a.sccp_user, &msc->a.g_calling_addr,
+ &msc->a.g_called_addr, msg);
}
/* Find an MSC by its sigtran point code */
@@ -107,7 +107,7 @@ 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)
+ if (memcmp(calling_addr, &msc->a.g_called_addr, sizeof(*calling_addr)) == 0)
return msc;
}
@@ -186,7 +186,7 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
/* Incoming data is a sign of a vital connection */
bsc_con = get_bsc_conn_by_conn_id(scu_prim->u.disconnect.conn_id);
if (bsc_con)
- a_reset_conn_success(&bsc_con->msc->msc_con->reset);
+ a_reset_conn_success(bsc_con->msc->a.reset);
rc = handle_data_from_msc(scu_prim->u.data.conn_id, oph->msg);
break;
@@ -206,7 +206,7 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
/* We might have a connectivity problem. Maybe we need to go
* through the reset procedure again? */
if (scu_prim->u.disconnect.cause == 0)
- a_reset_conn_fail(&bsc_con->msc->msc_con->reset);
+ a_reset_conn_fail(bsc_con->msc->a.reset);
rc = osmo_bsc_sigtran_del_conn(bsc_con);
}
@@ -233,7 +233,7 @@ enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, s
LOGP(DMSC, LOGL_NOTICE, "Initalizing resources for new SIGTRAN connection to MSC No.: %i...\n", msc->nr);
- if (a_reset_conn_ready(&msc->msc_con->reset) == false) {
+ if (a_reset_conn_ready(msc->a.reset) == false) {
LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
return BSC_CON_REJECT_NO_LINK;
}
@@ -278,7 +278,7 @@ int osmo_bsc_sigtran_open_conn(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
msc = conn->msc;
- if (a_reset_conn_ready(&msc->msc_con->reset) == false) {
+ if (a_reset_conn_ready(msc->a.reset) == false) {
LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
return -EINVAL;
}
@@ -286,8 +286,8 @@ int osmo_bsc_sigtran_open_conn(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
conn_id = conn->conn_id;
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);
+ rc = osmo_sccp_tx_conn_req_msg(msc->a.sccp_user, conn_id, &msc->a.g_calling_addr,
+ &msc->a.g_called_addr, msg);
return rc;
}
@@ -305,7 +305,7 @@ int osmo_bsc_sigtran_send(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
msc = conn->msc;
- if (a_reset_conn_ready(&msc->msc_con->reset) == false) {
+ if (a_reset_conn_ready(msc->a.reset) == false) {
LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
return -EINVAL;
}
@@ -314,7 +314,7 @@ int osmo_bsc_sigtran_send(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
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);
+ rc = osmo_sccp_tx_data_msg(msc->a.sccp_user, conn_id, msg);
return rc;
}
@@ -336,7 +336,7 @@ int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *conn)
/* This bahaviour might be caused by a bad connection. Maybe we
* will have to go through the reset procedure again */
- a_reset_conn_fail(&conn->msc->msc_con->reset);
+ a_reset_conn_fail(conn->msc->a.reset);
}
llist_del(&conn->entry);
@@ -385,7 +385,7 @@ void osmo_bsc_sigtran_reset(struct bsc_msc_data *msc)
gsm0808_clear(conn->conn);
/* Disconnect all Sigtran connections */
- osmo_sccp_tx_disconn(msc->msc_con->sccp_user, conn->conn_id, &msc->msc_con->g_calling_addr, 0);
+ osmo_sccp_tx_disconn(msc->a.sccp_user, conn->conn_id, &msc->a.g_calling_addr, 0);
/* Delete subscriber connection */
osmo_bsc_sigtran_del_conn(conn);
@@ -414,8 +414,6 @@ int osmo_bsc_sigtran_init(struct llist_head *mscs)
OSMO_ASSERT(mscs);
- osmo_ss7_init();
-
msc_list = mscs;
conn_id_counter = 0;
@@ -425,17 +423,14 @@ int osmo_bsc_sigtran_init(struct llist_head *mscs)
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,
+ msc->a.sccp =
+ osmo_sccp_simple_client(NULL, msc_name, msc->a.g_calling_addr.pc,
OSMO_SS7_ASP_PROT_M3UA, 0, NULL, M3UA_PORT, "127.0.0.1");
- msc->msc_con->sccp_user =
- osmo_sccp_user_bind(msc->msc_con->sccp, msc_name, sccp_sap_up, SCCP_SSN_BSSAP);
+ msc->a.sccp_user =
+ osmo_sccp_user_bind(msc->a.sccp, msc_name, sccp_sap_up, SCCP_SSN_BSSAP);
/* Start MSC reset procedure */
- msc->msc_con->reset.priv = msc;
- msc->msc_con->reset.cb = osmo_bsc_sigtran_reset_cb;
- snprintf(msc->msc_con->reset.name,sizeof(msc->msc_con->reset.name),"MSC No. %u",msc->nr);
- a_reset_start(&msc->msc_con->reset);
+ msc->a.reset = a_reset_alloc(msc, msc_name, osmo_bsc_sigtran_reset_cb, msc);
}
return 0;
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
index 2e2e99bfd..5d6491047 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
@@ -184,6 +184,18 @@ static void write_msc(struct vty *vty, struct bsc_msc_data *msc)
/* write amr options */
write_msc_amr_options(vty, msc);
+
+ /* write sccp connection configuration */
+ if (msc->a.ss7) {
+ vty_out(vty, " cs7-instance %u%s", msc->a.ss7->cfg.id,
+ VTY_NEWLINE);
+ vty_out(vty, " calling-addr %s%s",
+ osmo_sccp_name_by_addr(&msc->a.g_calling_addr,
+ msc->a.ss7), VTY_NEWLINE);
+ vty_out(vty, " called-addr %s%s",
+ osmo_sccp_name_by_addr(&msc->a.g_called_addr,
+ msc->a.ss7), VTY_NEWLINE);
+ }
}
static int config_write_msc(struct vty *vty)
@@ -685,6 +697,80 @@ DEFUN(cfg_msc_no_acc_lst_name,
return CMD_SUCCESS;
}
+DEFUN(cfg_msc_cs7_instance,
+ cfg_msc_cs7_instance_cmd,
+ "cs7-instance <0-15>",
+ "Set Associated SS7 instance.\n" "SS7 instance reference number\n")
+{
+ struct bsc_msc_data *msc = bsc_msc_data(vty);
+ uint32_t inst_id = atoi(argv[0]);
+ struct osmo_ss7_instance *inst;
+
+ inst = osmo_ss7_instance_find(inst_id);
+ if (!inst) {
+ vty_out(vty, "No SS7 instance %d found%s", inst_id,
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ msc->a.ss7 = inst;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_msc_cs7_calling_addr,
+ cfg_msc_cs7_calling_addr_cmd,
+ "calling-addr NAME",
+ "Calling Address (local address of this BSC)\n" "SCCP address name\n")
+{
+ struct bsc_msc_data *msc = bsc_msc_data(vty);
+ const char *calling_addr_name = argv[0];
+ struct osmo_sccp_addr *calling_addr;
+
+ if (!msc->a.ss7) {
+ vty_out(vty, "cs7-instance instance must be configured first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ calling_addr = osmo_sccp_addr_by_name(calling_addr_name, msc->a.ss7);
+ if (!calling_addr) {
+ vty_out(vty, "No sccp address %s found%s", calling_addr_name,
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ memcpy(&msc->a.g_calling_addr, calling_addr, sizeof(*calling_addr));
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_msc_cs7_called_addr,
+ cfg_msc_cs7_called_addr_cmd,
+ "called-addr NAME",
+ "Called Address (remote address of the MSC)\n" "SCCP address name\n")
+{
+ struct bsc_msc_data *msc = bsc_msc_data(vty);
+ const char *called_addr_name = argv[0];
+ struct osmo_sccp_addr *called_addr;
+
+ if (!msc->a.ss7) {
+ vty_out(vty, "cs7-instance instance must be configured first%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ called_addr = osmo_sccp_addr_by_name(called_addr_name, msc->a.ss7);
+ if (!called_addr) {
+ vty_out(vty, "No sccp address %s found%s", called_addr_name,
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ memcpy(&msc->a.g_called_addr, called_addr, sizeof(*called_addr));
+
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_net_bsc_mid_call_text,
cfg_net_bsc_mid_call_text_cmd,
"mid-call-text .TEXT",
@@ -931,6 +1017,9 @@ int bsc_vty_init_extra(void)
install_element(MSC_NODE, &cfg_net_msc_amr_4_75_cmd);
install_element(MSC_NODE, &cfg_msc_acc_lst_name_cmd);
install_element(MSC_NODE, &cfg_msc_no_acc_lst_name_cmd);
+ install_element(MSC_NODE, &cfg_msc_cs7_instance_cmd);
+ install_element(MSC_NODE, &cfg_msc_cs7_calling_addr_cmd);
+ install_element(MSC_NODE, &cfg_msc_cs7_called_addr_cmd);
install_element_ve(&show_statistics_cmd);
install_element_ve(&show_mscs_cmd);
diff --git a/openbsc/src/osmo-msc/msc_main.c b/openbsc/src/osmo-msc/msc_main.c
index c79332cd3..2e225e7a4 100644
--- a/openbsc/src/osmo-msc/msc_main.c
+++ b/openbsc/src/osmo-msc/msc_main.c
@@ -503,8 +503,6 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i
/* Set up IuCS */
//iu_init(tall_msc_ctx, "OsmoMSC", 1, "127.0.0.3", "127.0.0.1", 0, rcvmsg_iu_cs, rx_iu_event);
- /* Set up A interface */
- a_init(tall_msc_ctx, "OsmoMSC_A", 254, "127.0.0.3", "127.0.0.1", 0, msc_network);
if (msc_cmdline_config.daemonize) {
rc = osmo_daemonize();