diff options
-rw-r--r-- | include/osmocom/bsc/abis_rsl.h | 2 | ||||
-rw-r--r-- | include/osmocom/bsc/bts.h | 2 | ||||
-rw-r--r-- | include/osmocom/bsc/lchan_fsm.h | 2 | ||||
-rw-r--r-- | include/osmocom/bsc/lchan_select.h | 1 | ||||
-rw-r--r-- | src/ipaccess/ipaccess-config.c | 1 | ||||
-rw-r--r-- | src/ipaccess/ipaccess-proxy.c | 1 | ||||
-rw-r--r-- | src/osmo-bsc/abis_rsl.c | 241 | ||||
-rw-r--r-- | src/osmo-bsc/bts.c | 14 | ||||
-rw-r--r-- | src/osmo-bsc/lchan_fsm.c | 7 | ||||
-rw-r--r-- | src/osmo-bsc/lchan_select.c | 36 | ||||
-rw-r--r-- | src/utils/bs11_config.c | 1 | ||||
-rw-r--r-- | src/utils/meas_json.c | 1 | ||||
-rw-r--r-- | tests/abis/abis_test.c | 1 | ||||
-rw-r--r-- | tests/acc/acc_test.c | 3 | ||||
-rw-r--r-- | tests/bsc/bsc_test.c | 1 | ||||
-rw-r--r-- | tests/gsm0408/gsm0408_test.c | 3 | ||||
-rw-r--r-- | tests/nanobts_omlattr/nanobts_omlattr_test.c | 1 |
17 files changed, 271 insertions, 47 deletions
diff --git a/include/osmocom/bsc/abis_rsl.h b/include/osmocom/bsc/abis_rsl.h index 2611a3d00..146c63683 100644 --- a/include/osmocom/bsc/abis_rsl.h +++ b/include/osmocom/bsc/abis_rsl.h @@ -118,5 +118,7 @@ int ipacc_payload_type(enum gsm48_chan_mode tch_mode, enum gsm_chan_t type); 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 16053a3bb..693fb804a 100644 --- a/include/osmocom/bsc/bts.h +++ b/include/osmocom/bsc/bts.h @@ -495,6 +495,8 @@ struct gsm_bts { 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 d935b5281..7a09db344 100644 --- a/include/osmocom/bsc/lchan_fsm.h +++ b/include/osmocom/bsc/lchan_fsm.h @@ -74,3 +74,5 @@ bool lchan_may_receive_data(struct gsm_lchan *lchan); 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 865181bf5..7a828d98c 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 c9264d723..be5f6a8a3 100644 --- a/src/ipaccess/ipaccess-config.c +++ b/src/ipaccess/ipaccess-config.c @@ -1142,3 +1142,4 @@ int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data 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 d5dd8d4d5..fec866a75 100644 --- a/src/ipaccess/ipaccess-proxy.c +++ b/src/ipaccess/ipaccess-proxy.c @@ -1260,3 +1260,4 @@ int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data 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 42f3a4226..64c4af50c 100644 --- a/src/osmo-bsc/abis_rsl.c +++ b/src/osmo-bsc/abis_rsl.c @@ -1322,77 +1322,219 @@ int rsl_tx_imm_ass_rej(struct gsm_bts *bts, struct gsm48_req_ref *rqd_ref) 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 @@ static int rsl_rx_chan_rqd(struct msgb *msg) * - 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 @@ static int rsl_rx_chan_rqd(struct msgb *msg) 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 4318b7ef9..ff8526777 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 @@ const struct value_string bts_attribute_names[] = { { 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 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, uint8_t bts_num) 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 f6b3f2b5f..2e1f9a7b0 100644 --- a/src/osmo-bsc/lchan_fsm.c +++ b/src/osmo-bsc/lchan_fsm.c @@ -1477,6 +1477,13 @@ static void lchan_fsm_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, } } +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 d2dba1bb2..6f73fbcda 100644 --- a/src/osmo-bsc/lchan_select.c +++ b/src/osmo-bsc/lchan_select.c @@ -162,16 +162,11 @@ struct gsm_lchan *lchan_select_by_chan_mode(struct gsm_bts *bts, 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 @@ struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts, enum gsm_chan_t type 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 @@ struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts, enum gsm_chan_t type 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 c279179d5..db804d51a 100644 --- a/src/utils/bs11_config.c +++ b/src/utils/bs11_config.c @@ -995,3 +995,4 @@ int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data 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 b44a3008c..6c9d43890 100644 --- a/src/utils/meas_json.c +++ b/src/utils/meas_json.c @@ -210,3 +210,4 @@ int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data 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 9d26eddcd..e87564e22 100644 --- a/tests/abis/abis_test.c +++ b/tests/abis/abis_test.c @@ -196,3 +196,4 @@ int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data 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 72d3212f1..e92972d1e 100644 --- a/tests/acc/acc_test.c +++ b/tests/acc/acc_test.c @@ -65,6 +65,8 @@ static inline void _bts_del(struct gsm_bts *bts, const char *msg) 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_sacch_filling(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data 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 dd2b1bbb5..e387c37ea 100644 --- a/tests/bsc/bsc_test.c +++ b/tests/bsc/bsc_test.c @@ -245,3 +245,4 @@ int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data 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 35531f81a..18ee788e3 100644 --- a/tests/gsm0408/gsm0408_test.c +++ b/tests/gsm0408/gsm0408_test.c @@ -142,6 +142,8 @@ static inline void _bts_del(struct gsm_bts *bts, const char *msg) 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 @@ void pcu_info_update(struct gsm_bts *bts) {}; 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 ea9840942..975c2803b 100644 --- a/tests/nanobts_omlattr/nanobts_omlattr_test.c +++ b/tests/nanobts_omlattr/nanobts_omlattr_test.c @@ -325,3 +325,4 @@ int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data 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; } |