From b908cb7e0ed9e10ee7ced8083d4abdfb9ca2e61c Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 22 Dec 2009 13:09:29 +0100 Subject: [PATCH] Display current channel usage load in 'show bts' and 'show network' This is just the load at one given instant. We definitely also want to see some averages and record the measurements in a database later. --- openbsc/include/openbsc/chan_alloc.h | 12 +++++++ openbsc/src/chan_alloc.c | 49 ++++++++++++++++++++++++++++ openbsc/src/vty_interface.c | 32 ++++++++++++++++++ 3 files changed, 93 insertions(+) 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 #include #include +#include #include #include @@ -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]",