Change in osmo-bsc[master]: abis_rsl: prioritize emergency calls over regular calls

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

dexter gerrit-no-reply at lists.osmocom.org
Fri Aug 21 21:16:00 UTC 2020


dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc/+/19793 )


Change subject: abis_rsl: prioritize emergency calls over regular calls
......................................................................

abis_rsl: prioritize emergency calls over regular calls

when an emergency call arrives while all TCH are busy, the BSC should
pick an arbitrary (preferably the longest lasting) call / lchan and
release it in favor of the incoming emergancy call.

The release of the existing call is a process that can not be done
synchronously while the ChanRQD is handled sonce multiple messages are
exchanged between BTS and MSC and multiple FSMs need to do their work.

To be able to release one lchan while handling a ChanRQD a queue is
implemented in which the incomming channel requests are collected. The
queue is checked regulary for incoming requests. If one of the requests
is for an emergency call and if all channels are busy one channel is
picked and released. It is also made sure that the incoming emergency
call directly gets the TCH that was just released.

Change-Id: If8651265928797dbda9f528b544931dcfa4a0b36
Related: OS#4549
---
M include/osmocom/bsc/abis_rsl.h
M include/osmocom/bsc/bts.h
M include/osmocom/bsc/lchan_fsm.h
M include/osmocom/bsc/lchan_select.h
M src/ipaccess/ipaccess-config.c
M src/ipaccess/ipaccess-proxy.c
M src/osmo-bsc/abis_rsl.c
M src/osmo-bsc/bts.c
M src/osmo-bsc/lchan_fsm.c
M src/osmo-bsc/lchan_select.c
M src/utils/bs11_config.c
M src/utils/meas_json.c
M tests/abis/abis_test.c
M tests/acc/acc_test.c
M tests/bsc/bsc_test.c
M tests/gsm0408/gsm0408_test.c
M tests/nanobts_omlattr/nanobts_omlattr_test.c
17 files changed, 271 insertions(+), 47 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/93/19793/1

diff --git a/include/osmocom/bsc/abis_rsl.h b/include/osmocom/bsc/abis_rsl.h
index 2611a3d..146c636 100644
--- a/include/osmocom/bsc/abis_rsl.h
+++ b/include/osmocom/bsc/abis_rsl.h
@@ -118,5 +118,7 @@
 
 int rsl_tx_rf_chan_release(struct gsm_lchan *lchan);
 
+int abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts);
+
 #endif /* RSL_MT_H */
 
diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h
index 16053a3..693fb80 100644
--- a/include/osmocom/bsc/bts.h
+++ b/include/osmocom/bsc/bts.h
@@ -495,6 +495,8 @@
 	struct osmo_timer_list etws_timer;	/* when to stop ETWS PN */
 
 	struct llist_head oml_fail_rep;
+	struct llist_head chan_rqd_queue;
+	struct osmo_timer_list chan_rqd_queue_timer;
 };
 
 #define GSM_BTS_SI2Q(bts, i)   (struct gsm48_system_information_type_2quater *)((bts)->si_buf[SYSINFO_TYPE_2quater][i])
diff --git a/include/osmocom/bsc/lchan_fsm.h b/include/osmocom/bsc/lchan_fsm.h
index e5b3707..8dc228b 100644
--- a/include/osmocom/bsc/lchan_fsm.h
+++ b/include/osmocom/bsc/lchan_fsm.h
@@ -75,3 +75,5 @@
 void lchan_forget_conn(struct gsm_lchan *lchan);
 
 void lchan_set_last_error(struct gsm_lchan *lchan, const char *fmt, ...);
+
+void lchan_fsm_skip_error(struct gsm_lchan *lchan);
diff --git a/include/osmocom/bsc/lchan_select.h b/include/osmocom/bsc/lchan_select.h
index 865181b..7a828d9 100644
--- a/include/osmocom/bsc/lchan_select.h
+++ b/include/osmocom/bsc/lchan_select.h
@@ -4,3 +4,4 @@
 struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts, enum gsm_chan_t type);
 struct gsm_lchan *lchan_select_by_chan_mode(struct gsm_bts *bts,
 					    enum gsm48_chan_mode chan_mode, enum channel_rate chan_rate);
