From 68e4be9c845e25f53aea511b1c57340a9da5825c Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 26 May 2018 22:42:29 +0200 Subject: Remove 'struct bsc_msc_connection' + fix IPA-encapsulated CTRL The bsc_msc_connection dates back to the old pre-libosmo-sigtran days, and 90% of the field members weren't used at all (even the new sigtran specific ones!). Let's merge what remains into struct bsc_msc_data. As a side effect, the already dysfunctional "dest A.B.C.D" VTY command has been removed from the MSC node. There's quite a bit of fall-out in the CTRL interface, which was the code with strongest ties to bsc_msc_connection. This was resolved by properly porting CTRL handling over to libosmo-sigtran, meaning that an IPA/SCCPlite connected MSC can now again send CTRL GET/SET commands, and can also receive those selective few TRAPs that old osmo-bsc-sccplite also sent to its MSC[s]. Change-Id: I6b7354f3b23a26bb4eab12213ca3d3b614c8154f Related: OS#2012 --- src/osmo-bsc/osmo_bsc_api.c | 1 + src/osmo-bsc/osmo_bsc_ctrl.c | 144 ++++++++++++++++++++++++++++++++++------ src/osmo-bsc/osmo_bsc_filter.c | 2 +- src/osmo-bsc/osmo_bsc_main.c | 4 -- src/osmo-bsc/osmo_bsc_msc.c | 12 +--- src/osmo-bsc/osmo_bsc_sigtran.c | 35 ++++++++++ src/osmo-bsc/osmo_bsc_vty.c | 71 ++------------------ 7 files changed, 171 insertions(+), 98 deletions(-) (limited to 'src/osmo-bsc') diff --git a/src/osmo-bsc/osmo_bsc_api.c b/src/osmo-bsc/osmo_bsc_api.c index 8c16bde25..8081ea410 100644 --- a/src/osmo-bsc/osmo_bsc_api.c +++ b/src/osmo-bsc/osmo_bsc_api.c @@ -24,6 +24,7 @@ #include #include +#include #include #include diff --git a/src/osmo-bsc/osmo_bsc_ctrl.c b/src/osmo-bsc/osmo_bsc_ctrl.c index 5f88b85f7..7891cf427 100644 --- a/src/osmo-bsc/osmo_bsc_ctrl.c +++ b/src/osmo-bsc/osmo_bsc_ctrl.c @@ -30,30 +30,126 @@ #include #include -#include + +#include + +#include +#include #include #include #include #include -void osmo_bsc_send_trap(struct ctrl_cmd *cmd, struct bsc_msc_connection *msc_con) +extern struct gsm_network *bsc_gsmnet; + +/* Obtain SS7 application server currently handling given MSC (DPC) */ +static struct osmo_ss7_as *msc_get_ss7_as(struct bsc_msc_data *msc) +{ + struct osmo_ss7_route *rt; + struct osmo_ss7_instance *ss7 = osmo_sccp_get_ss7(msc->a.sccp); + rt = osmo_ss7_route_lookup(ss7, msc->a.msc_addr.pc); + if (!rt) + return NULL; + return rt->dest.as; +} + + +/* Encode a CTRL command and send it to the given ASP + * \param[in] asp ASP through which we shall send the encoded message + * \param[in] cmd decoded CTRL command to be encoded and sent. Ownership is *NOT* + * transferred, to permit caller to send the same CMD to several ASPs. + * Caller must hence free 'cmd' itself. + * \returns 0 on success; negative on error */ +static int sccplite_asp_ctrl_cmd_send(struct osmo_ss7_asp *asp, struct ctrl_cmd *cmd) +{ + /* this is basically like libosmoctrl:ctrl_cmd_send(), not for a dedicated + * CTRL connection but for the CTRL piggy-back on the IPA/SCCPlite link */ + struct msgb *msg; + + /* don't attempt to send CTRL on a non-SCCPlite ASP */ + if (asp->cfg.proto != OSMO_SS7_ASP_PROT_IPA) + return 0; + + msg = ctrl_cmd_make(cmd); + if (!msg) + return -1; + + ipa_prepend_header_ext(msg, IPAC_PROTO_EXT_CTRL); + ipa_prepend_header(msg, IPAC_PROTO_OSMO); + + return osmo_ss7_asp_send(asp, msg); +} + +/* Ownership of 'cmd' is *NOT* transferred, to permit caller to send the same CMD to several ASPs. + * Caller must hence free 'cmd' itself. */ +static int sccplite_msc_ctrl_cmd_send(struct bsc_msc_data *msc, struct ctrl_cmd *cmd) +{ + struct osmo_ss7_as *as; + struct osmo_ss7_asp *asp; + unsigned int i; + + as = msc_get_ss7_as(msc); + if (!as) + return -1; + + /* don't attempt to send CTRL on a non-SCCPlite AS */ + if (as->cfg.proto != OSMO_SS7_ASP_PROT_IPA) + return 0; + + /* FIXME: unify with xua_as_transmit_msg() and perform proper ASP lookup */ + for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { + asp = as->cfg.asps[i]; + if (!asp) + continue; + /* FIXME: deal with multiple ASPs per AS */ + return sccplite_asp_ctrl_cmd_send(asp, cmd); + } + return -1; +} + +/* receive + process a CTRL command from the piggy-back on the IPA/SCCPlite link */ +int bsc_sccplite_rx_ctrl(struct osmo_ss7_asp *asp, struct msgb *msg) +{ + struct ctrl_cmd *cmd; + int rc; + + /* caller has already ensured ipaccess_head + ipaccess_head_ext */ + OSMO_ASSERT(msg->l2h); + + /* prase raw (ASCII) CTRL command into ctrl_cmd */ + cmd = ctrl_cmd_parse2(asp, msg); + OSMO_ASSERT(cmd); + msgb_free(msg); + if (cmd->type == CTRL_TYPE_ERROR) + goto send_reply; + + /* handle the CTRL command */ + ctrl_cmd_handle(bsc_gsmnet->ctrl, cmd, bsc_gsmnet); + +send_reply: + rc = sccplite_asp_ctrl_cmd_send(asp, cmd); + talloc_free(cmd); + return rc; +} + + +void osmo_bsc_send_trap(struct ctrl_cmd *cmd, struct bsc_msc_data *msc_data) { struct ctrl_cmd *trap; struct ctrl_handle *ctrl; - struct bsc_msc_data *msc_data; - msc_data = (struct bsc_msc_data *) msc_con->write_queue.bfd.data; ctrl = msc_data->network->ctrl; trap = ctrl_cmd_trap(cmd); if (!trap) { + LOGP(DCTRL, LOGL_ERROR, "Failed to create trap.\n"); return; } ctrl_cmd_send_to_all(ctrl, trap); - ctrl_cmd_send(&msc_con->write_queue, trap); + sccplite_msc_ctrl_cmd_send(msc_data, trap); talloc_free(trap); } @@ -62,12 +158,21 @@ CTRL_CMD_DEFINE_RO(msc_connection_status, "connection_status"); static int get_msc_connection_status(struct ctrl_cmd *cmd, void *data) { struct bsc_msc_data *msc = (struct bsc_msc_data *)cmd->node; + struct osmo_ss7_as *as; + const char *as_state_name; + if (msc == NULL) { cmd->reply = "msc not found"; return CTRL_CMD_ERROR; } + as = msc_get_ss7_as(msc); + if (!as) { + cmd->reply = "AS not found for MSC"; + return CTRL_CMD_ERROR; + } - if (msc->msc_con->is_connected) + as_state_name = osmo_fsm_inst_state_name(as->fi); + if (!strcmp(as_state_name, "AS_ACTIVE")) cmd->reply = "connected"; else cmd->reply = "disconnected"; @@ -80,14 +185,15 @@ static int msc_connection_status = 0; /* XXX unused */ static int get_msc0_connection_status(struct ctrl_cmd *cmd, void *data) { - struct gsm_network *gsmnet = data; - struct bsc_msc_data *msc = osmo_msc_data_find(gsmnet, 0); + struct bsc_msc_data *msc = osmo_msc_data_find(bsc_gsmnet, 0); + void *old_node = cmd->node; + int rc; - if (msc->msc_con->is_connected) - cmd->reply = "connected"; - else - cmd->reply = "disconnected"; - return CTRL_CMD_REPLY; + cmd->node = msc; + rc = get_msc_connection_status(cmd, data); + cmd->node = old_node; + + return rc; } static int msc_connection_status_trap_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) @@ -184,12 +290,12 @@ static int bts_connection_status_trap_cb(unsigned int subsys, unsigned int signa static int get_bts_loc(struct ctrl_cmd *cmd, void *data); -static void generate_location_state_trap(struct gsm_bts *bts, struct bsc_msc_connection *msc_con) +static void generate_location_state_trap(struct gsm_bts *bts, struct bsc_msc_data *msc) { struct ctrl_cmd *cmd; const char *oper, *admin, *policy; - cmd = ctrl_cmd_create(msc_con, CTRL_TYPE_TRAP); + cmd = ctrl_cmd_create(msc, CTRL_TYPE_TRAP); if (!cmd) { LOGP(DCTRL, LOGL_ERROR, "Failed to create TRAP command.\n"); return; @@ -213,7 +319,7 @@ static void generate_location_state_trap(struct gsm_bts *bts, struct bsc_msc_con osmo_mnc_name(bts->network->plmn.mnc, bts->network->plmn.mnc_3_digits)); - osmo_bsc_send_trap(cmd, msc_con); + osmo_bsc_send_trap(cmd, msc); talloc_free(cmd); } @@ -222,7 +328,7 @@ void bsc_gen_location_state_trap(struct gsm_bts *bts) struct bsc_msc_data *msc; llist_for_each_entry(msc, &bts->network->bsc_data->mscs, entry) - generate_location_state_trap(bts, msc->msc_con); + generate_location_state_trap(bts, msc); } static int location_equal(struct bts_location *a, struct bts_location *b) @@ -537,7 +643,7 @@ static int set_net_inform_msc(struct ctrl_cmd *cmd, void *data) trap->id = "0"; trap->variable = "inform-msc-v1"; trap->reply = talloc_strdup(trap, cmd->value); - ctrl_cmd_send(&msc->msc_con->write_queue, trap); + sccplite_msc_ctrl_cmd_send(msc, trap); talloc_free(trap); } @@ -625,7 +731,7 @@ static int msc_signal_handler(unsigned int subsys, unsigned int signal, net = msc->data->network; llist_for_each_entry(bts, &net->bts_list, list) - generate_location_state_trap(bts, msc->data->msc_con); + generate_location_state_trap(bts, msc->data); return 0; } diff --git a/src/osmo-bsc/osmo_bsc_filter.c b/src/osmo-bsc/osmo_bsc_filter.c index 5f60989a7..0d0fc29c6 100644 --- a/src/osmo-bsc/osmo_bsc_filter.c +++ b/src/osmo-bsc/osmo_bsc_filter.c @@ -161,7 +161,7 @@ struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, round_robin: llist_for_each_entry(msc, &bsc->mscs, entry) { - if (!msc->msc_con->is_authenticated) + if (!msc->is_authenticated) continue; if (!is_emerg && msc->type != MSC_CON_TYPE_NORMAL) continue; diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c index db6bcdb2c..095a07a16 100644 --- a/src/osmo-bsc/osmo_bsc_main.c +++ b/src/osmo-bsc/osmo_bsc_main.c @@ -248,8 +248,6 @@ static struct vty_app_info vty_info = { extern int bsc_shutdown_net(struct gsm_network *net); static void signal_handler(int signal) { - struct bsc_msc_data *msc; - fprintf(stdout, "signal %u received\n", signal); switch (signal) { @@ -270,8 +268,6 @@ static void signal_handler(int signal) case SIGUSR2: if (!bsc_gsmnet->bsc_data) return; - llist_for_each_entry(msc, &bsc_gsmnet->bsc_data->mscs, entry) - bsc_msc_lost(msc->msc_con); break; default: break; diff --git a/src/osmo-bsc/osmo_bsc_msc.c b/src/osmo-bsc/osmo_bsc_msc.c index 10f602a09..e00c9ef81 100644 --- a/src/osmo-bsc/osmo_bsc_msc.c +++ b/src/osmo-bsc/osmo_bsc_msc.c @@ -1,6 +1,6 @@ /* * Handle the connection to the MSC. This include ping/timeout/reconnect - * (C) 2008-2009 by Harald Welte + * (C) 2008-2018 by Harald Welte * (C) 2009-2015 by Holger Hans Peter Freyther * (C) 2009-2015 by On-Waves * All Rights Reserved @@ -41,19 +41,12 @@ int osmo_bsc_msc_init(struct bsc_msc_data *data) { - data->msc_con = bsc_msc_create(data, &data->dests); - if (!data->msc_con) { - LOGP(DMSC, LOGL_ERROR, "Creating the MSC network connection failed.\n"); - return -1; - } - /* FIXME: This is a leftover from the old architecture that used * sccp-lite with osmocom specific authentication. Since we now * changed to AoIP the connected status and the authentication * status is managed differently. However osmo_bsc_filter.c still * needs the flags to be set to one. See also: OS#3112 */ - data->msc_con->is_connected = 1; - data->msc_con->is_authenticated = 1; + data->is_authenticated = 1; return 0; } @@ -86,7 +79,6 @@ struct bsc_msc_data *osmo_msc_data_alloc(struct gsm_network *net, int nr) /* Init back pointer */ msc_data->network = net; - INIT_LLIST_HEAD(&msc_data->dests); msc_data->core_plmn = (struct osmo_plmn_id){ .mcc = GSM_MCC_MNC_INVALID, .mnc = GSM_MCC_MNC_INVALID, diff --git a/src/osmo-bsc/osmo_bsc_sigtran.c b/src/osmo-bsc/osmo_bsc_sigtran.c index 2c3507d9e..c33124f70 100644 --- a/src/osmo-bsc/osmo_bsc_sigtran.c +++ b/src/osmo-bsc/osmo_bsc_sigtran.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -512,3 +513,37 @@ fail_auto_cofiguration: "A-interface: More than one invalid/inclomplete configuration detected, unable to revover - check config file!\n"); return -EINVAL; } + +/* this function receives all messages received on an ASP for a PPID / StreamID that + * libosmo-sigtran doesn't know about, such as piggy-backed CTRL and/or MGCP */ +int osmo_ss7_asp_rx_unknown(struct osmo_ss7_asp *asp, int ppid_mux, struct msgb *msg) +{ + struct ipaccess_head *iph; + struct ipaccess_head_ext *iph_ext; + + if (asp->cfg.proto != OSMO_SS7_ASP_PROT_IPA) { + msgb_free(msg); + return 0; + } + + switch (ppid_mux) { + case IPAC_PROTO_OSMO: + if (msg->len < sizeof(*iph) + sizeof(*iph_ext)) { + LOGP(DMSC, LOGL_ERROR, "The message is too short.\n"); + msgb_free(msg); + return -EINVAL; + } + iph = (struct ipaccess_head *) msg->data; + iph_ext = (struct ipaccess_head_ext *) iph->data; + msg->l2h = iph_ext->data; + switch (iph_ext->proto) { + case IPAC_PROTO_EXT_CTRL: + return bsc_sccplite_rx_ctrl(asp, msg); + } + break; + default: + break; + } + msgb_free(msg); + return 0; /* OSMO_SS7_UNKNOWN? */ +} diff --git a/src/osmo-bsc/osmo_bsc_vty.c b/src/osmo-bsc/osmo_bsc_vty.c index bda89c142..d1a82ba92 100644 --- a/src/osmo-bsc/osmo_bsc_vty.c +++ b/src/osmo-bsc/osmo_bsc_vty.c @@ -1,6 +1,7 @@ /* Osmo BSC VTY Configuration */ /* (C) 2009-2015 by Holger Hans Peter Freyther * (C) 2009-2014 by On-Waves + * (C) 2018 by Harald Welte * All Rights Reserved * * This program is free software; you can redistribute it and/or modify @@ -105,8 +106,6 @@ static void write_msc_amr_options(struct vty *vty, struct bsc_msc_data *msc) static void write_msc(struct vty *vty, struct bsc_msc_data *msc) { - struct bsc_msc_dest *dest; - vty_out(vty, "msc %d%s", msc->nr, VTY_NEWLINE); if (msc->core_plmn.mnc != GSM_MCC_MNC_INVALID) vty_out(vty, " core-mobile-network-code %s%s", @@ -154,10 +153,6 @@ static void write_msc(struct vty *vty, struct bsc_msc_data *msc) } - llist_for_each_entry(dest, &msc->dests, list) - vty_out(vty, " dest %s %d %d%s", dest->ip, dest->port, - dest->dscp, VTY_NEWLINE); - vty_out(vty, " type %s%s", msc->type == MSC_CON_TYPE_NORMAL ? "normal" : "local", VTY_NEWLINE); vty_out(vty, " allow-emergency %s%s", msc->allow_emerg ? @@ -337,58 +332,6 @@ error: return CMD_ERR_INCOMPLETE; } -DEFUN(cfg_net_msc_dest, - cfg_net_msc_dest_cmd, - "dest A.B.C.D <1-65000> <0-255>", - "Add a destination to a MUX/MSC\n" - "IP Address\n" "Port\n" "DSCP\n") -{ - struct bsc_msc_dest *dest; - struct bsc_msc_data *data = bsc_msc_data(vty); - - dest = talloc_zero(osmo_bsc_data(vty), struct bsc_msc_dest); - if (!dest) { - vty_out(vty, "%%Failed to create structure.%s", VTY_NEWLINE); - return CMD_WARNING; - } - - dest->ip = talloc_strdup(dest, argv[0]); - if (!dest->ip) { - vty_out(vty, "%%Failed to copy dest ip.%s", VTY_NEWLINE); - talloc_free(dest); - return CMD_WARNING; - } - - dest->port = atoi(argv[1]); - dest->dscp = atoi(argv[2]); - llist_add_tail(&dest->list, &data->dests); - return CMD_SUCCESS; -} - -DEFUN(cfg_net_msc_no_dest, - cfg_net_msc_no_dest_cmd, - "no dest A.B.C.D <1-65000> <0-255>", - NO_STR "Remove a destination to a MUX/MSC\n" - "IP Address\n" "Port\n" "DSCP\n") -{ - struct bsc_msc_dest *dest, *tmp; - struct bsc_msc_data *data = bsc_msc_data(vty); - - int port = atoi(argv[1]); - int dscp = atoi(argv[2]); - - llist_for_each_entry_safe(dest, tmp, &data->dests, list) { - if (port != dest->port || dscp != dest->dscp - || strcmp(dest->ip, argv[0]) != 0) - continue; - - llist_del(&dest->list); - talloc_free(dest); - } - - return CMD_SUCCESS; -} - DEFUN(cfg_net_msc_welcome_ussd, cfg_net_msc_welcome_ussd_cmd, "bsc-welcome-text .TEXT", @@ -787,10 +730,12 @@ DEFUN(show_mscs, { struct bsc_msc_data *msc; llist_for_each_entry(msc, &bsc_gsmnet->bsc_data->mscs, entry) { - vty_out(vty, "MSC Nr: %d is connected: %d auth: %d.%s", - msc->nr, - msc->msc_con ? msc->msc_con->is_connected : -1, - msc->msc_con ? msc->msc_con->is_authenticated : -1, + vty_out(vty, "%d %s %s ", + msc->a.cs7_instance, + osmo_ss7_asp_protocol_name(msc->a.asp_proto), + osmo_sccp_inst_addr_name(msc->a.sccp, &msc->a.bsc_addr)); + vty_out(vty, "%s%s", + osmo_sccp_inst_addr_name(msc->a.sccp, &msc->a.msc_addr), VTY_NEWLINE); } @@ -943,8 +888,6 @@ int bsc_vty_init_extra(void) install_element(MSC_NODE, &cfg_net_bsc_ci_cmd); install_element(MSC_NODE, &cfg_net_bsc_rtp_base_cmd); install_element(MSC_NODE, &cfg_net_bsc_codec_list_cmd); - install_element(MSC_NODE, &cfg_net_msc_dest_cmd); - install_element(MSC_NODE, &cfg_net_msc_no_dest_cmd); install_element(MSC_NODE, &cfg_net_msc_welcome_ussd_cmd); install_element(MSC_NODE, &cfg_net_msc_no_welcome_ussd_cmd); install_element(MSC_NODE, &cfg_net_msc_lost_ussd_cmd); -- cgit v1.2.3