From 0559bd977572a2c14189db3dda2f0cac30448e26 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 6 Sep 2021 22:02:38 +0200 Subject: add CTRL 'rf_states' and 'bts.N.rf_states' These commands return a listing of OML state, RF policy as well as RSL connection status for each TRX in the form: ,,,,,;,,... For example, the root node 'rf_states' may return: 0,0,operational,unlocked,on,rsl-up;1,0,operational,unlocked,on,rsl-down;2,0,inoperational,locked,on,rsl-down; A 'bts.N.rf_states' returns the same form of string, but lists only the TRX for the given BTS nr. Note, there is already a CTRL command 'bts.N.rf_state' (singular 'rf_state', not plural 'rf_states'), which only reflects the overall status of all TRX combined. This new command has per-TRX resolution. The rf-policy is so far always looked up in the global gsm_network flag, as does the old 'rf_state' command; see osmo_bsc_rf_get_policy_by_bts() which does not depend on the specific BTS at all. This may be worth revisiting in the future, so I am already including the rf-policy in the rf_state string for each TRX, even though it is globally identical. Related: SYS#5542 Related: I01e6f391a5e71b0606c42be9b57f8a1687d59bcb (osmo-ttcn3-hacks) Change-Id: I14fa2678fc8f2c11a879c5e9615ac552782c5b7e --- include/osmocom/bsc/osmo_bsc_rf.h | 5 +++ src/osmo-bsc/bsc_ctrl_commands.c | 38 ++++++++++++++++++++ src/osmo-bsc/bsc_rf_ctrl.c | 76 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) diff --git a/include/osmocom/bsc/osmo_bsc_rf.h b/include/osmocom/bsc/osmo_bsc_rf.h index 56ac980ca..f88ccbf6a 100644 --- a/include/osmocom/bsc/osmo_bsc_rf.h +++ b/include/osmocom/bsc/osmo_bsc_rf.h @@ -60,7 +60,12 @@ const char *osmo_bsc_rf_get_policy_name(enum osmo_bsc_rf_policy policy); enum osmo_bsc_rf_opstate osmo_bsc_rf_get_opstate_by_bts(struct gsm_bts *bts); enum osmo_bsc_rf_adminstate osmo_bsc_rf_get_adminstate_by_bts(struct gsm_bts *bts); enum osmo_bsc_rf_policy osmo_bsc_rf_get_policy_by_bts(struct gsm_bts *bts); +enum osmo_bsc_rf_opstate osmo_bsc_rf_get_opstate_by_trx(struct gsm_bts_trx *trx); +enum osmo_bsc_rf_adminstate osmo_bsc_rf_get_adminstate_by_trx(struct gsm_bts_trx *trx); struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net); void osmo_bsc_rf_schedule_lock(struct osmo_bsc_rf *rf, char cmd); +char *bsc_rf_states_of_bts_c(void *ctx, struct gsm_bts *bts); +char *bsc_rf_states_c(void *ctx); + #endif diff --git a/src/osmo-bsc/bsc_ctrl_commands.c b/src/osmo-bsc/bsc_ctrl_commands.c index be83b1b49..3b8125a78 100644 --- a/src/osmo-bsc/bsc_ctrl_commands.c +++ b/src/osmo-bsc/bsc_ctrl_commands.c @@ -420,6 +420,42 @@ static int get_bts_rf_state(struct ctrl_cmd *cmd, void *data) } CTRL_CMD_DEFINE_RO(bts_rf_state, "rf_state"); +/* Return a list of the states of each TRX for a given BTS: + * ,,,,;,,... + */ +static int get_bts_rf_states(struct ctrl_cmd *cmd, void *data) +{ + struct gsm_bts *bts = cmd->node; + + if (!bts) { + cmd->reply = "bts not found."; + return CTRL_CMD_ERROR; + } + + cmd->reply = bsc_rf_states_of_bts_c(cmd, bts); + if (!cmd->reply) { + cmd->reply = "OOM."; + return CTRL_CMD_ERROR; + } + + return CTRL_CMD_REPLY; +} +CTRL_CMD_DEFINE_RO(bts_rf_states, "rf_states"); + +/* Return a list of the states of each TRX for all BTS: + * ,,,,;,,... + */ +static int get_net_rf_states(struct ctrl_cmd *cmd, void *data) +{ + cmd->reply = bsc_rf_states_c(cmd); + if (!cmd->reply) { + cmd->reply = "OOM."; + return CTRL_CMD_ERROR; + } + return CTRL_CMD_REPLY; +} +CTRL_CMD_DEFINE_RO(net_rf_states, "rf_states"); + static int get_net_rf_lock(struct ctrl_cmd *cmd, void *data) { struct gsm_network *net = cmd->node; @@ -609,6 +645,7 @@ int bsc_base_ctrl_cmds_install(void) rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mcc_mnc_apply); rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_rf_lock); rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_bts_num); + rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_rf_states); rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_lac); rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_ci); @@ -619,6 +656,7 @@ int bsc_base_ctrl_cmds_install(void) rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_oml_up); rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_gprs_mode); rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_rf_state); + rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_rf_states); rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_c0_power_red); rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_max_power); diff --git a/src/osmo-bsc/bsc_rf_ctrl.c b/src/osmo-bsc/bsc_rf_ctrl.c index a845859be..7040da473 100644 --- a/src/osmo-bsc/bsc_rf_ctrl.c +++ b/src/osmo-bsc/bsc_rf_ctrl.c @@ -124,6 +124,82 @@ enum osmo_bsc_rf_policy osmo_bsc_rf_get_policy_by_bts(struct gsm_bts *bts) } } +enum osmo_bsc_rf_opstate osmo_bsc_rf_get_opstate_by_trx(struct gsm_bts_trx *trx) +{ + if (trx->mo.nm_state.operational == NM_OPSTATE_ENABLED) + return OSMO_BSC_RF_OPSTATE_OPERATIONAL; + return OSMO_BSC_RF_OPSTATE_INOPERATIONAL; +} + +enum osmo_bsc_rf_adminstate osmo_bsc_rf_get_adminstate_by_trx(struct gsm_bts_trx *trx) +{ + if (trx->mo.nm_state.administrative == NM_STATE_UNLOCKED) + return OSMO_BSC_RF_ADMINSTATE_UNLOCKED; + return OSMO_BSC_RF_ADMINSTATE_LOCKED; +} + +/* Return a string listing the state of the given TRX. + * The string has the form: + * ,,,,,; + */ +static int bsc_rf_state_of_trx_buf(char *buf, size_t buflen, struct gsm_bts_trx *trx) +{ + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; + OSMO_STRBUF_PRINTF(sb, "%u,%u,%s,%s,%s,%s;", + trx->bts->nr, trx->nr, + osmo_bsc_rf_get_opstate_name(osmo_bsc_rf_get_opstate_by_trx(trx)), + osmo_bsc_rf_get_adminstate_name(osmo_bsc_rf_get_adminstate_by_trx(trx)), + osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(trx->bts)), + trx->rsl_link_primary ? "rsl-up" : "rsl-down"); + return sb.chars_needed; +} + +static int bsc_rf_states_of_bts_buf(char *buf, size_t buflen, struct gsm_bts *bts) +{ + struct gsm_bts_trx *trx; + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; + + llist_for_each_entry(trx, &bts->trx_list, list) { + OSMO_STRBUF_APPEND(sb, bsc_rf_state_of_trx_buf, trx); + } + return sb.chars_needed; +} + +/* Return a string listing the states of each TRX for the given BTS. + * The string has the form: + * ,,,,,;,,...;...; + * \param ctx Talloc context to allocate the returned string from. + * \param bts BTS of which to list the TRX states. + * \return talloc allocated string. + */ +char *bsc_rf_states_of_bts_c(void *ctx, struct gsm_bts *bts) +{ + OSMO_NAME_C_IMPL(ctx, 256, "ERROR", bsc_rf_states_of_bts_buf, bts); +} + +static int bsc_rf_states_buf(char *buf, size_t buflen) +{ + struct gsm_bts *bts; + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; + + llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) { + OSMO_STRBUF_APPEND(sb, bsc_rf_states_of_bts_buf, bts); + } + return sb.chars_needed; +} + +/* Return a string listing the states of all TRX of all BTS. + * The string has the form: + * ,,,,,;,,...;...; + * \param ctx Talloc context to allocate the returned string from. + * \param bts BTS of which to list the TRX states, or NULL to list all TRX of all BTS. + * \return talloc allocated string. + */ +char *bsc_rf_states_c(void *ctx) +{ + OSMO_NAME_C_IMPL(ctx, 4096, "ERROR", bsc_rf_states_buf); +} + static int lock_each_trx(struct gsm_network *net, bool lock) { struct gsm_bts *bts; -- cgit v1.2.3