diff --git a/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus01-4trx.cfg b/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus01-4trx.cfg index 68837caf7..8ef161990 100644 --- a/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus01-4trx.cfg +++ b/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus01-4trx.cfg @@ -39,7 +39,7 @@ network ms max power 15 cell reselection hysteresis 4 rxlev access min 0 - channel allocator descending + channel allocator mode set-all descending rach tx integer 9 rach max transmission 7 oml e1 line 0 timeslot 1 sub-slot full diff --git a/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus02-4trx.cfg b/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus02-4trx.cfg index ae0b7db3a..7c9b84739 100644 --- a/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus02-4trx.cfg +++ b/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus02-4trx.cfg @@ -39,7 +39,7 @@ network ms max power 15 cell reselection hysteresis 4 rxlev access min 0 - channel allocator descending + channel allocator mode set-all descending rach tx integer 9 rach max transmission 7 oml e1 line 0 timeslot 1 sub-slot full diff --git a/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus02-8trx.cfg b/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus02-8trx.cfg index ff0b27797..6db88b541 100644 --- a/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus02-8trx.cfg +++ b/doc/examples/osmo-bsc/ericsson/osmo-bsc.dug20-rus02-8trx.cfg @@ -39,7 +39,7 @@ network ms max power 15 cell reselection hysteresis 4 rxlev access min 0 - channel allocator descending + channel allocator mode set-all descending rach tx integer 9 rach max transmission 7 oml e1 line 0 timeslot 1 sub-slot full diff --git a/doc/examples/osmo-bsc/ericsson/osmo-bsc.rbs2308.cfg b/doc/examples/osmo-bsc/ericsson/osmo-bsc.rbs2308.cfg index f79d45735..a90cfa107 100644 --- a/doc/examples/osmo-bsc/ericsson/osmo-bsc.rbs2308.cfg +++ b/doc/examples/osmo-bsc/ericsson/osmo-bsc.rbs2308.cfg @@ -45,7 +45,7 @@ network ms max power 33 cell reselection hysteresis 4 rxlev access min 0 - channel allocator descending + channel allocator mode set-all descending rach tx integer 9 rach max transmission 7 oml e1 line 0 timeslot 1 sub-slot full diff --git a/doc/examples/osmo-bsc/osmo-bsc-4trx.cfg b/doc/examples/osmo-bsc/osmo-bsc-4trx.cfg index 68d6a3829..206a3c7b8 100644 --- a/doc/examples/osmo-bsc/osmo-bsc-4trx.cfg +++ b/doc/examples/osmo-bsc/osmo-bsc-4trx.cfg @@ -17,7 +17,7 @@ network cell reselection hysteresis 4 rxlev access min 0 radio-link-timeout 32 - channel allocator ascending + channel allocator mode set-all ascending rach tx integer 9 rach max transmission 7 channel-description attach 1 diff --git a/doc/examples/osmo-bsc/osmo-bsc.cfg b/doc/examples/osmo-bsc/osmo-bsc.cfg index c86a491b6..22afa0740 100644 --- a/doc/examples/osmo-bsc/osmo-bsc.cfg +++ b/doc/examples/osmo-bsc/osmo-bsc.cfg @@ -29,7 +29,7 @@ network cell reselection hysteresis 4 rxlev access min 0 radio-link-timeout 32 - channel allocator ascending + channel allocator mode set-all ascending rach tx integer 9 rach max transmission 7 channel-description attach 1 diff --git a/doc/examples/osmo-bsc/osmo-bsc_custom-sccp.cfg b/doc/examples/osmo-bsc/osmo-bsc_custom-sccp.cfg index e60f39a3b..21187c79a 100644 --- a/doc/examples/osmo-bsc/osmo-bsc_custom-sccp.cfg +++ b/doc/examples/osmo-bsc/osmo-bsc_custom-sccp.cfg @@ -28,7 +28,7 @@ network cell reselection hysteresis 4 rxlev access min 0 radio-link-timeout 32 - channel allocator ascending + channel allocator mode set-all ascending rach tx integer 9 rach max transmission 7 channel-description attach 1 diff --git a/doc/manuals/chapters/bts-examples.adoc b/doc/manuals/chapters/bts-examples.adoc index 836dec03d..2afc8ff55 100644 --- a/doc/manuals/chapters/bts-examples.adoc +++ b/doc/manuals/chapters/bts-examples.adoc @@ -32,7 +32,7 @@ network ms max power 15 cell reselection hysteresis 4 rxlev access min 0 - channel allocator ascending + channel allocator mode set-all ascending rach tx integer 9 rach max transmission 7 ipa unit-id 1801 0 <4> @@ -110,7 +110,7 @@ network ms max power 15 cell reselection hysteresis 4 rxlev access min 0 - channel allocator ascending + channel allocator mode set-all ascending rach tx integer 9 rach max transmission 7 ipa unit-id 1800 0 <1> @@ -203,7 +203,7 @@ network ms max power 15 cell reselection hysteresis 4 rxlev access min 0 - channel allocator ascending + channel allocator mode set-all ascending rach tx integer 9 rach max transmission 7 oml e1 line 0 timeslot 1 sub-slot full <3> diff --git a/doc/manuals/chapters/chan_alloc.adoc b/doc/manuals/chapters/chan_alloc.adoc index d99512465..b6b7b9285 100644 --- a/doc/manuals/chapters/chan_alloc.adoc +++ b/doc/manuals/chapters/chan_alloc.adoc @@ -19,7 +19,9 @@ All parameters with their respective default values are listed below: ---- network bts 0 - channel allocator ascending + channel allocator mode chan-req ascending + channel allocator mode assignment ascending + channel allocator mode handover ascending channel allocator avoid-interference 0 channel allocator tch-signalling-policy always ---- @@ -41,10 +43,21 @@ selected in both ascending and descending modes. The allocation mode to be used can be configured using the following VTY command: ---- -OsmoBSC(config-net-bts)# channel allocator ? - ascending Allocate Timeslots and Transceivers in ascending order - descending Allocate Timeslots and Transceivers in descending order +OsmoBSC(config-net-bts)# channel allocator mode ? <1> + 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 + +OsmoBSC(config-net-bts)# channel allocator mode set-all ? <2> + ascending Allocate Timeslots and Transceivers in ascending order + descending Allocate Timeslots and Transceivers in descending order ---- +<1> It's optionally possible to configure different allocation modes for +different allocation causes, e.g. `ascending` for `chan-req` and `descending` +for both `assignment` and `handover`. +<2> `set-all` is equivalent to the old (deprecated) command syntax: +`channel allocator (ascending|descending)`. ==== Interference aware channel allocation diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h index 8abcf1323..76945a136 100644 --- a/include/osmocom/bsc/bts.h +++ b/include/osmocom/bsc/bts.h @@ -517,7 +517,9 @@ struct gsm_bts { /* should the channel allocator allocate channels from high TRX to TRX0, * rather than starting from TRX0 and go upwards? */ - int chan_alloc_reverse; + bool chan_alloc_chan_req_reverse; + bool chan_alloc_assignment_reverse; + bool chan_alloc_handover_reverse; /* When true, interference measurements from the BTS are used in the channel allocator to favor lchans with less * interference reported in RSL Resource Indication. */ diff --git a/include/osmocom/bsc/lchan_select.h b/include/osmocom/bsc/lchan_select.h index 3bb0d1ce6..b5eb078db 100644 --- a/include/osmocom/bsc/lchan_select.h +++ b/include/osmocom/bsc/lchan_select.h @@ -1,9 +1,24 @@ /* Select a suitable lchan from a given cell. */ #pragma once -struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts, enum gsm_chan_t type); +enum lchan_select_reason { + SELECT_FOR_MS_CHAN_REQ, + SELECT_FOR_ASSIGNMENT, + SELECT_FOR_HANDOVER, +}; + +extern const struct value_string lchan_select_reason_names[]; +static inline const char *lchan_select_reason_name(enum lchan_select_reason reason) +{ return get_value_string(lchan_select_reason_names, reason); } + +struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts, + enum gsm_chan_t type, + enum lchan_select_reason reason); enum gsm_chan_t chan_mode_to_chan_type(enum gsm48_chan_mode chan_mode, enum channel_rate chan_rate); struct gsm_lchan *lchan_select_by_chan_mode(struct gsm_bts *bts, - enum gsm48_chan_mode chan_mode, enum channel_rate chan_rate); -struct gsm_lchan *lchan_avail_by_type(struct gsm_bts *bts, enum gsm_chan_t type, bool log); + enum gsm48_chan_mode chan_mode, + enum channel_rate chan_rate, + enum lchan_select_reason reason); +struct gsm_lchan *lchan_avail_by_type(struct gsm_bts *bts, enum gsm_chan_t type, + enum lchan_select_reason reason, bool log); void lchan_select_set_type(struct gsm_lchan *lchan, enum gsm_chan_t type); 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)", - CHAN_ALLOC_DESC - "Allocate Timeslots and Transceivers in ascending order\n" - "Allocate Timeslots and Transceivers in descending order\n", - CMD_ATTR_IMMEDIATE) +#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; - if (!strcmp(argv[0], "ascending")) - bts->chan_alloc_reverse = 0; - else - bts->chan_alloc_reverse = 1; + 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 + "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 (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(%s)\n", gsm_lchant_name(type)); + 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)); + } + + 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; } diff --git a/tests/ctrl/osmo-bsc-apply-config-file.cfg b/tests/ctrl/osmo-bsc-apply-config-file.cfg index 1a069ce75..0094cd70d 100644 --- a/tests/ctrl/osmo-bsc-apply-config-file.cfg +++ b/tests/ctrl/osmo-bsc-apply-config-file.cfg @@ -9,7 +9,7 @@ network cell reselection hysteresis 4 rxlev access min 0 radio-link-timeout 32 - channel allocator ascending + channel allocator mode set-all ascending rach tx integer 9 rach max transmission 7 channel-description attach 1 diff --git a/tests/ctrl/osmo-bsc-neigh-test.cfg b/tests/ctrl/osmo-bsc-neigh-test.cfg index 93d7fca83..8c04db6d6 100644 --- a/tests/ctrl/osmo-bsc-neigh-test.cfg +++ b/tests/ctrl/osmo-bsc-neigh-test.cfg @@ -35,7 +35,7 @@ network cell reselection hysteresis 4 rxlev access min 0 radio-link-timeout 32 - channel allocator ascending + channel allocator mode set-all ascending rach tx integer 9 rach max transmission 7 channel-description attach 1 @@ -92,7 +92,7 @@ network cell reselection hysteresis 4 rxlev access min 0 radio-link-timeout 32 - channel allocator ascending + channel allocator mode set-all ascending rach tx integer 9 rach max transmission 7 channel-description attach 1 diff --git a/tests/handover/handover_test.c b/tests/handover/handover_test.c index d82ba9f90..77fa3712e 100644 --- a/tests/handover/handover_test.c +++ b/tests/handover/handover_test.c @@ -488,7 +488,8 @@ struct gsm_lchan *create_lchan(struct gsm_bts *bts, int full_rate, const char *c { struct gsm_lchan *lchan; - lchan = lchan_select_by_type(bts, (full_rate) ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H); + lchan = lchan_select_by_type(bts, (full_rate) ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H, + SELECT_FOR_HANDOVER); if (!lchan) { fprintf(stderr, "No resource for lchan\n"); exit(EXIT_FAILURE); diff --git a/tests/handover/test_dyn_ts_favor_static_ts_as_target.ho_vty b/tests/handover/test_dyn_ts_favor_static_ts_as_target.ho_vty index c50b00705..0c55a2c97 100644 --- a/tests/handover/test_dyn_ts_favor_static_ts_as_target.ho_vty +++ b/tests/handover/test_dyn_ts_favor_static_ts_as_target.ho_vty @@ -3,7 +3,7 @@ create-bts trx-count 1 timeslots c+s4 dyn TCH/H dyn TCH/H dyn TCH/H network bts 0 - channel allocator ascending + channel allocator mode set-all ascending set-ts-use trx 0 0 states * TCH/-H TCH/-H TCH/-H TCH/-H TCH/-H TCH/-H * diff --git a/tests/osmo-bsc.vty b/tests/osmo-bsc.vty index f2af32bca..e0b9bdc18 100644 --- a/tests/osmo-bsc.vty +++ b/tests/osmo-bsc.vty @@ -166,11 +166,20 @@ OsmoBSC(config-net-bts)# channel ? allocator Channel Allocator OsmoBSC(config-net-bts)# channel allocator ? - ascending Allocate Timeslots and Transceivers in ascending order - descending Allocate Timeslots and Transceivers in descending order + mode Channel allocation mode avoid-interference Configure whether reported interference levels from RES IND are used in channel allocation tch-signalling-policy Configure when TCH/H or TCH/F channels can be used to serve signalling if SDCCHs are exhausted +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 + +OsmoBSC(config-net-bts)# channel allocator mode set-all ? + ascending Allocate Timeslots and Transceivers in ascending order + descending Allocate Timeslots and Transceivers in descending order + OsmoBSC(config-net-bts)# channel allocator avoid-interference ? 0 Ignore interference levels (default). Always assign lchans in a deterministic order. 1 In channel allocation, prefer lchans with less interference.