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
This commit is contained in:
parent
ff9d3a64dc
commit
c2928ac269
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue