aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/chan_alloc.h12
-rw-r--r--openbsc/src/chan_alloc.c49
-rw-r--r--openbsc/src/vty_interface.c32
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]",