aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2019-05-16 06:13:29 +0700
committerHarald Welte <laforge@gnumonks.org>2019-06-03 07:18:41 +0000
commit8014917f0a803d0f5be97bc77d3dc1dcd03e176b (patch)
treec204c3b6c2fc99822ed2c5922c1a9b49ccdd90cc
parenta2273f5f1d3719543eb0ab922c19952b651a2ccf (diff)
libmsc/msc_vty.c: refactor 'show subscr / conn / trans' commands
The current way of printing subscriber, connection, and transaction info is ugly (sorry) and has several problems: - the terminal width should be large enough to fit quite long lines, otherwise the output is unreadable and looks misaligned; - some fields (such as subscriber name) can be larger than it's expected, so either they're getting truncated, or again, the output is misaligned and unreadable; - adding new info fields would require one to think about the alignment and would make the output even more cumbersome. Here is an example output of 'show connection' command: _Subscriber_______________________________________ _LAC_ _RAN___________________ _MSC-A_state_________ _MSC-A_use_ IMSI-123456789012345:MSISDN-12345:TMSI-0x12345678 1 GERAN-A-4294967295:A5-3 WAIT_CLASSMARK_UPDATE 2=cm_service,trans_cc IMSI-123456789012356:MSISDN-234567:TMSI-0x123ABC78 65535 UTRAN-Iu-4294967295 COMMUNICATING 2=cm_service,trans_sms IMSI-262073993158656:MSISDN-123456:TMSI-0x493026BA 1 GERAN-A-1 MSC_A_ST_COMMUNICATING 1=1 (silent_call) Another 'show subscriber' command mixes the information about subscriber, its connections and transactions without any alignment, what also decreases the readability. This change introduces a hierarchical approach, based on the old 'field per line' formatting. First of all, the VTY commands were extended with optional flags: show connection [trans] show subscriber cache [(conn|trans|conn+trans)] show subscriber TYPE ID [(conn|trans|conn+trans)] so it can be decided, whether to print child connections and/or transaction, or not. For example: show connection trans would print all connections and their child transactions with hierarchical alignment: Connection #00: Subscriber: IMSI-262073993158656:MSISDN-123456:TMSI-0x76760B75 RAN connection: GERAN-A-1 RAN connection state: MSC_A_ST_COMMUNICATING LAC / cell ID: 1 / 0 Use count total: 1 Use count: 1 (silent_call) Transaction #00: Unique (global) identifier: 0x00000000 GSM 04.07 identifier (MT): 0 Type: silent-call another example is: show subscriber cache conn+trans which would print all known subscribers, their active connections and transactions: Subscriber #00: MSISDN: 123456 LAC / cell ID: 1 / 0 RAN type: GERAN-A IMSI: 262073993158656 TMSI: 76760B75 ... Connection: RAN connection: GERAN-A-1 RAN connection state: MSC_A_ST_COMMUNICATING ... Transaction #00: Unique (global) identifier: 0x00000000 GSM 04.07 identifier (MT): 0 Type: silent-call Transaction #01: Unique (global) identifier: 0x00000001 GSM 04.07 identifier (MO): 0 Type: SMS Transaction #02: Unique (global) identifier: 0x00000002 GSM 04.07 identifier (MT): 0 Type: SMS Please note that we don't print redundant info in child nodes (i.e. connection and transaction info), such as subscriber name in connection info, nor connection name in transaction info - it is clear from the hierarchical formatting. Change-Id: I5e58b56204c3f3d019e8d4c3c96cefdbb4af4d47
-rw-r--r--src/libmsc/msc_vty.c445
1 files changed, 283 insertions, 162 deletions
diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c
index 0c07bc217..5b0cfc4af 100644
--- a/src/libmsc/msc_vty.c
+++ b/src/libmsc/msc_vty.c
@@ -661,58 +661,6 @@ DEFUN(show_bsc, show_bsc_cmd,
return CMD_SUCCESS;
}
-/*
-_Subscriber_______________________________________ _LAC_ _RAN___________________ _MSC-A_state_________ _MSC-A_use_
-IMSI-123456789012345:MSISDN-12345:TMSI-0x12345678 1 GERAN-A-4294967295:A5-3 WAIT_CLASSMARK_UPDATE 2=cm_service,trans_cc
-IMSI-123456789012356:MSISDN-234567:TMSI-0x123ABC78 65535 UTRAN-Iu-4294967295 COMMUNICATING 2=cm_service,trans_sms
-IMSI-123456789012367:MSISDN-98712345890:TMSI-0xF.. - EUTRAN-SGs RELEASING 0=none
-IMSI-123456789012378:HONR-12345432101 2 MSC-901-700-423:9876 REMOTE_MSC_A 1=inter_msc
-*/
-static void vty_dump_one_conn(struct vty *vty, const struct msub *msub, int *idx)
-{
- struct msc_a *msc_a = msub_msc_a(msub);
- struct vlr_subscr *vsub = msub_vsub(msub);
- char buf[128];
-
- if (!(*idx))
- vty_out(vty,
- "_Subscriber_______________________________________ _LAC_ _RAN___________________"
- " _MSC-A_state_________ _MSC-A_use_%s",
- VTY_NEWLINE);
- (*idx)++;
-
- vty_out(vty, "%50s %5u %23s %20s %d=%s%s",
- vlr_subscr_short_name(msub_vsub(msub), 50),
- vsub ? vsub->cgi.lai.lac : 0,
- msub_ran_conn_name(msub),
- osmo_fsm_inst_state_name(msc_a->c.fi),
- osmo_use_count_total(&msc_a->use_count),
- osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
- VTY_NEWLINE);
-}
-
-DEFUN(show_msc_conn, show_msc_conn_cmd,
- "show connection", SHOW_STR "Subscriber Connections\n")
-{
- struct msub *msub;
- int idx = 0;
- llist_for_each_entry(msub, &msub_list, entry) {
- vty_dump_one_conn(vty, msub, &idx);
- }
- return CMD_SUCCESS;
-}
-
-static void vty_trans_hdr(struct vty *vty)
-{
- if (llist_empty(&gsmnet->trans_list))
- return;
-
- vty_out(vty,
- "_Subscriber_______________________________________ _RAN___________________"
- " _P__ TI CallRef_ _state_%s",
- VTY_NEWLINE);
-}
-
static const char *get_trans_proto_str(const struct gsm_trans *trans)
{
static char buf[256];
@@ -725,146 +673,311 @@ static const char *get_trans_proto_str(const struct gsm_trans *trans)
trans->cc.T308_second);
break;
case TRANS_SMS:
- snprintf(buf, sizeof(buf), "%s %s",
+ snprintf(buf, sizeof(buf), "CP:%s RP:%s",
gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
break;
default:
- buf[0] = '\0';
- break;
+ return NULL;
}
return buf;
}
-static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans)
+/* Prefix a given format string with a given amount of spaces */
+#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
+ vty_out(vty, "%*s" fmt, offset, "", ##args)
+
+#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
+ MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
+ name, 30 - (int)strlen(name), "", \
+ flag ? "true" : "false", \
+ VTY_NEWLINE)
+
+enum msc_vty_dump_flags {
+ MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
+ MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
+ MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
+};
+
+static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
+ int offset, uint8_t dump_flags)
{
- vty_out(vty, "%50s %23s %4s %02u %08x %s%s",
- vlr_subscr_short_name(msc_a_vsub(trans->msc_a), 50),
- msub_ran_conn_name(trans->msc_a->c.msub),
- trans_type_name(trans->type),
- trans->transaction_id,
- trans->callref,
- get_trans_proto_str(trans),
- VTY_NEWLINE);
+ const char *proto_str;
+
+ if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
+ MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
+ vlr_subscr_name(msc_a_vsub(trans->msc_a)),
+ VTY_NEWLINE);
+ }
+
+ if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
+ MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
+ trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
+ : "(not established)",
+ VTY_NEWLINE);
+ }
+
+ MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
+ trans->callref, VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
+ (trans->transaction_id & 0x08) ? "MO" : "MT",
+ trans->transaction_id,
+ VTY_NEWLINE);
+
+ MSC_VTY_DUMP(vty, offset, "Type: %s%s",
+ trans_type_name(trans->type),
+ VTY_NEWLINE);
+
+ if ((proto_str = get_trans_proto_str(trans))) {
+ MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
+ proto_str, VTY_NEWLINE);
+ }
}
-DEFUN(show_msc_transaction, show_msc_transaction_cmd,
- "show transaction", SHOW_STR "Transactions\n")
+static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
+ int offset, uint8_t dump_flags)
{
- struct gsm_trans *trans;
+ struct vlr_subscr *vsub = msub_vsub(msub);
+ struct msc_a *msc_a = msub_msc_a(msub);
+ char buf[128];
- vty_trans_hdr(vty);
- llist_for_each_entry(trans, &gsmnet->trans_list, entry)
- vty_dump_one_trans(vty, trans);
+ if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
+ dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
+ MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
+ vlr_subscr_name(vsub),
+ VTY_NEWLINE);
+ }
- return CMD_SUCCESS;
+ MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
+ msub_ran_conn_name(msub),
+ VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
+ osmo_fsm_inst_state_name(msc_a->c.fi),
+ VTY_NEWLINE);
+
+ if (vsub) {
+ MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
+ vsub->cgi.lai.lac, vsub->cgi.cell_identity,
+ VTY_NEWLINE);
+ }
+
+ MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
+ osmo_use_count_total(&msc_a->use_count),
+ VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
+ osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
+ VTY_NEWLINE);
+
+ /* Transactions of this connection */
+ if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
+ struct gsm_trans *trans;
+ unsigned int i = 0;
+
+ /* Both subscriber and connection info is already printed */
+ dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
+ dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
+
+ llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
+ if (trans->msc_a != msc_a)
+ continue;
+ MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
+ i++, VTY_NEWLINE);
+ vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
+ }
+ }
}
-static void subscr_dump_full_vty(struct vty *vty, struct vlr_subscr *vsub)
+static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
+ int offset, uint8_t dump_flags)
{
- struct gsm_trans *trans;
char buf[128];
- if (strlen(vsub->name))
- vty_out(vty, " Name: '%s'%s", vsub->name, VTY_NEWLINE);
- if (strlen(vsub->msisdn))
- vty_out(vty, " Extension: %s%s", vsub->msisdn,
- VTY_NEWLINE);
- vty_out(vty, " LAC: %d/0x%x%s",
- vsub->cgi.lai.lac, vsub->cgi.lai.lac, VTY_NEWLINE);
- vty_out(vty, " RAN: %s%s",
- osmo_rat_type_name(vsub->cs.attached_via_ran), VTY_NEWLINE);
- vty_out(vty, " IMSI: %s%s", vsub->imsi, VTY_NEWLINE);
- if (vsub->tmsi != GSM_RESERVED_TMSI)
- vty_out(vty, " TMSI: %08X%s", vsub->tmsi,
- VTY_NEWLINE);
- if (vsub->tmsi_new != GSM_RESERVED_TMSI)
- vty_out(vty, " new TMSI: %08X%s", vsub->tmsi_new,
- VTY_NEWLINE);
- if (vsub->imei[0] != '\0')
- vty_out(vty, " IMEI: %s%s", vsub->imei, VTY_NEWLINE);
- if (vsub->imeisv[0] != '\0')
- vty_out(vty, " IMEISV: %s%s", vsub->imeisv, VTY_NEWLINE);
-
- vty_out(vty, " Flags: %s", VTY_NEWLINE);
- vty_out(vty, " IMSI detached: %s%s",
- vsub->imsi_detached_flag ? "true" : "false", VTY_NEWLINE);
- vty_out(vty, " Conf. by radio contact: %s%s",
- vsub->conf_by_radio_contact_ind ? "true" : "false",
- VTY_NEWLINE);
- vty_out(vty, " Subscr. data conf. by HLR: %s%s",
- vsub->sub_dataconf_by_hlr_ind ? "true" : "false", VTY_NEWLINE);
- vty_out(vty, " Location conf. in HLR: %s%s",
- vsub->loc_conf_in_hlr_ind ? "true" : "false", VTY_NEWLINE);
- vty_out(vty, " Subscriber dormant: %s%s",
- vsub->dormant_ind ? "true" : "false", VTY_NEWLINE);
- vty_out(vty, " Received cancel locataion: %s%s",
- vsub->cancel_loc_rx ? "true" : "false", VTY_NEWLINE);
- vty_out(vty, " MS not reachable: %s%s",
- vsub->ms_not_reachable_flag ? "true" : "false", VTY_NEWLINE);
- vty_out(vty, " LA allowed: %s%s",
- vsub->la_allowed ? "true" : "false", VTY_NEWLINE);
+ if (strlen(vsub->name)) {
+ MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
+ vsub->name, VTY_NEWLINE);
+ }
+ if (strlen(vsub->msisdn)) {
+ MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
+ vsub->msisdn, VTY_NEWLINE);
+ }
+
+ MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
+ vsub->cgi.lai.lac, vsub->cgi.cell_identity,
+ VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
+ osmo_rat_type_name(vsub->cs.attached_via_ran),
+ VTY_NEWLINE);
+
+ MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
+ vsub->imsi, VTY_NEWLINE);
+ if (vsub->tmsi != GSM_RESERVED_TMSI) {
+ MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
+ vsub->tmsi, VTY_NEWLINE);
+ }
+ if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
+ MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
+ vsub->tmsi_new, VTY_NEWLINE);
+ }
+ if (vsub->imei[0] != '\0') {
+ MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
+ vsub->imei, VTY_NEWLINE);
+ }
+ if (vsub->imeisv[0] != '\0') {
+ MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
+ vsub->imeisv, VTY_NEWLINE);
+ }
+
+ MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
+ MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
+ vsub->imsi_detached_flag);
+ MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
+ vsub->conf_by_radio_contact_ind);
+ MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
+ vsub->sub_dataconf_by_hlr_ind);
+ MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
+ vsub->loc_conf_in_hlr_ind);
+ MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
+ vsub->dormant_ind);
+ MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
+ vsub->cancel_loc_rx);
+ MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
+ vsub->ms_not_reachable_flag);
+ MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
+ vsub->la_allowed);
if (vsub->last_tuple) {
struct vlr_auth_tuple *t = vsub->last_tuple;
- vty_out(vty, " A3A8 last tuple (used %d times):%s",
- t->use_count, VTY_NEWLINE);
- vty_out(vty, " seq # : %d%s",
- t->key_seq, VTY_NEWLINE);
- vty_out(vty, " RAND : %s%s",
- osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
- VTY_NEWLINE);
- vty_out(vty, " SRES : %s%s",
- osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
- VTY_NEWLINE);
- vty_out(vty, " Kc : %s%s",
- osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
- VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
+ t->use_count, VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
+ t->key_seq, VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
+ osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
+ VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
+ osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
+ VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
+ osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
+ VTY_NEWLINE);
}
- vty_out(vty, " Paging: %s paging for %d requests%s",
- vsub->cs.is_paging ? "is" : "not",
- llist_count(&vsub->cs.requests),
- VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
+ vsub->cs.is_paging ? "is" : "not",
+ llist_count(&vsub->cs.requests),
+ VTY_NEWLINE);
/* SGs related */
- vty_out(vty, " SGs-state: %s%s",
- osmo_fsm_inst_state_name(vsub->sgs_fsm), VTY_NEWLINE);
- if (strlen(vsub->sgs.mme_name))
- vty_out(vty, " SGs-MME: %s%s", vsub->sgs.mme_name, VTY_NEWLINE);
- else
- vty_out(vty, " SGs-MME: (none)%s", VTY_NEWLINE);
-
- vty_out(vty, " Use: %s%s", osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count), VTY_NEWLINE);
-
- /* Connection */
- if (vsub->msc_conn_ref) {
+ MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
+ osmo_fsm_inst_state_name(vsub->sgs_fsm),
+ VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
+ strlen(vsub->sgs.mme_name) ?
+ vsub->sgs.mme_name : "(none)",
+ VTY_NEWLINE);
+
+ MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
+ osmo_use_count_total(&vsub->use_count),
+ VTY_NEWLINE);
+ MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
+ osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
+ VTY_NEWLINE);
+
+ /* Connection(s) and/or transactions of this subscriber */
+ if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
struct msub *msub = msub_for_vsub(vsub);
- int idx = 0;
- if (msub) {
- vty_dump_one_conn(vty, msub, &idx);
+ if (!msub)
+ return;
+
+ /* Subscriber info is already printed */
+ dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
+
+ MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
+ vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
+ } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
+ struct gsm_trans *trans;
+ unsigned int i = 0;
+
+ /* Subscriber info is already printed */
+ dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
+ /* Do not print connection info, but mention it */
+ dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
+
+ llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
+ if (trans->vsub != vsub)
+ continue;
+ MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
+ i++, VTY_NEWLINE);
+ vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
}
}
+}
+
+DEFUN(show_msc_transaction, show_msc_transaction_cmd,
+ "show transaction",
+ SHOW_STR "Transactions\n")
+{
+ struct gsm_trans *trans;
+ uint8_t flags = 0x00;
+ unsigned int i = 0;
+
+ flags |= MSC_VTY_DUMP_F_CONNECTION;
+ flags |= MSC_VTY_DUMP_F_SUBSCR;
- /* Transactions */
- vty_trans_hdr(vty);
llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
- if (trans->vsub != vsub)
- continue;
- vty_dump_one_trans(vty, trans);
+ vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
+ vty_dump_one_trans(vty, trans, 4, flags);
}
+
+ return CMD_SUCCESS;
}
+DEFUN(show_msc_conn, show_msc_conn_cmd,
+ "show connection [trans]",
+ SHOW_STR "Subscriber Connections\n"
+ "Show child transactions of each connection\n")
+{
+ uint8_t flags = 0x00;
+ unsigned int i = 0;
+ struct msub *msub;
+
+ if (argc > 0)
+ flags |= MSC_VTY_DUMP_F_TRANSACTION;
+ flags |= MSC_VTY_DUMP_F_SUBSCR;
+
+ llist_for_each_entry(msub, &msub_list, entry) {
+ vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
+ vty_dump_one_conn(vty, msub, 4, flags);
+ }
+
+ return CMD_SUCCESS;
+}
+
+#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
+#define SUBSCR_FLAGS_HELP \
+ "Show child connections\n" \
+ "Show child transactions\n" \
+ "Show child connections and transactions\n"
+
/* Subscriber */
-DEFUN(show_subscr_cache,
- show_subscr_cache_cmd,
- "show subscriber cache",
+DEFUN(show_subscr_cache, show_subscr_cache_cmd,
+ "show subscriber cache " SUBSCR_FLAGS,
SHOW_STR "Show information about subscribers\n"
- "Display contents of subscriber cache\n")
+ "Display contents of subscriber cache\n"
+ SUBSCR_FLAGS_HELP)
{
struct vlr_subscr *vsub;
- int count = 0;
+ unsigned int count = 0;
+ uint8_t flags = 0x00;
+ unsigned int i = 0;
+
+ if (argc && strcmp(argv[0], "conn") == 0)
+ flags |= MSC_VTY_DUMP_F_CONNECTION;
+ else if (argc && strcmp(argv[0], "trans") == 0)
+ flags |= MSC_VTY_DUMP_F_TRANSACTION;
+ else if (argc && strcmp(argv[0], "conn+trans") == 0)
+ flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
if (++count > 100) {
@@ -872,8 +985,8 @@ DEFUN(show_subscr_cache,
" stopping here.%s", count-1, VTY_NEWLINE);
break;
}
- vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
- subscr_dump_full_vty(vty, vsub);
+ vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
+ vty_dump_one_subscr(vty, vsub, 4, flags);
}
return CMD_SUCCESS;
@@ -982,14 +1095,14 @@ static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
"Legacy alias for 'imsi'\n" \
"Identifier for the subscriber\n"
-DEFUN(show_subscr,
- show_subscr_cmd,
- "show subscriber " SUBSCR_TYPES " ID",
- SHOW_STR SUBSCR_HELP)
+DEFUN(show_subscr, show_subscr_cmd,
+ "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
+ SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
{
- struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
- argv[1]);
+ struct vlr_subscr *vsub;
+ uint8_t flags = 0x00;
+ vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
if (!vsub) {
vty_out(vty, "%% No subscriber found for %s %s%s",
argv[0], argv[1], VTY_NEWLINE);
@@ -1001,7 +1114,15 @@ DEFUN(show_subscr,
* this, and since this is not multi-threaded, this vlr_subscr_put() cannot possibly reach a count of 0. */
vlr_subscr_put(vsub, VSUB_USE_VTY);
- subscr_dump_full_vty(vty, vsub);
+ if (argc > 2 && strcmp(argv[2], "conn") == 0)
+ flags |= MSC_VTY_DUMP_F_CONNECTION;
+ else if (argc > 2 && strcmp(argv[2], "trans") == 0)
+ flags |= MSC_VTY_DUMP_F_TRANSACTION;
+ else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
+ flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
+
+ vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
+ vty_dump_one_subscr(vty, vsub, 4, flags);
return CMD_SUCCESS;
}