+bool lchan_select_avail(struct gsm_bts *bts, enum gsm_chan_t type);
diff --git a/src/ipaccess/ipaccess-config.c b/src/ipaccess/ipaccess-config.c
index c9264d7..be5f6a8 100644
--- a/src/ipaccess/ipaccess-config.c
+++ b/src/ipaccess/ipaccess-config.c
@@ -1142,3 +1142,4 @@
 int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len)
 { return 0; }
 int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type) { return 0; }
+int abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts) { return 0; }
diff --git a/src/ipaccess/ipaccess-proxy.c b/src/ipaccess/ipaccess-proxy.c
index d5dd8d4..fec866a 100644
--- a/src/ipaccess/ipaccess-proxy.c
+++ b/src/ipaccess/ipaccess-proxy.c
@@ -1260,3 +1260,4 @@
 int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len)
 { return 0; }
 int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type) { return 0; }
+int abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts) { return 0; }
diff --git a/src/osmo-bsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c
index 42f3a42..64c4af5 100644
--- a/src/osmo-bsc/abis_rsl.c
+++ b/src/osmo-bsc/abis_rsl.c
@@ -1322,77 +1322,219 @@
 	return rsl_send_imm_ass_rej(bts, rqd_ref, wait_ind);
 }
 
+struct chan_rqd {
+	struct llist_head list;
+	struct gsm_bts *bts;
+	struct gsm48_req_ref ref;
+	enum gsm_chreq_reason_t reason;
+	uint8_t ta;
+	bool relasing;
+	struct gsm_lchan *lchan;
+};
+
 /* Handle packet channel rach requests */
