diff options
-rw-r--r-- | openbsc/include/openbsc/a_iface.h | 16 | ||||
-rw-r--r-- | openbsc/include/openbsc/a_reset.h | 5 | ||||
-rw-r--r-- | openbsc/include/openbsc/bsc_msc.h | 7 | ||||
-rw-r--r-- | openbsc/include/openbsc/bsc_msc_data.h | 10 | ||||
-rw-r--r-- | openbsc/include/openbsc/gsm_data.h | 5 | ||||
-rw-r--r-- | openbsc/src/libcommon-cs/a_reset.c | 37 | ||||
-rw-r--r-- | openbsc/src/libcommon-cs/common_cs.c | 2 | ||||
-rw-r--r-- | openbsc/src/libmsc/a_iface.c | 131 | ||||
-rw-r--r-- | openbsc/src/libmsc/msc_vty.c | 104 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc/osmo_bsc_bssap.c | 2 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc/osmo_bsc_main.c | 22 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc/osmo_bsc_sigtran.c | 45 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc/osmo_bsc_vty.c | 89 | ||||
-rw-r--r-- | openbsc/src/osmo-msc/msc_main.c | 2 |
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(); |