diff options
author | Sylvain Munaut <tnt@246tNt.com> | 2019-03-07 16:32:02 +0100 |
---|---|---|
committer | tnt <tnt@246tNt.com> | 2019-03-14 08:31:58 +0000 |
commit | 4d3a21269b25e7164a94fa8ce3ad67ff80904aee (patch) | |
tree | 3542ca15253e0519e6801474ca224640566f7392 /src/osmo-bsc/assignment_fsm.c | |
parent | a58e10c1b62c9b757a37697da3d986e3e0d0e9de (diff) |
assignment_fsm: Properly support assigning signalling mode TCH/x
To support the 3 possible preferences, the changes needed were:
- Replace 'full_rate' bool with a 3 option enum to represent
the channels types for signalling
- Switch from _pref/_alt to using an array sorted in preference
order
Change-Id: I4c7499c8c866ea3ff7b1327edb3615d003d927d3
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Diffstat (limited to 'src/osmo-bsc/assignment_fsm.c')
-rw-r--r-- | src/osmo-bsc/assignment_fsm.c | 124 |
1 files changed, 58 insertions, 66 deletions
diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c index aa696ac0a..218079159 100644 --- a/src/osmo-bsc/assignment_fsm.c +++ b/src/osmo-bsc/assignment_fsm.c @@ -251,17 +251,15 @@ static void assignment_fsm_update_id(struct gsm_subscriber_connection *conn) static bool lchan_type_compat_with_mode(enum gsm_chan_t type, const struct channel_mode_and_rate *ch_mode_rate) { enum gsm48_chan_mode chan_mode = ch_mode_rate->chan_mode; - bool full_rate = ch_mode_rate->full_rate; + enum channel_rate chan_rate = ch_mode_rate->chan_rate; switch (chan_mode) { case GSM48_CMODE_SIGN: switch (type) { - case GSM_LCHAN_TCH_F: - case GSM_LCHAN_TCH_H: - case GSM_LCHAN_SDCCH: - return true; - default: - return false; + case GSM_LCHAN_TCH_F: return chan_rate == CH_RATE_FULL; + case GSM_LCHAN_TCH_H: return chan_rate == CH_RATE_HALF; + case GSM_LCHAN_SDCCH: return chan_rate == CH_RATE_SDCCH; + default: return false; } case GSM48_CMODE_SPEECH_V1: @@ -269,12 +267,12 @@ static bool lchan_type_compat_with_mode(enum gsm_chan_t type, const struct chann case GSM48_CMODE_DATA_3k6: case GSM48_CMODE_DATA_6k0: /* these services can all run on TCH/H, but we may have - * an explicit override by the 'full_rate' argument */ + * an explicit override by the 'chan_rate' argument */ switch (type) { case GSM_LCHAN_TCH_F: - return full_rate; + return chan_rate == CH_RATE_FULL; case GSM_LCHAN_TCH_H: - return !full_rate; + return chan_rate == CH_RATE_HALF; default: return false; } @@ -320,45 +318,34 @@ static int check_requires_voice(bool *requires_voice, enum gsm48_chan_mode chan_ * sure that both are consistent. */ static int check_requires_voice_stream(struct gsm_subscriber_connection *conn) { - bool result_requires_voice_alt; - bool result_requires_voice_pref; + bool requires_voice_pref = false, requires_voice_alt; struct assignment_request *req = &conn->assignment.req; struct osmo_fsm_inst *fi = conn->fi; - int rc; + int i, rc; /* When the assignment request indicates that there is an alternate * rate available (e.g. "Full or Half rate channel, Half rate * preferred..."), then both must be either voice or either signalling, * a mismatch is not permitted */ - /* Check the prefered setting */ - rc = check_requires_voice(&result_requires_voice_pref, req->ch_mode_rate_pref.chan_mode); - if (rc < 0) { - assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP, - "Prefered channel mode not supported: %s", - gsm48_chan_mode_name(req->ch_mode_rate_pref.chan_mode)); - return -EINVAL; - } - conn->assignment.requires_voice_stream = result_requires_voice_pref; - - /* If there is an alternate setting, check that one as well */ - if (!req->ch_mode_rate_alt_present) - return 0; - rc = check_requires_voice(&result_requires_voice_alt, req->ch_mode_rate_alt.chan_mode); - if (rc < 0) { - assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP, - "Alternate channel mode not supported: %s", - gsm48_chan_mode_name(req->ch_mode_rate_alt.chan_mode)); - return -EINVAL; - } + for (i = 0; i < req->n_ch_mode_rate; i++) { + rc = check_requires_voice(&requires_voice_alt, req->ch_mode_rate[i].chan_mode); + if (rc < 0) { + assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP, + "Channel mode not supported (prev level %d): %s", i, + gsm48_chan_mode_name(req->ch_mode_rate[i].chan_mode)); + return -EINVAL; + } - /* Make sure both settings match */ - if (result_requires_voice_pref != result_requires_voice_alt) { - assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP, - "Inconsistent channel modes: %s != %s", - gsm48_chan_mode_name(req->ch_mode_rate_pref.chan_mode), - gsm48_chan_mode_name(req->ch_mode_rate_alt.chan_mode)); - return -EINVAL; + if (i==0) + requires_voice_pref = requires_voice_alt; + else if (requires_voice_alt != requires_voice_pref) { + assignment_fail(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP, + "Inconsistent channel modes: %s != %s", + gsm48_chan_mode_name(req->ch_mode_rate[0].chan_mode), + gsm48_chan_mode_name(req->ch_mode_rate[i].chan_mode)); + return -EINVAL; + } } return 0; @@ -370,18 +357,20 @@ static int check_requires_voice_stream(struct gsm_subscriber_connection *conn) static bool reuse_existing_lchan(struct gsm_subscriber_connection *conn) { struct assignment_request *req = &conn->assignment.req; + int i; if (!conn->lchan) return false; /* Check if the currently existing lchan is compatible with the * preferred rate/codec. */ - if (lchan_type_compat_with_mode(conn->lchan->type, &req->ch_mode_rate_pref)) - conn->lchan->ch_mode_rate = req->ch_mode_rate_pref; - else if (req->ch_mode_rate_alt_present - && lchan_type_compat_with_mode(conn->lchan->type, &req->ch_mode_rate_alt)) - conn->lchan->ch_mode_rate = req->ch_mode_rate_alt; - else + for (i = 0; i < req->n_ch_mode_rate; i++) + if (lchan_type_compat_with_mode(conn->lchan->type, &req->ch_mode_rate[i])) { + conn->lchan->ch_mode_rate = req->ch_mode_rate[i]; + break; + } + + if (i == req->n_ch_mode_rate) return false; if (conn->lchan->tch_mode != conn->lchan->ch_mode_rate.chan_mode) { @@ -399,8 +388,14 @@ static bool reuse_existing_lchan(struct gsm_subscriber_connection *conn) void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts *bts, struct assignment_request *req) { + static const char *rate_names[] = { + [CH_RATE_SDCCH] = "SDCCH", + [CH_RATE_HALF] = "HR", + [CH_RATE_FULL] = "FR", + }; struct osmo_fsm_inst *fi; struct lchan_activate_info info; + int i; OSMO_ASSERT(conn); OSMO_ASSERT(conn->fi); @@ -443,17 +438,13 @@ void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts return; } - /* Try to allocate a new lchan with the preferred codec/rate choice */ - conn->assignment.new_lchan = - lchan_select_by_chan_mode(bts, req->ch_mode_rate_pref.chan_mode, req->ch_mode_rate_pref.full_rate); - conn->lchan->ch_mode_rate = req->ch_mode_rate_pref; - - /* In case the lchan allocation fails, we try with the alternat codec/ - * rate choice (if possible) */ - if (!conn->assignment.new_lchan && req->ch_mode_rate_alt_present) { - conn->assignment.new_lchan = - lchan_select_by_chan_mode(bts, req->ch_mode_rate_alt.chan_mode, req->ch_mode_rate_alt.full_rate); - conn->lchan->ch_mode_rate = req->ch_mode_rate_alt; + /* 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[i].chan_mode, req->ch_mode_rate[i].chan_rate); + conn->lchan->ch_mode_rate = req->ch_mode_rate[i]; + if (conn->assignment.new_lchan) + break; } /* Check whether the lchan allocation was successful or not and tear @@ -462,21 +453,22 @@ void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts assignment_count_result(BSC_CTR_ASSIGNMENT_NO_CHANNEL); assignment_fail(GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, "BSSMAP Assignment Command:" - " No lchan available for: preferred=%s%s / alternate=%s%s\n", - gsm48_chan_mode_name(req->ch_mode_rate_pref.chan_mode), - req->ch_mode_rate_pref.full_rate ? ",FR" : ",HR", - req->ch_mode_rate_alt_present ? - gsm48_chan_mode_name(req->ch_mode_rate_alt.chan_mode) : "none", - req->ch_mode_rate_alt_present ? - (req->ch_mode_rate_alt.full_rate ? ",FR" : ",HR") : ""); + " No lchan available for: pref=%s:%s / alt1=%s:%s / alt2=%s:%s\n", + gsm48_chan_mode_name(req->ch_mode_rate[0].chan_mode), + rate_names[req->ch_mode_rate[0].chan_rate], + req->n_ch_mode_rate >= 1 ? gsm48_chan_mode_name(req->ch_mode_rate[0].chan_mode) : "", + req->n_ch_mode_rate >= 1 ? rate_names[req->ch_mode_rate[0].chan_rate] : "", + req->n_ch_mode_rate >= 2 ? gsm48_chan_mode_name(req->ch_mode_rate[0].chan_mode) : "", + req->n_ch_mode_rate >= 2 ? rate_names[req->ch_mode_rate[0].chan_rate] : "" + ); return; } assignment_fsm_update_id(conn); - LOG_ASSIGNMENT(conn, LOGL_INFO, "Starting Assignment: chan_mode=%s, full_rate=%d," + LOG_ASSIGNMENT(conn, LOGL_INFO, "Starting Assignment: chan_mode=%s, chan_type=%s," " aoip=%s MSC-rtp=%s:%u\n", gsm48_chan_mode_name(conn->lchan->ch_mode_rate.chan_mode), - conn->lchan->ch_mode_rate.full_rate, + rate_names[conn->lchan->ch_mode_rate.chan_rate], req->aoip ? "yes" : "no", req->msc_rtp_addr, req->msc_rtp_port); assignment_fsm_state_chg(ASSIGNMENT_ST_WAIT_LCHAN_ACTIVE); |