-static int rsl_rx_pchan_rqd(struct msgb *msg, struct gsm_bts *bts)
+static int rsl_rx_pchan_rqd(struct chan_rqd *rqd)
 {
-	struct gsm48_req_ref *rqd_ref;
-	struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
-	rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
-	uint8_t ra = rqd_ref->ra;
 	uint8_t t1, t2, t3;
 	uint32_t fn;
 	uint8_t rqd_ta;
 	uint8_t is_11bit;
 
 	/* Process rach request and forward contained information to PCU */
-	if (ra == 0x7F) {
+	if (rqd->ref.ra == 0x7F) {
 		is_11bit = 1;
 
 		/* FIXME: Also handle 11 bit rach requests */
-		LOGP(DRSL, LOGL_ERROR, "BTS %d eleven bit access burst not supported yet!\n",bts->nr);
+		LOGP(DRSL, LOGL_ERROR, "BTS %d eleven bit access burst not supported yet!\n",rqd->bts->nr);
 		return -EINVAL;
 	} else {
 		is_11bit = 0;
-		t1 = rqd_ref->t1;
-		t2 = rqd_ref->t2;
-		t3 = rqd_ref->t3_low | (rqd_ref->t3_high << 3);
+		t1 = rqd->ref.t1;
+		t2 = rqd->ref.t2;
+		t3 = rqd->ref.t3_low | (rqd->ref.t3_high << 3);
 		fn = (51 * ((t3-t2) % 26) + t3 + 51 * 26 * t1);
-
-		rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
+		rqd_ta = rqd->ta;
 	}
 
-	return pcu_tx_rach_ind(bts, rqd_ta, ra, fn, is_11bit,
+	return pcu_tx_rach_ind(rqd->bts, rqd_ta, rqd->ref.ra, fn, is_11bit,
 			       GSM_L1_BURST_TYPE_ACCESS_0);
 }
 
 /* MS has requested a channel on the RACH */
 static int rsl_rx_chan_rqd(struct msgb *msg)
 {
-	struct lchan_activate_info info;
 	struct e1inp_sign_link *sign_link = msg->dst;
 	struct gsm_bts *bts = sign_link->trx->bts;
 	struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
-	struct gsm48_req_ref *rqd_ref;
-	enum gsm_chan_t lctype;
-	enum gsm_chreq_reason_t chreq_reason;
-	struct gsm_lchan *lchan;
-	uint8_t rqd_ta;
+	struct chan_rqd *rqd;
+
+	rqd = talloc_zero(bts, struct chan_rqd);
+	OSMO_ASSERT(rqd);
+
+	rqd->bts = bts;
 
 	/* parse request reference to be used in immediate assign */
-	if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
+	if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE) {
+		talloc_free(rqd);
 		return -EINVAL;
-
-	rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
+	}
+	memcpy(&rqd->ref, &rqd_hdr->data[1], sizeof(rqd->ref));
 
 	/* parse access delay and use as TA */
-	if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
+	if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY) {
+		talloc_free(rqd);
 		return -EINVAL;
-	rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
+	}
+	rqd->ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
 
 	/* Determine channel request cause code */
-	chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
+	rqd->reason = get_reason_by_chreq(rqd->ref.ra, bts->network->neci);
 	LOG_BTS(bts, DRSL, LOGL_INFO, "CHAN RQD: reason: %s (ra=0x%02x, neci=0x%02x, chreq_reason=0x%02x)\n",
-		get_value_string(gsm_chreq_descs, chreq_reason), rqd_ref->ra, bts->network->neci, chreq_reason);
+		get_value_string(gsm_chreq_descs, rqd->reason), rqd->ref.ra, bts->network->neci, rqd->reason);
+
+	rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_CHREQ_TOTAL]);
+
+	/* Enqueue request */
+	llist_add_tail(&rqd->list, &bts->chan_rqd_queue);
+	return 0;
+}
+
+/* Find any busy TCH/H or TCH/F lchan, prefer established and old lchans */
+static struct gsm_lchan *get_any_lchan(struct gsm_bts *bts)
+{
+	int trx_nr;
+	int ts_nr;
+	struct gsm_bts_trx *trx;
+	struct gsm_bts_trx_ts *ts;
+	struct gsm_lchan *lchan_est = NULL;
+	struct gsm_lchan *lchan_any = NULL;
+	struct gsm_lchan *lchan;
+
+	for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
+		trx = gsm_bts_trx_num(bts, trx_nr);
+		for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
+			ts = &trx->ts[ts_nr];
+			ts_for_each_lchan(lchan, ts) {
+				if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H) {
+					if (bts->chan_alloc_reverse) {
+						if (lchan->fi->state == LCHAN_ST_ESTABLISHED)
+							lchan_est = lchan;
+						else
+							lchan_any = lchan;
+					} else {
+						if (lchan->fi->state == LCHAN_ST_ESTABLISHED) {
+							if (!lchan_est)
+								lchan_est = lchan;
+						} else {
+							if (!lchan_any)
+								lchan_any = lchan;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	if (lchan_est)
+		return lchan_est;
+	else if (lchan_any)
+		return lchan_any;
+	return NULL;
+}
+
+/* Ensure that an incoming emergency call gets priority, if all voice channels
+ * are busy, terminate one regular call */
+static int handle_emergency_call(struct chan_rqd *rqd)
+{
+	/* If the request is not about an emergency call, we may exit early,
+	 * without doing anything. */
+	if(rqd->reason != GSM_CHREQ_REASON_EMERG)
+              return 0;
+
+	/* First check the situation on the BTS, if we still have TCH/H or
+	 * TCH/F resources available, then not action is required. */
+	if (lchan_select_avail(rqd->bts, GSM_LCHAN_TCH_F)) {
+		LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
+			"CHAN RQD/EMERGENCY-PRIORITY: at least one TCH/F is (now) available!\n");
+		return 0;
+	}
+	if (lchan_select_avail(rqd->bts, GSM_LCHAN_TCH_H)) {
+		LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
+			"CHAN RQD/EMERGENCY-PRIORITY: at least one TCH/H is (now) available!\n");
+		return 0;
+	}
+
+	if (!rqd->relasing) {
+		/* Pick any busy TCH/F or TCH/H lchan and inititate a channel
+		 * release to make room for the incoming emergency call */
+		rqd->lchan = get_any_lchan(rqd->bts);
+		if (!rqd->lchan) {
+			/* It can not happen that we first find out that there
+			 * is no TCH/H or TCH/F available and at the same time
+			 * we ware unable to find any busy TCH/H or TCH/F. In
+			 * this case, the BTS probably does not have any
+			 * voice channels configured? */
+			LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
+				"CHAN RQD/EMERGENCY-PRIORITY: no TCH/H or TCH/F available - check VTY config!\n");
+			return 0;
+		}
+
+		LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
+			"CHAN RQD/EMERGENCY-PRIORITY: inducing termination of lchan %s (state:%s) in favor of incoming EMERGENCY CALL!\n",
+			gsm_lchan_name(rqd->lchan), osmo_fsm_inst_state_name(rqd->lchan->fi));
+
+		lchan_release(rqd->lchan, !!(rqd->lchan->conn), true, 0);
+		rqd->relasing = true;
+	} else {
+		if (!rqd->lchan->fi) {
+			LOG_BTS(rqd->bts, DRSL, LOGL_ERROR,
+				"CHAN RQD/EMERGENCY-PRIORITY: lchan %s has lost its FSM - skipping!\n",
+				gsm_lchan_name(rqd->lchan));
+			return 0;
+		}
+
+		LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
+			"CHAN RQD/EMERGENCY-PRIORITY: still terminating lchan %s (state:%s) in favor of incoming EMERGENCY CALL!\n",
+			gsm_lchan_name(rqd->lchan), osmo_fsm_inst_state_name(rqd->lchan->fi));
+
+		/* If the channel was released in error (not established), the
+		 * lchan FSM automatically blocks the LCHAN for a short time.
+		 * This is not acceptable in an emergency situation, so we skip
+		 * this waiting period. */
+		if (rqd->lchan->fi->state == LCHAN_ST_WAIT_AFTER_ERROR)
+			lchan_fsm_skip_error(rqd->lchan);
+	}
+
+	return -1;
+}
+
+int abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts)
+{
+	struct lchan_activate_info info;
+	enum gsm_chan_t lctype;
+	struct gsm_lchan *lchan;
+	struct llist_head *lh_rqd;
+	struct chan_rqd *rqd;
+
+	if (llist_empty(&bts->chan_rqd_queue)) {
+		return 0;
+	}
+	lh_rqd = bts->chan_rqd_queue.next;
+	if(!lh_rqd)
+		return 0;
+	rqd = llist_entry(lh_rqd, struct chan_rqd, list);
 
 	/* Handle PDCH related rach requests (in case of BSC-co-located-PCU */
-	if (chreq_reason == GSM_CHREQ_REASON_PDCH)
-		return rsl_rx_pchan_rqd(msg, bts);
+	if (rqd->reason == GSM_CHREQ_REASON_PDCH)
+		return rsl_rx_pchan_rqd(rqd);
+
+	/* Ensure that emergency calls will get priority over regular calls */
+	if (handle_emergency_call(rqd) < 0)
+		return 0;
 
 	/* determine channel type (SDCCH/TCH_F/TCH_H) based on
 	 * request reference RA */
-	lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
-
-	rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_CHREQ_TOTAL]);
+	lctype = get_ctype_by_chreq(bts->network, rqd->ref.ra);
 
 	/* check availability / allocate channel
 	 *
@@ -1402,30 +1544,45 @@
 	 * - If there is still no channel available, try a TCH/F.
 	 *
 	 */
