diff options
-rw-r--r-- | openbsc/include/openbsc/chan_alloc.h | 12 | ||||
-rw-r--r-- | openbsc/src/chan_alloc.c | 49 | ||||
-rw-r--r-- | openbsc/src/vty_interface.c | 32 |
3 files changed, 93 insertions, 0 deletions
diff --git a/openbsc/include/openbsc/chan_alloc.h b/openbsc/include/openbsc/chan_alloc.h index 38855d1ee..fa8663056 100644 --- a/openbsc/include/openbsc/chan_alloc.h +++ b/openbsc/include/openbsc/chan_alloc.h @@ -49,4 +49,16 @@ void lchan_free(struct gsm_lchan *lchan); /* Consider releasing the channel */ int lchan_auto_release(struct gsm_lchan *lchan); +struct load_counter { + unsigned int total; + unsigned int used; +}; + +struct pchan_load { + struct load_counter pchan[GSM_PCHAN_UNKNOWN]; +}; + +void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts); +void network_chan_load(struct pchan_load *pl, struct gsm_network *net); + #endif /* _CHAN_ALLOC_H */ diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index c42b60b46..632860814 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -121,6 +121,7 @@ static const u_int8_t subslots_per_pchan[] = { [GSM_PCHAN_TCH_F] = 1, [GSM_PCHAN_TCH_H] = 2, [GSM_PCHAN_SDCCH8_SACCH8C] = 8, + /* FIXME: what about dynamic TCH_F_TCH_H ? */ }; static struct gsm_lchan * @@ -329,3 +330,51 @@ struct gsm_lchan *lchan_for_subscr(struct gsm_subscriber *subscr) return NULL; } + +void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts) +{ + struct gsm_bts_trx *trx; + + llist_for_each_entry(trx, &bts->trx_list, list) { + int i; + + /* skip administratively deactivated tranxsceivers */ + if (trx->nm_state.availability != NM_AVSTATE_OK || + trx->bb_transc.nm_state.availability != NM_AVSTATE_OK) + continue; + + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { + struct gsm_bts_trx_ts *ts = &trx->ts[i]; + struct load_counter *pl = &cl->pchan[ts->pchan]; + int j; + + /* skip administratively deactivated timeslots */ + if (ts->nm_state.availability != NM_AVSTATE_OK) + continue; + + for (j = 0; j < subslots_per_pchan[ts->pchan]; j++) { + struct gsm_lchan *lchan = &ts->lchan[j]; + + pl->total++; + + switch (lchan->state) { + case LCHAN_S_NONE: + break; + default: + pl->used++; + break; + } + } + } + } +} + +void network_chan_load(struct pchan_load *pl, struct gsm_network *net) +{ + struct gsm_bts *bts; + + memset(pl, 0, sizeof(*pl)); + + llist_for_each_entry(bts, &net->bts_list, list) + bts_chan_load(pl, bts); +} diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index fdc678a3b..077e1d03f 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -33,6 +33,7 @@ #include <openbsc/e1_input.h> #include <openbsc/abis_nm.h> #include <openbsc/gsm_utils.h> +#include <openbsc/chan_alloc.h> #include <openbsc/db.h> #include <openbsc/talloc.h> @@ -74,8 +75,30 @@ static void net_dump_nmstate(struct vty *vty, struct gsm_nm_state *nms) nm_avail_name(nms->availability), VTY_NEWLINE); } +static void dump_pchan_load_vty(struct vty *vty, char *prefix, + const struct pchan_load *pl) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pl->pchan); i++) { + const struct load_counter *lc = &pl->pchan[i]; + unsigned int percent; + + if (lc->total == 0) + continue; + + percent = (lc->used * 100) / lc->total; + + vty_out(vty, "%s%20s: %3u%% (%u/%u)%s", prefix, + gsm_pchan_name(i), percent, lc->used, lc->total, + VTY_NEWLINE); + } +} + static void net_dump_vty(struct vty *vty, struct gsm_network *net) { + struct pchan_load pl; + vty_out(vty, "BSC is on Country Code %u, Network Code %u " "and has %u BTS%s", net->country_code, net->network_code, net->num_bts, VTY_NEWLINE); @@ -97,6 +120,9 @@ static void net_dump_vty(struct vty *vty, struct gsm_network *net) VTY_NEWLINE); vty_out(vty, " Handover: %s%s", net->handover.active ? "On" : "Off", VTY_NEWLINE); + network_chan_load(&pl, net); + vty_out(vty, " Current Channel Load:%s", VTY_NEWLINE); + dump_pchan_load_vty(vty, " ", &pl); } DEFUN(show_net, show_net_cmd, "show network", @@ -128,6 +154,8 @@ static void e1isl_dump_vty(struct vty *vty, struct e1inp_sign_link *e1l) static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) { + struct pchan_load pl; + vty_out(vty, "BTS %u is of %s type in band %s, has CI %u LAC %u, " "BSIC %u, TSC %u and %u TRX%s", bts->nr, btstype2str(bts->type), gsm_band_name(bts->band), @@ -157,6 +185,10 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) e1isl_dump_vty(vty, bts->oml_link); } /* FIXME: oml_link, chan_desc */ + memset(&pl, 0, sizeof(pl)); + bts_chan_load(&pl, bts); + vty_out(vty, " Current Channel Load:%s", VTY_NEWLINE); + dump_pchan_load_vty(vty, " ", &pl); } DEFUN(show_bts, show_bts_cmd, "show bts [number]", |