bsc: Prepare to have multiple MSC connections

We now have a list of MSCs but in the code we will
try to access the MSC with the nr 0.
diff --git a/openbsc/include/openbsc/osmo_msc_data.h b/openbsc/include/openbsc/osmo_msc_data.h
index 384549e..0f3f927 100644
--- a/openbsc/include/openbsc/osmo_msc_data.h
+++ b/openbsc/include/openbsc/osmo_msc_data.h
@@ -1,8 +1,8 @@
 /*
  * Data for the true BSC
  *
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2011 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -36,6 +36,8 @@
 };
 
 struct osmo_msc_data {
+	struct llist_head entry;
+
 	/* Back pointer */
 	struct gsm_network *network;
 
@@ -62,6 +64,8 @@
 
 	/* mgcp agent */
 	struct osmo_wqueue mgcp_agent;
+
+	int nr;
 };
 
 /*
@@ -71,7 +75,7 @@
 	struct gsm_network *network;
 
 	/* msc configuration */
-	struct osmo_msc_data msc;
+	struct llist_head mscs;
 
 	/* rf ctl related bits */
 	char *mid_call_txt;
@@ -87,4 +91,8 @@
 
 int osmo_bsc_audio_init(struct gsm_network *network);
 
+struct osmo_msc_data *osmo_msc_data_find(struct gsm_network *, int);
+struct osmo_msc_data *osmo_msc_data_alloc(struct gsm_network *, int);
+
+
 #endif
diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c
index a731c1a..6eb39b0 100644
--- a/openbsc/src/libcommon/gsm_data.c
+++ b/openbsc/src/libcommon/gsm_data.c
@@ -87,6 +87,7 @@
 
 	/* Init back pointer */
 	net->bsc_data->network = net;
+	INIT_LLIST_HEAD(&net->bsc_data->mscs);
 
 	net->country_code = country_code;
 	net->network_code = network_code;
@@ -141,14 +142,6 @@
 
 	net->mncc_recv = mncc_recv;
 
