aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2018-07-12 05:00:55 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2018-07-28 12:18:23 +0200
commita07b6674531d201feeb628f0a51356eac9f11f0f (patch)
treeb30eb7a1d413c588e70fd32ce6dabac9832fdfd0
parent6d568ed7ff8f7ccc8b751671ff8a4a8793ebcac0 (diff)
vty: 'handover any': pick more random chans, use lchan_select_by_type()
The 'handover any' VTY command is only useful for testing. It is even more useful if it doesn't always pick the first used lchan but produces more random handovers. The algorithm takes a random number as input, iterates over used lchans once, and if the random number is larger, takes modulo of the nr of used lchans counted. A second iteration will then produce a match. Instead of figuring out the lchan type logic in bsc_vty.c, just use lchan_select_by_type(); Change-Id: I50b70e02d665b967e401db65581e110bc83101e7
-rw-r--r--src/osmo-bsc/bsc_vty.c96
1 files changed, 46 insertions, 50 deletions
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index 594069631..e99029a95 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -68,6 +68,7 @@
#include <osmocom/bsc/gsm_timers.h>
#include <osmocom/bsc/timeslot_fsm.h>
#include <osmocom/bsc/lchan_fsm.h>
+#include <osmocom/bsc/lchan_select.h>
#include <osmocom/bsc/gsm_timers.h>
#include <osmocom/bsc/mgw_endpoint_fsm.h>
@@ -1605,36 +1606,48 @@ DEFUN(assignment_subscr_conn,
return ho_or_as(vty, argv, argc);
}
-static struct gsm_lchan *find_used_voice_lchan(struct vty *vty)
+static struct gsm_lchan *find_used_voice_lchan(struct vty *vty, int random_idx)
{
struct gsm_bts *bts;
struct gsm_network *network = gsmnet_from_vty(vty);
- llist_for_each_entry(bts, &network->bts_list, list) {
- struct gsm_bts_trx *trx;
+ while (1) {
+ int count = 0;
+ llist_for_each_entry(bts, &network->bts_list, list) {
+ struct gsm_bts_trx *trx;
- llist_for_each_entry(trx, &bts->trx_list, list) {
- int i;
- for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
- struct gsm_bts_trx_ts *ts = &trx->ts[i];
- struct gsm_lchan *lchan;
-
- if (ts->fi->state != TS_ST_IN_USE)
- continue;
-
- ts_for_each_lchan(lchan, ts) {
- if (lchan_state_is(lchan, LCHAN_ST_ESTABLISHED)
- && (lchan->type == GSM_LCHAN_TCH_F
- || lchan->type == GSM_LCHAN_TCH_H)) {
-
- vty_out(vty, "Found voice call: %s%s",
- gsm_lchan_name(lchan), VTY_NEWLINE);
- lchan_dump_full_vty(vty, lchan);
- return lchan;
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[i];
+ struct gsm_lchan *lchan;
+
+ if (ts->fi->state != TS_ST_IN_USE)
+ continue;
+
+ ts_for_each_lchan(lchan, ts) {
+ if (lchan_state_is(lchan, LCHAN_ST_ESTABLISHED)
+ && (lchan->type == GSM_LCHAN_TCH_F
+ || lchan->type == GSM_LCHAN_TCH_H)) {
+
+ if (count == random_idx) {
+ vty_out(vty, "Found voice call: %s%s",
+ gsm_lchan_name(lchan),
+ VTY_NEWLINE);
+ lchan_dump_full_vty(vty, lchan);
+ return lchan;
+ }
+ count ++;
+ }
}
}
}
}
+
+ if (!count)
+ break;
+ /* there are used lchans, but random_idx is > count. Iterate again. */
+ random_idx %= count;
}
vty_out(vty, "Cannot find any ongoing voice calls%s", VTY_NEWLINE);
@@ -1642,7 +1655,7 @@ static struct gsm_lchan *find_used_voice_lchan(struct vty *vty)
}
static struct gsm_bts *find_other_bts_with_free_slots(struct vty *vty, struct gsm_bts *not_this_bts,
- enum gsm_phys_chan_config free_type)
+ enum gsm_chan_t free_type)
{
struct gsm_bts *bts;
struct gsm_network *network = gsmnet_from_vty(vty);
@@ -1654,30 +1667,14 @@ static struct gsm_bts *find_other_bts_with_free_slots(struct vty *vty, struct gs
continue;
llist_for_each_entry(trx, &bts->trx_list, list) {
- int i;
- /* FIXME: use lchan_select_by_type() instead */
- for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
- struct gsm_bts_trx_ts *ts = &trx->ts[i];
- struct gsm_lchan *lchan;
-
- /* skip administratively deactivated timeslots */
- if (!nm_is_running(&ts->mo.nm_state))
- continue;
-
- if (ts->pchan_is != free_type)
- continue;
+ struct gsm_lchan *lchan = lchan_select_by_type(bts, free_type);
+ if (!lchan)
+ continue;
- ts_for_each_lchan(lchan, ts) {
- if (lchan->fi->state != LCHAN_ST_UNUSED)
- continue;
- vty_out(vty, "Found unused %s slot: %s%s",
- gsm_pchan_name(free_type),
- gsm_lchan_name(lchan),
- VTY_NEWLINE);
- lchan_dump_full_vty(vty, lchan);
- return bts;
- }
- }
+ vty_out(vty, "Found unused %s slot: %s%s",
+ gsm_lchant_name(free_type), gsm_lchan_name(lchan), VTY_NEWLINE);
+ lchan_dump_full_vty(vty, lchan);
+ return bts;
}
}
vty_out(vty, "Cannot find any BTS (other than BTS %u) with free %s lchan%s",
@@ -1694,12 +1691,11 @@ DEFUN(handover_any, handover_any_cmd,
struct gsm_lchan *from_lchan;
struct gsm_bts *to_bts;
- from_lchan = find_used_voice_lchan(vty);
+ from_lchan = find_used_voice_lchan(vty, random());
if (!from_lchan)
return CMD_WARNING;
- to_bts = find_other_bts_with_free_slots(vty, from_lchan->ts->trx->bts,
- from_lchan->ts->pchan_is);
+ to_bts = find_other_bts_with_free_slots(vty, from_lchan->ts->trx->bts, from_lchan->type);
if (!to_bts)
return CMD_WARNING;
@@ -1714,7 +1710,7 @@ DEFUN(assignment_any, assignment_any_cmd,
{
struct gsm_lchan *from_lchan;
- from_lchan = find_used_voice_lchan(vty);
+ from_lchan = find_used_voice_lchan(vty, random());
if (!from_lchan)
return CMD_WARNING;
@@ -1733,7 +1729,7 @@ DEFUN(handover_any_to_arfcn_bsic, handover_any_to_arfcn_bsic_cmd,
struct handover_out_req req;
struct gsm_lchan *from_lchan;
- from_lchan = find_used_voice_lchan(vty);
+ from_lchan = find_used_voice_lchan(vty, random());
if (!from_lchan)
return CMD_WARNING;