diff --git a/include/osmocom/bsc/ctrl.h b/include/osmocom/bsc/ctrl.h index 86eb3b114..c61e01f85 100644 --- a/include/osmocom/bsc/ctrl.h +++ b/include/osmocom/bsc/ctrl.h @@ -1,6 +1,7 @@ #pragma once #include +#include struct gsm_network; struct gsm_bts; @@ -15,6 +16,10 @@ int bsc_bts_trx_ts_ctrl_cmds_install(void); int bsc_bts_trx_ts_lchan_ctrl_cmds_install(void); void ctrl_generate_bts_location_state_trap(struct gsm_bts *bts, struct bsc_msc_data *msc); void osmo_bsc_send_trap(struct ctrl_cmd *cmd, struct bsc_msc_data *msc_data); +char *lchan_dump_full_ctrl(const void *t, struct gsm_lchan *lchan); +char *ts_lchan_dump_full_ctrl(const void *t, struct gsm_bts_trx_ts *ts); +char *trx_lchan_dump_full_ctrl(const void *t, struct gsm_bts_trx *trx); +char *bts_lchan_dump_full_ctrl(const void *t, struct gsm_bts *bts); enum bsc_ctrl_node { diff --git a/src/osmo-bsc/bsc_ctrl.c b/src/osmo-bsc/bsc_ctrl.c index cfba3e251..aff1d83e6 100644 --- a/src/osmo-bsc/bsc_ctrl.c +++ b/src/osmo-bsc/bsc_ctrl.c @@ -820,6 +820,45 @@ static int set_net_inform_msc(struct ctrl_cmd *cmd, void *data) return CTRL_CMD_HANDLED; } +/* Return full information about all logical channels. + * format: show-lchan.full + * result format: New line delimited list of ,,,,,,,,, + * ,, ,,,,,, + * ,,, + */ +static int get_net_show_lchan_full(struct ctrl_cmd *cmd, void *data) +{ + struct gsm_network *net = cmd->node; + int bts_nr; + bool first_bts = true; + char *bts_dump; + + cmd->reply = talloc_strdup(cmd, ""); + if (!cmd->reply) { + cmd->reply = "OOM"; + return CTRL_CMD_ERROR; + } + + for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) { + bts_dump = bts_lchan_dump_full_ctrl(cmd, gsm_bts_num(net, bts_nr)); + if (!bts_dump) { + cmd->reply = "OOM"; + return CTRL_CMD_ERROR; + } + if (!strlen(bts_dump)) + continue; + cmd->reply = talloc_asprintf_append(cmd->reply, first_bts ? "%s" : "\n%s", bts_dump); + if (!cmd->reply) { + cmd->reply = "OOM"; + return CTRL_CMD_ERROR; + } + first_bts = false; + } + + return CTRL_CMD_REPLY; +} +CTRL_CMD_DEFINE_RO(net_show_lchan_full, "show-lchan full"); + static int bsc_base_ctrl_cmds_install(struct gsm_network *net) { int rc = 0; @@ -837,6 +876,7 @@ static int bsc_base_ctrl_cmds_install(struct gsm_network *net) rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_msc0_connection_status); rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_notification); rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_inform_msc); + rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_show_lchan_full); rc |= ctrl_cmd_install(CTRL_NODE_MSC, &cmd_msc_connection_status); diff --git a/src/osmo-bsc/bts_ctrl.c b/src/osmo-bsc/bts_ctrl.c index eac01bf3b..814a17dca 100644 --- a/src/osmo-bsc/bts_ctrl.c +++ b/src/osmo-bsc/bts_ctrl.c @@ -1479,6 +1479,53 @@ static int get_bts_neighbor_list_si2quater_earfcn(struct ctrl_cmd *cmd, void *da CTRL_CMD_DEFINE_RO(bts_neighbor_list_si2quater_earfcn, "neighbor-list si2quater earfcns"); +char *bts_lchan_dump_full_ctrl(const void *t, struct gsm_bts *bts) +{ + int trx_nr; + bool first_trx = true; + char *trx_dump, *dump; + struct gsm_bts_trx *trx; + + dump = talloc_strdup(t, ""); + if (!dump) + return NULL; + + for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) { + trx = gsm_bts_trx_num(bts, trx_nr); + trx_dump = trx_lchan_dump_full_ctrl(t, trx); + if (!trx_dump) + return NULL; + if (!strlen(trx_dump)) + continue; + dump = talloc_asprintf_append(dump, first_trx ? "%s" : "\n%s", trx_dump); + if (!dump) + return NULL; + first_trx = false; + } + + return dump; +} + +/* Return full information about all logical channels in a BTS. + * format: bts.<0-255>.show-lchan.full + * result format: New line delimited list of ,,,,,,,,, + * ,, ,,,,,, + * ,,, + */ +static int get_bts_show_lchan_full(struct ctrl_cmd *cmd, void *data) +{ + struct gsm_bts *bts = cmd->node; + + cmd->reply = bts_lchan_dump_full_ctrl(cmd, bts); + if (!cmd->reply) { + cmd->reply = "OOM"; + return CTRL_CMD_ERROR; + } + + return CTRL_CMD_REPLY; +} +CTRL_CMD_DEFINE_RO(bts_show_lchan_full, "show-lchan full"); + int bsc_bts_ctrl_cmds_install(void) { int rc = 0; @@ -1523,6 +1570,7 @@ int bsc_bts_ctrl_cmds_install(void) rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_rach_max_trans); rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_neighbor_list_si2quater_uarfcn); rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_neighbor_list_si2quater_earfcn); + rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_show_lchan_full); rc |= neighbor_ident_ctrl_init(); diff --git a/src/osmo-bsc/bts_trx_ctrl.c b/src/osmo-bsc/bts_trx_ctrl.c index d5e8f5a83..1e30e8518 100644 --- a/src/osmo-bsc/bts_trx_ctrl.c +++ b/src/osmo-bsc/bts_trx_ctrl.c @@ -97,6 +97,51 @@ static int set_trx_max_power(struct ctrl_cmd *cmd, void *_data) } CTRL_CMD_DEFINE(trx_max_power, "max-power-reduction"); +char *trx_lchan_dump_full_ctrl(const void *t, struct gsm_bts_trx *trx) +{ + int ts_nr; + bool first_ts = true; + char *ts_dump, *dump; + + dump = talloc_strdup(t, ""); + if (!dump) + return NULL; + + for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) { + ts_dump = ts_lchan_dump_full_ctrl(t, &trx->ts[ts_nr]); + if (!ts_dump) + return NULL; + if (!strlen(ts_dump)) + continue; + dump = talloc_asprintf_append(dump, first_ts ? "%s" : "\n%s", ts_dump); + if (!dump) + return NULL; + first_ts = false; + } + + return dump; +} + +/* Return full information about all logical channels in a TRX. + * format: bts.<0-255>.trx.<0-255>.show-lchan.full + * result format: New line delimited list of ,,,,,,,,, + * ,, ,,,,,, + * ,,, + */ +static int get_trx_show_lchan_full(struct ctrl_cmd *cmd, void *data) +{ + struct gsm_bts_trx *trx = cmd->node; + + cmd->reply = trx_lchan_dump_full_ctrl(cmd, trx); + if (!cmd->reply) { + cmd->reply = "OOM"; + return CTRL_CMD_ERROR; + } + + return CTRL_CMD_REPLY; +} +CTRL_CMD_DEFINE_RO(trx_show_lchan_full, "show-lchan full"); + int bsc_bts_trx_ctrl_cmds_install(void) { int rc = 0; @@ -104,6 +149,7 @@ int bsc_bts_trx_ctrl_cmds_install(void) rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_max_power); rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_arfcn); rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_rf_locked); + rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_show_lchan_full); rc |= bsc_bts_trx_ts_ctrl_cmds_install(); diff --git a/src/osmo-bsc/bts_trx_ts_ctrl.c b/src/osmo-bsc/bts_trx_ts_ctrl.c index f0a592d44..a1a17f0d2 100644 --- a/src/osmo-bsc/bts_trx_ts_ctrl.c +++ b/src/osmo-bsc/bts_trx_ts_ctrl.c @@ -94,6 +94,48 @@ static int set_ts_hopping_arfcn_del(struct ctrl_cmd *cmd, void *data) /* Parameter format: "(|all)" */ CTRL_CMD_DEFINE_WO(ts_hopping_arfcn_del, "hopping-arfcn-del"); +char *ts_lchan_dump_full_ctrl(const void *t, struct gsm_bts_trx_ts *ts) +{ + bool first_lchan = true; + char *lchan_dump, *dump; + struct gsm_lchan *lchan; + + dump = talloc_strdup(t, ""); + if (!dump) + return NULL; + + ts_for_n_lchans(lchan, ts, ts->max_lchans_possible) { + lchan_dump = lchan_dump_full_ctrl(t, lchan); + if (!lchan_dump) + return NULL; + dump = talloc_asprintf_append(dump, first_lchan ? "%s" : "\n%s", lchan_dump); + if (!dump) + return NULL; + first_lchan = false; + } + + return dump; +} + +/* Return full information about all logical channels in a timeslot. + * format: bts.<0-255>.trx.<0-255>.ts.<0-8>.show-lchan.full + * result format: New line delimited list of ,,,,,,,,, + * ,, ,,,,,, + * ,,, + */ +static int get_ts_show_lchan_full(struct ctrl_cmd *cmd, void *data) +{ + struct gsm_bts_trx_ts *ts = cmd->node; + + cmd->reply = ts_lchan_dump_full_ctrl(cmd, ts); + if (!cmd->reply) { + cmd->reply = "OOM"; + return CTRL_CMD_ERROR; + } + + return CTRL_CMD_REPLY; +} +CTRL_CMD_DEFINE_RO(ts_show_lchan_full, "show-lchan full"); int bsc_bts_trx_ts_ctrl_cmds_install(void) { @@ -101,6 +143,7 @@ int bsc_bts_trx_ts_ctrl_cmds_install(void) rc |= ctrl_cmd_install(CTRL_NODE_TS, &cmd_ts_hopping_arfcn_add); rc |= ctrl_cmd_install(CTRL_NODE_TS, &cmd_ts_hopping_arfcn_del); + rc |= ctrl_cmd_install(CTRL_NODE_TS, &cmd_ts_show_lchan_full); rc |= bsc_bts_trx_ts_lchan_ctrl_cmds_install(); diff --git a/src/osmo-bsc/bts_trx_ts_lchan_ctrl.c b/src/osmo-bsc/bts_trx_ts_lchan_ctrl.c index 6ddbe1ec2..be5e755cb 100644 --- a/src/osmo-bsc/bts_trx_ts_lchan_ctrl.c +++ b/src/osmo-bsc/bts_trx_ts_lchan_ctrl.c @@ -68,55 +68,41 @@ static int set_lchan_ms_power(struct ctrl_cmd *cmd, void *data) CTRL_CMD_DEFINE(lchan_ms_power, "ms-power"); -/* Return full information about a logical channel. - * format: bts.<0-255>.trx.<0-255>.ts.<0-8>.lchan.<0-8>.show.full - * result format: ,,,,,,,,,,, - * ,,,,,,,, - * , - */ -static int get_lchan_show_full(struct ctrl_cmd *cmd, void *data) + +char *lchan_dump_full_ctrl(const void *t, struct gsm_lchan *lchan) { - struct gsm_lchan *lchan = cmd->node; struct in_addr ia; char *interference = ",", *tmsi = "", *ipa_bound = ",,", *ipa_conn = ",,"; if (lchan->interf_dbm != INTERF_DBM_UNKNOWN) { - interference = talloc_asprintf(cmd, "%d,%u", lchan->interf_dbm, lchan->interf_band); - if (!interference) { - cmd->reply = "OOM"; - return CTRL_CMD_ERROR; - } + interference = talloc_asprintf(t, "%d,%u", lchan->interf_dbm, lchan->interf_band); + if (!interference) + return NULL; } if (lchan->conn && lchan->conn->bsub && lchan->conn->bsub->tmsi != GSM_RESERVED_TMSI) { - tmsi = talloc_asprintf(cmd, "0x%08x", lchan->conn->bsub->tmsi); - if (!tmsi) { - cmd->reply = "OOM"; - return CTRL_CMD_ERROR; - } + tmsi = talloc_asprintf(t, "0x%08x", lchan->conn->bsub->tmsi); + if (!tmsi) + return NULL; } if (is_ipa_abisip_bts(lchan->ts->trx->bts) && lchan->abis_ip.bound_ip) { ia.s_addr = htonl(lchan->abis_ip.bound_ip); - ipa_bound = talloc_asprintf(cmd, "%s,%u,%u", inet_ntoa(ia), lchan->abis_ip.bound_port, + ipa_bound = talloc_asprintf(t, "%s,%u,%u", inet_ntoa(ia), lchan->abis_ip.bound_port, lchan->abis_ip.conn_id); - if (!ipa_bound) { - cmd->reply = "OOM"; - return CTRL_CMD_ERROR; - } + if (!ipa_bound) + return NULL; } if (is_ipa_abisip_bts(lchan->ts->trx->bts) && lchan->abis_ip.connect_ip) { ia.s_addr = htonl(lchan->abis_ip.connect_ip); - ipa_conn = talloc_asprintf(cmd, "%s,%u,0x%02x", inet_ntoa(ia), lchan->abis_ip.connect_port, + ipa_conn = talloc_asprintf(t, "%s,%u,0x%02x", inet_ntoa(ia), lchan->abis_ip.connect_port, lchan->abis_ip.speech_mode); - if (!ipa_conn) { - cmd->reply = "OOM"; - return CTRL_CMD_ERROR; - } + if (!ipa_conn) + return NULL; } - cmd->reply = talloc_asprintf(cmd, "%u,%u,%u,%u,%s,%u,%s,%s,%u,%u,%s,%s,%s,%s,%s,%s", + return talloc_asprintf(t, "%u,%u,%u,%u,%s,%u,%s,%s,%u,%u,%s,%s,%s,%s,%s,%s", lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, @@ -133,6 +119,18 @@ static int get_lchan_show_full(struct ctrl_cmd *cmd, void *data) ipa_bound, ipa_conn ); +} + +/* Return full information about a logical channel. + * format: bts.<0-255>.trx.<0-255>.ts.<0-8>.lchan.<0-8>.show.full + * result format: ,,,,,,,,,,, + * ,,,,,,,, + * , + */ +static int get_lchan_show_full(struct ctrl_cmd *cmd, void *data) +{ + struct gsm_lchan *lchan = cmd->node; + cmd->reply = lchan_dump_full_ctrl(cmd, lchan); if (!cmd->reply) { cmd->reply = "OOM"; return CTRL_CMD_ERROR;