-	INIT_LLIST_HEAD(&net->bsc_data->msc.dests);
-	net->bsc_data->msc.ping_timeout = 20;
-	net->bsc_data->msc.pong_timeout = 5;
-	net->bsc_data->msc.core_ncc = -1;
-	net->bsc_data->msc.core_mcc = -1;
-	net->bsc_data->msc.rtp_base = 4000;
-	net->bsc_data->msc.network = net;
-
 	gsm_net_update_ctype(net);
 
 	return net;
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_main.c b/openbsc/src/osmo-bsc/osmo_bsc_main.c
index 6e34105..63e1d8e 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_main.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_main.c
@@ -144,6 +144,8 @@
 extern int bsc_shutdown_net(struct gsm_network *net);
 static void signal_handler(int signal)
 {
+	struct osmo_msc_data *msc;
+
 	fprintf(stdout, "signal %u received\n", signal);
 
 	switch (signal) {
@@ -163,11 +165,8 @@
 	case SIGUSR2:
 		if (!bsc_gsmnet->bsc_data)
 			return;
-		if (!bsc_gsmnet->bsc_data->msc.msc_con)
-			return;
-		if (!bsc_gsmnet->bsc_data->msc.msc_con->is_connected)
-			return;
-		bsc_msc_lost(bsc_gsmnet->bsc_data->msc.msc_con);
+		llist_for_each_entry(msc, &bsc_gsmnet->bsc_data->mscs, entry)
+			bsc_msc_lost(msc->msc_con);
 		break;
 	default:
 		break;
@@ -391,6 +390,7 @@
 
 int main(int argc, char **argv)
 {
+	struct osmo_msc_data *msc;
 	struct osmo_bsc_data *data;
 	int rc;
 
@@ -443,11 +443,14 @@
 		}
 	}
 
-	if (osmo_bsc_msc_init(&bsc_gsmnet->bsc_data->msc) != 0) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to start up. Exiting.\n");
-		exit(1);
+	llist_for_each_entry(msc, &bsc_gsmnet->bsc_data->mscs, entry) {
+		if (osmo_bsc_msc_init(msc) != 0) {
+			LOGP(DNAT, LOGL_ERROR, "Failed to start up. Exiting.\n");
+			exit(1);
+		}
 	}
 
+
 	if (osmo_bsc_sccp_init(bsc_gsmnet) != 0) {
 		LOGP(DNM, LOGL_ERROR, "Failed to register SCCP.\n");
 		exit(1);
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_msc.c b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
index b2962a9..617a59a 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_msc.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
@@ -455,3 +455,43 @@
 
 	return 0;
 }
+
+struct osmo_msc_data *osmo_msc_data_find(struct gsm_network *net, int nr)
+{
+	struct osmo_msc_data *msc_data;
+
+	llist_for_each_entry(msc_data, &net->bsc_data->mscs, entry)
+		if (msc_data->nr == nr)
+			return msc_data;
+	return NULL;
+}
+
+struct osmo_msc_data *osmo_msc_data_alloc(struct gsm_network *net, int nr)
+{
+	struct osmo_msc_data *msc_data;
+
+	/* check if there is already one */
+	msc_data = osmo_msc_data_find(net, nr);
+	if (msc_data)
+		return msc_data;
+
+	msc_data = talloc_zero(net, struct osmo_msc_data);
+	if (!msc_data)
+		return NULL;
+
+	llist_add_tail(&msc_data->entry, &net->bsc_data->mscs);
+
+	/* Init back pointer */
+	msc_data->network = net;
+
+	INIT_LLIST_HEAD(&msc_data->dests);
+	msc_data->ping_timeout = 20;
+	msc_data->pong_timeout = 5;
+	msc_data->core_ncc = -1;
+	msc_data->core_mcc = -1;
+	msc_data->rtp_base = 4000;
+
+	msc_data->nr = 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 6ac3007..cc4eedf 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
@@ -195,7 +195,12 @@
 	struct sccp_connection *sccp;
 
 	net = conn->bts->network;
-	msc = &net->bsc_data->msc;
+	msc = osmo_msc_data_find(net, 0);
+	if (!msc) {
+		LOGP(DMSC, LOGL_ERROR, "Failed to select a MSC.\n");
+		return -1;
+	}
+
 	if (!msc->msc_con->is_authenticated) {
 		LOGP(DMSC, LOGL_ERROR, "Not connected to a MSC. Not forwarding data.\n");
 		return -1;
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
index 8e687e3..8cf5a14 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
@@ -36,7 +36,7 @@
 
 static struct osmo_msc_data *osmo_msc_data(struct vty *vty)
 {
-	return &bsc_gsmnet->bsc_data->msc;
+	return osmo_msc_data_find(bsc_gsmnet, (int) vty->index);
 }
 
 static struct cmd_node msc_node = {
@@ -48,17 +48,23 @@
 DEFUN(cfg_net_msc, cfg_net_msc_cmd,
       "msc", "Configure MSC details")
 {
-	vty->index = bsc_gsmnet;
-	vty->node = MSC_NODE;
+	int index = 0;
+	struct osmo_msc_data *msc;
 
+	msc = osmo_msc_data_alloc(bsc_gsmnet, index);
+	if (!msc) {
+		vty_out(vty, "%%Failed to allocate MSC data.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	vty->index = (void *) index;
+	vty->node = MSC_NODE;
 	return CMD_SUCCESS;
 }
 
-static int config_write_msc(struct vty *vty)
+static void write_msc(struct vty *vty, struct osmo_msc_data *msc)
 {
 	struct bsc_msc_dest *dest;
-	struct osmo_bsc_data *bsc = osmo_bsc_data(vty);
-	struct osmo_msc_data *msc = &bsc->msc;
 
 	vty_out(vty, "msc%s", VTY_NEWLINE);
 	if (msc->bsc_token)
@@ -95,6 +101,15 @@
 	llist_for_each_entry(dest, &msc->dests, list)
 		vty_out(vty, " dest %s %d %d%s", dest->ip, dest->port,
 			dest->dscp, VTY_NEWLINE);
+}
+
+static int config_write_msc(struct vty *vty)
+{
+	struct osmo_msc_data *msc;
+	struct osmo_bsc_data *bsc = osmo_bsc_data(vty);
+
+	llist_for_each_entry(msc, &bsc->mscs, entry)
+		write_msc(vty, msc);
 
 	if (bsc->mid_call_txt)
 		vty_out(vty, " mid-call-text %s%s", bsc->mid_call_txt, VTY_NEWLINE);