aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc
diff options
context:
space:
mode:
authorVadim Yanitskiy <vyanitskiy@sysmocom.de>2022-06-06 01:43:28 +0600
committerfixeria <vyanitskiy@sysmocom.de>2022-06-30 16:36:41 +0000
commitc2928ac269a55d2ea1a6ae7984ba9065f8c41db0 (patch)
tree6b51e4a323ab6083589934f399063dd4e22c088f /src/osmo-bsc
parentff9d3a64dc8fec465140c244a816db22eea97b6b (diff)
lchan_select: allow different alloc order for assignment and handover
A follow-up patch implements a special channel allocation mode, which is only working for assignment (basically TCH selection for a voice call). This mode cannot be employed for initial CHANNEL REQUEST or handover due to the absence of an already established lchan. Adding this mode to the existing VTY command syntax would be confusing: channel allocator (ascending|desscending|dynamic) ^^^^^^^ so this patch extends the VTY syntax in a way that it becomes possible to configure different channel allocator modes for different cases: OsmoBSC(config-net-bts)# channel allocator mode ? set-all Set a single mode for all variants chan-req Channel allocation for CHANNEL REQUEST (RACH) assignment Channel allocation for assignment handover Channel allocation for handover The old command syntax, which is basically 'set-all', is kept for backwards compatibility, but marked as deprecated. Change-Id: I3ae73b36ee9433cc768376b56f0765e5f416162f Related: SYS#5460
Diffstat (limited to 'src/osmo-bsc')
-rw-r--r--src/osmo-bsc/abis_rsl.c19
-rw-r--r--src/osmo-bsc/assignment_fsm.c4
-rw-r--r--src/osmo-bsc/bsc_vty.c7
-rw-r--r--src/osmo-bsc/bts_vty.c62
-rw-r--r--src/osmo-bsc/handover_decision_2.c4
-rw-r--r--src/osmo-bsc/handover_fsm.c9
-rw-r--r--src/osmo-bsc/lchan_select.c55
7 files changed, 120 insertions, 40 deletions
diff --git a/src/osmo-bsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c
index f6215d954..7f88096e0 100644
--- a/src/osmo-bsc/abis_rsl.c
+++ b/src/osmo-bsc/abis_rsl.c
@@ -1978,10 +1978,10 @@ static struct gsm_lchan *get_any_lchan(struct gsm_bts *bts)
ts_for_n_lchans(lchan, ts, ts->max_primary_lchans) {
if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H) {
if (lchan->fi->state == LCHAN_ST_ESTABLISHED) {
- if (!lchan_est || bts->chan_alloc_reverse)
+ if (!lchan_est || bts->chan_alloc_chan_req_reverse)
lchan_est = lchan;
} else {
- if (!lchan_any || bts->chan_alloc_reverse)
+ if (!lchan_any || bts->chan_alloc_chan_req_reverse)
lchan_any = lchan;
}
}
@@ -2007,12 +2007,12 @@ static bool force_free_lchan_for_emergency(struct chan_rqd *rqd)
/* First check the situation on the BTS, if we have TCH/H or TCH/F resources available for another (EMERGENCY)
* call. If yes, then no (further) action has to be carried out. */
- if (lchan_avail_by_type(rqd->bts, GSM_LCHAN_TCH_F, true)) {
+ if (lchan_avail_by_type(rqd->bts, GSM_LCHAN_TCH_F, SELECT_FOR_MS_CHAN_REQ, true)) {
LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
"CHAN RQD/EMERGENCY-PRIORITY: at least one TCH/F is (now) available!\n");
return false;
}
- if (lchan_avail_by_type(rqd->bts, GSM_LCHAN_TCH_H, true)) {
+ if (lchan_avail_by_type(rqd->bts, GSM_LCHAN_TCH_H, SELECT_FOR_MS_CHAN_REQ, true)) {
LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
"CHAN RQD/EMERGENCY-PRIORITY: at least one TCH/H is (now) available!\n");
return false;
@@ -2083,7 +2083,7 @@ struct gsm_lchan *_select_sdcch_for_call(struct gsm_bts *bts, const struct chan_
int free_tchf, free_tchh;
bool needs_dyn_switch;
- lchan = lchan_avail_by_type(bts, GSM_LCHAN_SDCCH, false);
+ lchan = lchan_avail_by_type(bts, GSM_LCHAN_SDCCH, SELECT_FOR_MS_CHAN_REQ, false);
if (!lchan)
return NULL;
@@ -2172,7 +2172,8 @@ void abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts)
if (rqd->reason == GSM_CHREQ_REASON_CALL) {
lchan = _select_sdcch_for_call(bts, rqd, lctype);
} else if (rqd->reason != GSM_CHREQ_REASON_EMERG) {
- lchan = lchan_select_by_type(bts, GSM_LCHAN_SDCCH);
+ lchan = lchan_select_by_type(bts, GSM_LCHAN_SDCCH,
+ SELECT_FOR_MS_CHAN_REQ);
}
/* else: Emergency calls will be put on a free TCH/H or TCH/F directly
* in the code below, all other channel requests will get an SDCCH first
@@ -2187,13 +2188,15 @@ void abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts)
LOG_BTS(bts, DRSL, LOGL_NOTICE, "CHAN RQD[%s]: no resources for %s 0x%x, retrying with %s\n",
get_value_string(gsm_chreq_descs, rqd->reason), gsm_lchant_name(GSM_LCHAN_SDCCH),
rqd->ref.ra, gsm_lchant_name(GSM_LCHAN_TCH_H));
- lchan = lchan_select_by_type(bts, GSM_LCHAN_TCH_H);
+ lchan = lchan_select_by_type(bts, GSM_LCHAN_TCH_H,
+ SELECT_FOR_MS_CHAN_REQ);
}
if (!lchan) {
LOG_BTS(bts, DRSL, LOGL_NOTICE, "CHAN RQD[%s]: no resources for %s 0x%x, retrying with %s\n",
get_value_string(gsm_chreq_descs, rqd->reason), gsm_lchant_name(GSM_LCHAN_SDCCH),
rqd->ref.ra, gsm_lchant_name(GSM_LCHAN_TCH_F));
- lchan = lchan_select_by_type(bts, GSM_LCHAN_TCH_F);
+ lchan = lchan_select_by_type(bts, GSM_LCHAN_TCH_F,
+ SELECT_FOR_MS_CHAN_REQ);
}
}
if (!lchan) {
diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c
index a0d008da5..209545fd9 100644
--- a/src/osmo-bsc/assignment_fsm.c
+++ b/src/osmo-bsc/assignment_fsm.c
@@ -604,7 +604,9 @@ void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts
/* Try to allocate a new lchan in order of preference */
for (i = 0; i < req->n_ch_mode_rate; i++) {
conn->assignment.new_lchan = lchan_select_by_chan_mode(bts,
- req->ch_mode_rate_list[i].chan_mode, req->ch_mode_rate_list[i].chan_rate);
+ req->ch_mode_rate_list[i].chan_mode,
+ req->ch_mode_rate_list[i].chan_rate,
+ SELECT_FOR_ASSIGNMENT);
if (!conn->assignment.new_lchan)
continue;
LOG_ASSIGNMENT(conn, LOGL_DEBUG, "selected new lchan %s for mode[%d] = %s channel_rate=%d\n",
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index 5b46e7917..0df5712b7 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -770,7 +770,9 @@ static int trigger_as(struct vty *vty, struct gsm_lchan *from_lchan, struct gsm_
{
LOG_LCHAN(from_lchan, LOGL_NOTICE, "Manually triggering Assignment from VTY\n");
if (!to_lchan) {
- to_lchan = lchan_select_by_type(from_lchan->ts->trx->bts, from_lchan->type);
+ struct gsm_bts *bts = from_lchan->ts->trx->bts;
+ to_lchan = lchan_select_by_type(bts, from_lchan->type,
+ SELECT_FOR_ASSIGNMENT);
vty_out(vty, "Error: cannot find free lchan of type %s%s",
gsm_lchant_name(from_lchan->type), VTY_NEWLINE);
}
@@ -955,7 +957,8 @@ 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) {
- struct gsm_lchan *lchan = lchan_select_by_type(bts, free_type);
+ struct gsm_lchan *lchan = lchan_select_by_type(bts, free_type,
+ SELECT_FOR_HANDOVER);
if (!lchan)
continue;
diff --git a/src/osmo-bsc/bts_vty.c b/src/osmo-bsc/bts_vty.c
index c23c14ee8..1a9b1e339 100644
--- a/src/osmo-bsc/bts_vty.c
+++ b/src/osmo-bsc/bts_vty.c
@@ -533,20 +533,51 @@ DEFUN_USRATTR(cfg_bts_oml_e1_tei,
"Channel Allocator\n" \
"Channel Allocator\n"
-DEFUN_ATTR(cfg_bts_challoc,
- cfg_bts_challoc_cmd,
- CHAN_ALLOC_CMD " (ascending|descending)",
+#define CHAN_ALLOC_ASC_DSC "(ascending|descending)"
+#define CHAN_ALLOC_ASC_DSC_DESC \
+ "Allocate Timeslots and Transceivers in ascending order\n" \
+ "Allocate Timeslots and Transceivers in descending order\n"
+
+DEFUN_ATTR(cfg_bts_challoc_mode_all,
+ cfg_bts_challoc_mode_all_cmd,
+ CHAN_ALLOC_CMD " " CHAN_ALLOC_ASC_DSC,
+ CHAN_ALLOC_DESC CHAN_ALLOC_ASC_DSC_DESC,
+ CMD_ATTR_IMMEDIATE | CMD_ATTR_DEPRECATED)
+{
+ bool reverse = !strcmp(argv[0], "descending");
+ struct gsm_bts *bts = vty->index;
+
+ bts->chan_alloc_chan_req_reverse = reverse;
+ bts->chan_alloc_assignment_reverse = reverse;
+ bts->chan_alloc_handover_reverse = reverse;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_bts_challoc_mode,
+ cfg_bts_challoc_mode_cmd,
+ CHAN_ALLOC_CMD
+ " mode (set-all|chan-req|assignment|handover) "
+ CHAN_ALLOC_ASC_DSC,
CHAN_ALLOC_DESC
- "Allocate Timeslots and Transceivers in ascending order\n"
- "Allocate Timeslots and Transceivers in descending order\n",
+ "Channel allocation mode\n"
+ "Set a single mode for all variants\n"
+ "Channel allocation for CHANNEL REQUEST (RACH)\n"
+ "Channel allocation for assignment\n"
+ "Channel allocation for handover\n"
+ CHAN_ALLOC_ASC_DSC_DESC,
CMD_ATTR_IMMEDIATE)
{
+ bool reverse = !strcmp(argv[1], "descending");
+ bool set_all = !strcmp(argv[0], "set-all");
struct gsm_bts *bts = vty->index;
- if (!strcmp(argv[0], "ascending"))
- bts->chan_alloc_reverse = 0;
- else
- bts->chan_alloc_reverse = 1;
+ if (set_all || !strcmp(argv[0], "chan-req"))
+ bts->chan_alloc_chan_req_reverse = reverse;
+ if (set_all || !strcmp(argv[0], "assignment"))
+ bts->chan_alloc_assignment_reverse = reverse;
+ if (set_all || !strcmp(argv[0], "handover"))
+ bts->chan_alloc_handover_reverse = reverse;
return CMD_SUCCESS;
}
@@ -4212,8 +4243,14 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
vty_out(vty, " radio-link-timeout %d%s",
gsm_bts_get_radio_link_timeout(bts), VTY_NEWLINE);
- vty_out(vty, " channel allocator %s%s",
- bts->chan_alloc_reverse ? "descending" : "ascending",
+ vty_out(vty, " channel allocator mode chan-req %s%s",
+ bts->chan_alloc_chan_req_reverse ? "descending" : "ascending",
+ VTY_NEWLINE);
+ vty_out(vty, " channel allocator mode assignment %s%s",
+ bts->chan_alloc_assignment_reverse ? "descending" : "ascending",
+ VTY_NEWLINE);
+ vty_out(vty, " channel allocator mode handover %s%s",
+ bts->chan_alloc_handover_reverse ? "descending" : "ascending",
VTY_NEWLINE);
if (bts->chan_alloc_avoid_interf)
vty_out(vty, " channel allocator avoid-interference 1%s", VTY_NEWLINE);
@@ -4543,7 +4580,8 @@ int bts_vty_init(void)
install_element(BTS_NODE, &cfg_bts_deprecated_stream_id_cmd);
install_element(BTS_NODE, &cfg_bts_oml_e1_cmd);
install_element(BTS_NODE, &cfg_bts_oml_e1_tei_cmd);
- install_element(BTS_NODE, &cfg_bts_challoc_cmd);
+ install_element(BTS_NODE, &cfg_bts_challoc_mode_cmd);
+ install_element(BTS_NODE, &cfg_bts_challoc_mode_all_cmd);
install_element(BTS_NODE, &cfg_bts_chan_alloc_interf_cmd);
install_element(BTS_NODE, &cfg_bts_chan_alloc_tch_signalling_policy_cmd);
install_element(BTS_NODE, &cfg_bts_chan_alloc_allow_tch_for_signalling_cmd);
diff --git a/src/osmo-bsc/handover_decision_2.c b/src/osmo-bsc/handover_decision_2.c
index a1a8ffa8f..3c4b3baac 100644
--- a/src/osmo-bsc/handover_decision_2.c
+++ b/src/osmo-bsc/handover_decision_2.c
@@ -1050,7 +1050,7 @@ static void candidate_set_free_tch(struct ho_candidate *c)
/* Would the next TCH/F lchan occupy a dynamic timeslot that currently counts for free TCH/H timeslots?
*/
- next_lchan = lchan_avail_by_type(c->target.bts, GSM_LCHAN_TCH_F, false);
+ next_lchan = lchan_avail_by_type(c->target.bts, GSM_LCHAN_TCH_F, SELECT_FOR_HANDOVER, false);
if (next_lchan && next_lchan->ts->pchan_on_init == GSM_PCHAN_OSMO_DYN)
c->target.next_tchf_reduces_tchh = 2;
else
@@ -1058,7 +1058,7 @@ static void candidate_set_free_tch(struct ho_candidate *c)
/* Would the next TCH/H lchan occupy a dynamic timeslot that currently counts for free TCH/F timeslots?
* Note that a dyn TS already in TCH/H mode (half occupied) would not reduce free TCH/F. */
- next_lchan = lchan_avail_by_type(c->target.bts, GSM_LCHAN_TCH_H, false);
+ next_lchan = lchan_avail_by_type(c->target.bts, GSM_LCHAN_TCH_H, SELECT_FOR_HANDOVER, false);
if (next_lchan && next_lchan->ts->pchan_on_init == GSM_PCHAN_OSMO_DYN
&& next_lchan->ts->pchan_is != GSM_PCHAN_TCH_H)
c->target.next_tchh_reduces_tchf = 1;
diff --git a/src/osmo-bsc/handover_fsm.c b/src/osmo-bsc/handover_fsm.c
index a4221c4bc..0797bf3f8 100644
--- a/src/osmo-bsc/handover_fsm.c
+++ b/src/osmo-bsc/handover_fsm.c
@@ -379,7 +379,9 @@ static void handover_start_intra_bsc(struct gsm_subscriber_connection *conn)
ho->async = true;
gsm_bts_cell_id_list(&ho->target_cell_ids, ho->new_bts);
- ho->new_lchan = lchan_select_by_type(ho->new_bts, ho->new_lchan_type);
+ ho->new_lchan = lchan_select_by_type(ho->new_bts,
+ ho->new_lchan_type,
+ SELECT_FOR_HANDOVER);
if (ho->scope & HO_INTRA_CELL) {
ho_count(bts, CTR_INTRA_CELL_HO_ATTEMPTED);
@@ -696,7 +698,10 @@ void handover_start_inter_bsc_in(struct gsm_subscriber_connection *conn,
ch_mode_rate.chan_rate == CH_RATE_FULL ? "full-rate" : "half-rate",
gsm0808_channel_type_name(&req->ct));
- lchan = lchan_select_by_chan_mode(bts, ch_mode_rate.chan_mode, ch_mode_rate.chan_rate);
+ lchan = lchan_select_by_chan_mode(bts,
+ ch_mode_rate.chan_mode,
+ ch_mode_rate.chan_rate,
+ SELECT_FOR_HANDOVER);
if (!lchan) {
LOG_HO(conn, LOGL_DEBUG, "BTS %u has no matching free channels\n", bts->nr);
continue;
diff --git a/src/osmo-bsc/lchan_select.c b/src/osmo-bsc/lchan_select.c
index a322f07a4..8b6da4036 100644
--- a/src/osmo-bsc/lchan_select.c
+++ b/src/osmo-bsc/lchan_select.c
@@ -35,6 +35,13 @@ struct lchan_select_ts_list {
unsigned int num;
};
+const struct value_string lchan_select_reason_names[] = {
+ OSMO_VALUE_STRING(SELECT_FOR_MS_CHAN_REQ),
+ OSMO_VALUE_STRING(SELECT_FOR_ASSIGNMENT),
+ OSMO_VALUE_STRING(SELECT_FOR_HANDOVER),
+ {0, NULL}
+};
+
static struct gsm_lchan *pick_better_lchan(struct gsm_lchan *a, struct gsm_lchan *b)
{
if (!a)
@@ -190,6 +197,7 @@ enum gsm_chan_t chan_mode_to_chan_type(enum gsm48_chan_mode chan_mode, enum chan
static void populate_ts_list(struct lchan_select_ts_list *ts_list,
struct gsm_bts *bts,
+ bool chan_alloc_reverse,
bool log)
{
struct gsm_bts_trx *trx;
@@ -208,7 +216,7 @@ static void populate_ts_list(struct lchan_select_ts_list *ts_list,
ts_list->num = num;
/* Reverse the timeslot list if required */
- if (bts->chan_alloc_reverse) {
+ if (chan_alloc_reverse) {
for (unsigned int tn = 0; tn < num / 2; tn++) {
struct gsm_bts_trx_ts *temp = ts_list->list[tn];
ts_list->list[tn] = ts_list->list[num - tn - 1];
@@ -218,22 +226,40 @@ static void populate_ts_list(struct lchan_select_ts_list *ts_list,
}
struct gsm_lchan *lchan_select_by_chan_mode(struct gsm_bts *bts,
- enum gsm48_chan_mode chan_mode, enum channel_rate chan_rate)
+ enum gsm48_chan_mode chan_mode,
+ enum channel_rate chan_rate,
+ enum lchan_select_reason reason)
{
enum gsm_chan_t type = chan_mode_to_chan_type(chan_mode, chan_rate);
if (type == GSM_LCHAN_NONE)
return NULL;
- return lchan_select_by_type(bts, type);
+ return lchan_select_by_type(bts, type, reason);
}
-struct gsm_lchan *lchan_avail_by_type(struct gsm_bts *bts, enum gsm_chan_t type, bool log)
+struct gsm_lchan *lchan_avail_by_type(struct gsm_bts *bts, enum gsm_chan_t type,
+ enum lchan_select_reason reason, bool log)
{
struct gsm_lchan *lchan = NULL;
enum gsm_phys_chan_config first, first_cbch, second, second_cbch;
struct lchan_select_ts_list ts_list;
+ bool chan_alloc_reverse;
+
+ if (log) {
+ LOG_BTS(bts, DRLL, LOGL_DEBUG, "lchan_avail_by_type(type=%s, reason=%s)\n",
+ gsm_lchant_name(type), lchan_select_reason_name(reason));
+ }
- if (log)
- LOG_BTS(bts, DRLL, LOGL_DEBUG, "lchan_avail_by_type(%s)\n", gsm_lchant_name(type));
+ switch (reason) {
+ case SELECT_FOR_MS_CHAN_REQ:
+ chan_alloc_reverse = bts->chan_alloc_chan_req_reverse;
+ break;
+ case SELECT_FOR_ASSIGNMENT:
+ chan_alloc_reverse = bts->chan_alloc_assignment_reverse;
+ break;
+ case SELECT_FOR_HANDOVER:
+ chan_alloc_reverse = bts->chan_alloc_handover_reverse;
+ break;
+ }
/* Allocate an array with pointers to all timeslots of a BTS */
ts_list.list = talloc_array_ptrtype(bts, ts_list.list, bts->num_trx * 8);
@@ -241,11 +267,11 @@ struct gsm_lchan *lchan_avail_by_type(struct gsm_bts *bts, enum gsm_chan_t type,
return NULL;
/* Populate this array with the actual pointers */
- populate_ts_list(&ts_list, bts, log);
+ populate_ts_list(&ts_list, bts, chan_alloc_reverse, log);
switch (type) {
case GSM_LCHAN_SDCCH:
- if (bts->chan_alloc_reverse) {
+ if (chan_alloc_reverse) {
first = GSM_PCHAN_SDCCH8_SACCH8C;
first_cbch = GSM_PCHAN_SDCCH8_SACCH8C_CBCH;
second = GSM_PCHAN_CCCH_SDCCH4;
@@ -302,17 +328,20 @@ struct gsm_lchan *lchan_avail_by_type(struct gsm_bts *bts, enum gsm_chan_t type,
/* Return a matching lchan from a specific BTS that is currently available. The next logical step is
* lchan_activate() on it, which would possibly cause dynamic timeslot pchan switching, taken care of by
* the lchan and timeslot FSMs. */
-struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts, enum gsm_chan_t type)
+struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts,
+ enum gsm_chan_t type,
+ enum lchan_select_reason reason)
{
struct gsm_lchan *lchan = NULL;
- LOG_BTS(bts, DRLL, LOGL_DEBUG, "lchan_select_by_type(%s)\n", gsm_lchant_name(type));
+ LOG_BTS(bts, DRLL, LOGL_DEBUG, "lchan_select_by_type(type=%s, reason=%s)\n",
+ gsm_lchant_name(type), lchan_select_reason_name(reason));
- lchan = lchan_avail_by_type(bts, type, true);
+ lchan = lchan_avail_by_type(bts, type, reason, true);
if (!lchan) {
- LOG_BTS(bts, DRLL, LOGL_NOTICE, "Failed to select %s channel\n",
- gsm_lchant_name(type));
+ LOG_BTS(bts, DRLL, LOGL_NOTICE, "Failed to select %s channel (%s)\n",
+ gsm_lchant_name(type), lchan_select_reason_name(reason));
return NULL;
}