-	if (chreq_reason == GSM_CHREQ_REASON_EMERG) {
+	if (rqd->reason == GSM_CHREQ_REASON_EMERG) {
 		if (bts->si_common.rach_control.t2 & 0x4) {
 			LOG_BTS(bts, DRSL, LOGL_NOTICE, "CHAN RQD: MS attempts EMERGENCY CALL although EMERGENCY CALLS "
 				"are not allowed in sysinfo (spec violation by MS!)\n");
-			rsl_tx_imm_ass_rej(bts, rqd_ref);
+			rsl_tx_imm_ass_rej(bts, &rqd->ref);
+			llist_del(lh_rqd);
+			talloc_free(rqd);
 			return -EINVAL;
 		}
 	}
-	lchan = lchan_select_by_type(bts, GSM_LCHAN_SDCCH);
+
+	lchan = lchan_select_by_type(bts, GSM_LCHAN_TCH_F);
+
+	/* If an emergency call is incoming, the preemption logic already
+	 * has made sure that there is at least one TCH/F or TCH/H available,
+	 * so we refrain from assigning an SDCCH first, assigning the TCH
+	 * dirrectly is faster and safer in this case */
+	if (rqd->reason == GSM_CHREQ_REASON_EMERG)
+		lchan = NULL;
+	else
+		lchan = lchan_select_by_type(bts, GSM_LCHAN_SDCCH);
+
 	if (!lchan) {
 		LOG_BTS(bts, DRSL, LOGL_NOTICE, "CHAN RQD: no resources for %s 0x%x, retrying with %s\n",
-			gsm_lchant_name(GSM_LCHAN_SDCCH), rqd_ref->ra, gsm_lchant_name(GSM_LCHAN_TCH_H));
+			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);
 	}
 	if (!lchan) {
 		LOG_BTS(bts, DRSL, LOGL_NOTICE, "CHAN RQD: no resources for %s 0x%x, retrying with %s\n",
-			gsm_lchant_name(GSM_LCHAN_SDCCH), rqd_ref->ra, gsm_lchant_name(GSM_LCHAN_TCH_F));
+			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);
 	}
 	if (!lchan) {
 		LOG_BTS(bts, DRSL, LOGL_NOTICE, "CHAN RQD: no resources for %s 0x%x\n",
-			gsm_lchant_name(lctype), rqd_ref->ra);
+			gsm_lchant_name(lctype), rqd->ref.ra);
 		rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_CHREQ_NO_CHANNEL]);
