diff options
author | Vadim Yanitskiy <axilirator@gmail.com> | 2019-05-16 06:13:29 +0700 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2019-06-03 07:18:41 +0000 |
commit | 8014917f0a803d0f5be97bc77d3dc1dcd03e176b (patch) | |
tree | c204c3b6c2fc99822ed2c5922c1a9b49ccdd90cc | |
parent | a2273f5f1d3719543eb0ab922c19952b651a2ccf (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.c | 445 |
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; } |