-		rsl_tx_imm_ass_rej(bts, rqd_ref);
+		rsl_tx_imm_ass_rej(bts, &rqd->ref);
+		llist_del(lh_rqd);
+		talloc_free(rqd);
 		return 0;
 	}
 
@@ -1433,17 +1590,19 @@
 	lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
 	OSMO_ASSERT(lchan->rqd_ref);
 
-	*(lchan->rqd_ref) = *rqd_ref;
-	lchan->rqd_ta = rqd_ta;
+	*(lchan->rqd_ref) = rqd->ref;
+	lchan->rqd_ta = rqd->ta;
 
 	LOG_LCHAN(lchan, LOGL_DEBUG, "MS: Channel Request: reason=%s ra=0x%02x ta=%d\n",
-		  gsm_chreq_name(chreq_reason), rqd_ref->ra, rqd_ta);
+		  gsm_chreq_name(rqd->reason), rqd->ref.ra, rqd->ta);
 	info = (struct lchan_activate_info){
 		.activ_for = FOR_MS_CHANNEL_REQUEST,
 		.chan_mode = GSM48_CMODE_SIGN,
 	};
 
 	lchan_activate(lchan, &info);
+	llist_del(lh_rqd);
+	talloc_free(rqd);
 	return 0;
 }
 
diff --git a/src/osmo-bsc/bts.c b/src/osmo-bsc/bts.c
index 4318b7e..ff85267 100644
--- a/src/osmo-bsc/bts.c
+++ b/src/osmo-bsc/bts.c
@@ -23,6 +23,7 @@
 #include <osmocom/bsc/gsm_data.h>
 #include <osmocom/bsc/bts.h>
 #include <osmocom/bsc/debug.h>
+#include <osmocom/bsc/abis_rsl.h>
 
 const struct value_string bts_attribute_names[] = {
 	OSMO_VALUE_STRING(BTS_TYPE_VARIANT),
@@ -31,6 +32,14 @@
 	{ 0, NULL }
 };
 
+/* timer call-back to poll CHAN RQD queue */
+static void chan_rqd_poll_cb(void *data)
+{
+	struct gsm_bts *bts = (struct gsm_bts *)data;
+	abis_rsl_chan_rqd_queue_poll(bts);
+	osmo_timer_schedule(&bts->chan_rqd_queue_timer, 0, 100000);
+}
+
 enum bts_attribute str2btsattr(const char *s)
 {
 	return get_string_value(bts_attribute_names, s);
@@ -319,6 +328,11 @@
 	INIT_LLIST_HEAD(&bts->loc_list);
 	INIT_LLIST_HEAD(&bts->local_neighbors);
 	INIT_LLIST_HEAD(&bts->oml_fail_rep);
+	INIT_LLIST_HEAD(&bts->chan_rqd_queue);
+
+	/* Start CHAN RQD queue */
+	osmo_timer_setup(&bts->chan_rqd_queue_timer, chan_rqd_poll_cb, bts);
+	osmo_timer_schedule(&bts->chan_rqd_queue_timer, 0, 0);
 
 	/* Enable all codecs by default. These get reset to a more fine grained selection IF a
 	 * 'codec-support' config appears in the config file (see bsc_vty.c). */
diff --git a/src/osmo-bsc/lchan_fsm.c b/src/osmo-bsc/lchan_fsm.c
index db72651..ea4a115 100644
--- a/src/osmo-bsc/lchan_fsm.c
+++ b/src/osmo-bsc/lchan_fsm.c
@@ -1479,6 +1479,13 @@
 	}
 }
 
+void lchan_fsm_skip_error(struct gsm_lchan *lchan)
+{
+	struct osmo_fsm_inst *fi = lchan->fi;
+	if (fi->state == LCHAN_ST_WAIT_AFTER_ERROR)
+		lchan_fsm_state_chg(LCHAN_ST_UNUSED);
+}
+
 static int lchan_fsm_timer_cb(struct osmo_fsm_inst *fi)
 {
 	struct gsm_lchan *lchan = lchan_fi_lchan(fi);
diff --git a/src/osmo-bsc/lchan_select.c b/src/osmo-bsc/lchan_select.c
index d2dba1b..6f73fbc 100644
--- a/src/osmo-bsc/lchan_select.c
+++ b/src/osmo-bsc/lchan_select.c
@@ -162,16 +162,11 @@
 	return lchan_select_by_type(bts, 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)
+static struct gsm_lchan *_get_lchan_by_type(struct gsm_bts *bts, enum gsm_chan_t type)
 {
 	struct gsm_lchan *lchan = NULL;
 	enum gsm_phys_chan_config first, first_cbch, second, second_cbch;
 
-	LOG_BTS(bts, DRLL, LOGL_DEBUG, "lchan_select_by_type(%s)\n", gsm_lchant_name(type));
-
 	switch (type) {
 	case GSM_LCHAN_SDCCH:
 		if (bts->chan_alloc_reverse) {
@@ -231,6 +226,20 @@
 		LOG_BTS(bts, DRLL, LOGL_ERROR, "Unknown gsm_chan_t %u\n", type);
 	}
 
+	return lchan;
+}
+
+/* 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 = NULL;
+
+	LOG_BTS(bts, DRLL, LOGL_DEBUG, "lchan_select_by_type(%s)\n", gsm_lchant_name(type));
+
+	lchan = _get_lchan_by_type(bts, type);
+
 	if (lchan) {
 		lchan->type = type;
 		LOG_LCHAN(lchan, LOGL_INFO, "Selected\n");
@@ -240,3 +249,18 @@
 
 	return lchan;
 }
+
+/* Look through the available BTS resources and tell if a desired channel type would be available */
+bool lchan_select_avail(struct gsm_bts *bts, enum gsm_chan_t type)
+{
+	struct gsm_lchan *lchan = NULL;
+
+	LOG_BTS(bts, DRLL, LOGL_DEBUG, "lchan_select_avail(%s)\n", gsm_lchant_name(type));
+
+	lchan = _get_lchan_by_type(bts, type);
+
+	if (lchan)
+		return true;
+
+	return false;
+}
diff --git a/src/utils/bs11_config.c b/src/utils/bs11_config.c
index c279179..db804d5 100644
--- a/src/utils/bs11_config.c
+++ b/src/utils/bs11_config.c
@@ -995,3 +995,4 @@
 int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len)
 { return 0; }
 int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type) { return 0; }
+int abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts) { return 0; }
diff --git a/src/utils/meas_json.c b/src/utils/meas_json.c
index b44a300..6c9d438 100644
--- a/src/utils/meas_json.c
+++ b/src/utils/meas_json.c
@@ -210,3 +210,4 @@
 int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len)
 { return 0; }
 int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type) { return 0; }
+int abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts) { return 0; }
diff --git a/tests/abis/abis_test.c b/tests/abis/abis_test.c
index 9d26edd..e87564e 100644
--- a/tests/abis/abis_test.c
+++ b/tests/abis/abis_test.c
@@ -196,3 +196,4 @@
 int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len)
 { return 0; }
 int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type) { return 0; }
+int abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts) { return 0; }
diff --git a/tests/acc/acc_test.c b/tests/acc/acc_test.c
index 72d3212..e92972d 100644
--- a/tests/acc/acc_test.c
+++ b/tests/acc/acc_test.c
@@ -65,6 +65,8 @@
 		osmo_timer_del(&bts->acc_mgr.rotate_timer);
 	if (osmo_timer_pending(&bts->acc_ramp.step_timer))
 		osmo_timer_del(&bts->acc_ramp.step_timer);
+	if (osmo_timer_pending(&bts->chan_rqd_queue_timer))
+		osmo_timer_del(&bts->chan_rqd_queue_timer);
 	/* no need to llist_del(&bts->list), we never registered the bts there. */
 	talloc_free(bts);
 	fprintf(stderr, "BTS deallocated OK in %s()\n", msg);
@@ -531,3 +533,4 @@
 int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len)
 { return 0; }
 int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type) { return 0; }
+int abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts) { return 0; }
diff --git a/tests/bsc/bsc_test.c b/tests/bsc/bsc_test.c
index dd2b1bb..e387c37 100644
--- a/tests/bsc/bsc_test.c
+++ b/tests/bsc/bsc_test.c
@@ -245,3 +245,4 @@
 int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len)
 { return 0; }
 int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type) { return 0; }
+int abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts) { return 0; }
diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c
index 35531f8..18ee788 100644
--- a/tests/gsm0408/gsm0408_test.c
+++ b/tests/gsm0408/gsm0408_test.c
@@ -142,6 +142,8 @@
 	rate_ctr_group_free(bts->bts_ctrs);
 	if (osmo_timer_pending(&bts->acc_mgr.rotate_timer))
 		osmo_timer_del(&bts->acc_mgr.rotate_timer);
+	if (osmo_timer_pending(&bts->chan_rqd_queue_timer))
+		osmo_timer_del(&bts->chan_rqd_queue_timer);
 	/* no need to llist_del(&bts->list), we never registered the bts there. */
 	talloc_free(bts);
 	printf("BTS deallocated OK in %s()\n", msg);
@@ -976,3 +978,4 @@
 int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data, int len) { return 0; }
 int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len)
 { return 0; }
+int abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts) { return 0; }
diff --git a/tests/nanobts_omlattr/nanobts_omlattr_test.c b/tests/nanobts_omlattr/nanobts_omlattr_test.c
index ea98409..975c280 100644
--- a/tests/nanobts_omlattr/nanobts_omlattr_test.c
+++ b/tests/nanobts_omlattr/nanobts_omlattr_test.c
@@ -325,3 +325,4 @@
 int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len)
 { return 0; }
 int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type) { return 0; }
+int abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts) { return 0; }

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/19793
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: If8651265928797dbda9f528b544931dcfa4a0b36
Gerrit-Change-Number: 19793
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200821/58fe5bdd/attachment.htm>


More information about the gerrit-log mailing list