Change in osmo-bsc[master]: assignment_fsm: Properly support assigning signalling mode TCH/x

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/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Fri May 3 18:20:36 UTC 2019


Harald Welte has submitted this change and it was merged. ( https://gerrit.osmocom.org/13818 )

Change subject: assignment_fsm: Properly support assigning signalling mode TCH/x
......................................................................

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

Originally merged as Change-Id I4c7499c8c866ea3ff7b1327edb3615d003d927d3,
reverted because the change broke voice calls. Re-submitting with the fix:
don't forget to set conn->assignment.requires_voice_stream.

Signed-off-by: Sylvain Munaut <tnt at 246tNt.com>
Change-Id: I7513d2cbe8b695ba6f031ad11560c63a6535cf2d
---
M include/osmocom/bsc/gsm_data.h
M include/osmocom/bsc/lchan_select.h
M src/osmo-bsc/assignment_fsm.c
M src/osmo-bsc/codec_pref.c
M src/osmo-bsc/handover_fsm.c
M src/osmo-bsc/lchan_select.c
M src/osmo-bsc/osmo_bsc_bssap.c
M tests/codec_pref/codec_pref_test.c
8 files changed, 169 insertions(+), 133 deletions(-)

Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved
  tnt: Looks good to me, but someone else must approve



diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index dacc63b..dc686c3 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -98,9 +98,15 @@
 	SUBSCR_SCCP_ST_CONNECTED
 };
 
+enum channel_rate {
+	CH_RATE_SDCCH,
+	CH_RATE_HALF,
+	CH_RATE_FULL,
+};
+
 struct channel_mode_and_rate {
 	enum gsm48_chan_mode chan_mode;
-	bool full_rate;
+	enum channel_rate chan_rate;
 	uint16_t s15_s0;
 };
 
@@ -115,12 +121,9 @@
 	char msc_rtp_addr[INET_ADDRSTRLEN];
 	uint16_t msc_rtp_port;
 
-	/* Prefered rate/codec setting (mandatory) */
-	struct channel_mode_and_rate ch_mode_rate_pref;
-
-	/* Alternate rate/codec setting (optional) */
-	bool ch_mode_rate_alt_present;
-	struct channel_mode_and_rate ch_mode_rate_alt;
+	/* Rate/codec setting in preference order (need at least 1 !) */
+	int n_ch_mode_rate;
+	struct channel_mode_and_rate ch_mode_rate[3];
 };
 
 /* State of an ongoing Assignment, while the assignment_fsm is still busy. This serves as state separation to keep the
diff --git a/include/osmocom/bsc/lchan_select.h b/include/osmocom/bsc/lchan_select.h
index 4aecdf6..865181b 100644
--- a/include/osmocom/bsc/lchan_select.h
+++ b/include/osmocom/bsc/lchan_select.h
@@ -3,4 +3,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, bool full_rate);
+					    enum gsm48_chan_mode chan_mode, enum channel_rate chan_rate);
diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c
index fdfc080..834b58b 100644
--- a/src/osmo-bsc/assignment_fsm.c
+++ b/src/osmo-bsc/assignment_fsm.c
@@ -250,17 +250,15 @@
 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:
@@ -268,12 +266,12 @@
 	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;
 		}
@@ -319,47 +317,37 @@
  * 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;
+	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;
+		}
 
-	/* 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;
+		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;
+		}
 	}
 
-	/* 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;
-	}
-
+	conn->assignment.requires_voice_stream = requires_voice_pref;
 	return 0;
 }
 
@@ -369,18 +357,20 @@
 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) {
@@ -398,8 +388,14 @@
 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);
@@ -442,17 +438,13 @@
 		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
@@ -461,21 +453,22 @@
 		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);
diff --git a/src/osmo-bsc/codec_pref.c b/src/osmo-bsc/codec_pref.c
index 3e06114..b27defc 100644
--- a/src/osmo-bsc/codec_pref.c
+++ b/src/osmo-bsc/codec_pref.c
@@ -324,6 +324,7 @@
 {
 	unsigned int i;
 	uint8_t perm_spch;
+	bool full_rate;
 	bool match = false;
 	const struct gsm0808_speech_codec *sc_match = NULL;
 	int rc;
@@ -337,15 +338,16 @@
 		perm_spch = audio_support_to_gsm88(msc->audio_support[i]);
 
 		/* Determine if the result is a half or full rate codec */
-		rc = full_rate_from_perm_spch(&ch_mode_rate->full_rate, perm_spch);
+		rc = full_rate_from_perm_spch(&full_rate, perm_spch);
 		if (rc < 0)
 			return -EINVAL;
+		ch_mode_rate->chan_rate = full_rate ? CH_RATE_FULL : CH_RATE_HALF;
 
 		/* If we have a preference for FR or HR in our request, we
 		 * discard the potential match */
-		if (rate_pref == RATE_PREF_HR && ch_mode_rate->full_rate)
+		if (rate_pref == RATE_PREF_HR && ch_mode_rate->chan_rate == CH_RATE_FULL)
 			continue;
-		if (rate_pref == RATE_PREF_FR && !ch_mode_rate->full_rate)
+		if (rate_pref == RATE_PREF_FR && ch_mode_rate->chan_rate == CH_RATE_HALF)
 			continue;
 
 		/* Check this permitted speech value against the BTS specific parameters.
@@ -375,8 +377,8 @@
 
 	/* Exit without result, in case no match can be deteched */
 	if (!match) {
-		ch_mode_rate->full_rate = false;
 		ch_mode_rate->chan_mode = GSM48_CMODE_SIGN;
+		ch_mode_rate->chan_rate = CH_RATE_SDCCH;
 		ch_mode_rate->s15_s0 = 0;
 		return -1;
 	}
diff --git a/src/osmo-bsc/handover_fsm.c b/src/osmo-bsc/handover_fsm.c
index 0d1449f..c044407 100644
--- a/src/osmo-bsc/handover_fsm.c
+++ b/src/osmo-bsc/handover_fsm.c
@@ -582,10 +582,11 @@
 		}
 
 		LOG_HO(conn, LOGL_DEBUG, "BTS %u: Found matching audio type: %s %s (for %s)\n",
-		       bts->nr, gsm48_chan_mode_name(ch_mode_rate.chan_mode), ch_mode_rate.full_rate? "full-rate" : "half-rate",
+		       bts->nr, gsm48_chan_mode_name(ch_mode_rate.chan_mode),
+		       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.full_rate);
+		lchan = lchan_select_by_chan_mode(bts, ch_mode_rate.chan_mode, ch_mode_rate.chan_rate);
 		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 0f4dd65..0a9752e 100644
--- a/src/osmo-bsc/lchan_select.c
+++ b/src/osmo-bsc/lchan_select.c
@@ -128,22 +128,31 @@
 }
 
 struct gsm_lchan *lchan_select_by_chan_mode(struct gsm_bts *bts,
-					    enum gsm48_chan_mode chan_mode, bool full_rate)
+					    enum gsm48_chan_mode chan_mode, enum channel_rate chan_rate)
 {
 	enum gsm_chan_t type;
 
 	switch (chan_mode) {
 	case GSM48_CMODE_SIGN:
-		type = GSM_LCHAN_SDCCH;
+		switch (chan_rate) {
+		case CH_RATE_SDCCH: type = GSM_LCHAN_SDCCH; break;
+		case CH_RATE_HALF:  type = GSM_LCHAN_TCH_H; break;
+		case CH_RATE_FULL:  type = GSM_LCHAN_TCH_F; break;
+		default: return NULL;
+		}
 		break;
 	case GSM48_CMODE_SPEECH_EFR:
 		/* EFR works over FR channels only */
-		if (!full_rate)
+		if (chan_rate != CH_RATE_FULL)
 			return NULL;
 		/* fall through */
 	case GSM48_CMODE_SPEECH_V1:
 	case GSM48_CMODE_SPEECH_AMR:
-		type = full_rate ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H;
+		switch (chan_rate) {
+		case CH_RATE_HALF:  type = GSM_LCHAN_TCH_H; break;
+		case CH_RATE_FULL:  type = GSM_LCHAN_TCH_F; break;
+		default: return NULL;
+		}
 		break;
 	default:
 		return NULL;
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
index 2d5d4ae..470ae42 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -627,60 +627,48 @@
 static int select_codecs(struct assignment_request *req, struct gsm0808_channel_type *ct,
 			 struct gsm_subscriber_connection *conn)
 {
-	int rc;
+	int rc, i, nc = 0;
 	struct bsc_msc_data *msc;
 
 	msc = conn->sccp.msc;
-	req->ch_mode_rate_alt_present = false;
 
 	switch (ct->ch_rate_type) {
 	case GSM0808_SPEECH_FULL_BM:
-		rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),
+		rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),
 				      RATE_PREF_FR);
+		nc += (rc == 0);
 		break;
 	case GSM0808_SPEECH_HALF_LM:
-		rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),
+		rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),
 				      RATE_PREF_HR);
+		nc += (rc == 0);
 		break;
 	case GSM0808_SPEECH_PERM:
 	case GSM0808_SPEECH_PERM_NO_CHANGE:
 	case GSM0808_SPEECH_FULL_PREF_NO_CHANGE:
 	case GSM0808_SPEECH_FULL_PREF:
-		rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),
+		rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),
 				      RATE_PREF_FR);
-		if (rc < 0) {
-			rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),
-					      RATE_PREF_HR);
-			break;
-		}
-		rc = match_codec_pref(&req->ch_mode_rate_alt, ct, &conn->codec_list, msc, conn_get_bts(conn),
+		nc += (rc == 0);
+		rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),
 				      RATE_PREF_HR);
-		if (rc == 0)
-			req->ch_mode_rate_alt_present = true;
-		rc = 0;
+		nc += (rc == 0);
 		break;
 	case GSM0808_SPEECH_HALF_PREF_NO_CHANGE:
 	case GSM0808_SPEECH_HALF_PREF:
-		rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),
+		rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),
 				      RATE_PREF_HR);
-
-		if (rc < 0) {
-			rc = match_codec_pref(&req->ch_mode_rate_pref, ct, &conn->codec_list, msc, conn_get_bts(conn),
-					      RATE_PREF_FR);
-			break;
-		}
-		rc = match_codec_pref(&req->ch_mode_rate_alt, ct, &conn->codec_list, msc, conn_get_bts(conn),
+		nc += (rc == 0);
+		rc = match_codec_pref(&req->ch_mode_rate[nc], ct, &conn->codec_list, msc, conn_get_bts(conn),
 				      RATE_PREF_FR);
-		if (rc == 0)
-			req->ch_mode_rate_alt_present = true;
-		rc = 0;
+		nc += (rc == 0);
 		break;
 	default:
 		rc = -EINVAL;
 		break;
 	}
 
-	if (rc < 0) {
+	if (!nc) {
 		LOGP(DMSC, LOGL_ERROR, "No supported audio type found for channel_type ="
 		     " { ch_indctr=0x%x, ch_rate_type=0x%x, perm_spch=[%s] }\n",
 		     ct->ch_indctr, ct->ch_rate_type, osmo_hexdump(ct->perm_spch, ct->perm_spch_len));
@@ -689,29 +677,69 @@
 		return -EINVAL;
 	}
 
-	if (req->ch_mode_rate_alt_present) {
-		DEBUGP(DMSC, "Found matching audio type (preferred): %s %s for channel_type ="
+	for (i = 0; i < nc; i++ ) {
+		DEBUGP(DMSC, "Found matching audio type (pref=%d): %s %s for channel_type ="
 		       " { ch_indctr=0x%x, ch_rate_type=0x%x, perm_spch=[ %s] }\n",
-		       req->ch_mode_rate_pref.full_rate ? "full rate" : "half rate",
-		       get_value_string(gsm48_chan_mode_names, req->ch_mode_rate_pref.chan_mode),
+		       i,
+		       req->ch_mode_rate[i].chan_rate == CH_RATE_FULL ? "full rate" : "half rate",
+		       get_value_string(gsm48_chan_mode_names, req->ch_mode_rate[i].chan_mode),
 		       ct->ch_indctr, ct->ch_rate_type, osmo_hexdump(ct->perm_spch, ct->perm_spch_len));
-		DEBUGP(DMSC, "Found matching audio type (alternative): %s %s for channel_type ="
-		       " { ch_indctr=0x%x, ch_rate_type=0x%x, perm_spch=[ %s] }\n",
-		       req->ch_mode_rate_alt.full_rate ? "full rate" : "half rate",
-		       get_value_string(gsm48_chan_mode_names, req->ch_mode_rate_alt.chan_mode),
-		       ct->ch_indctr, ct->ch_rate_type, osmo_hexdump(ct->perm_spch, ct->perm_spch_len));
-	} else {
-		DEBUGP(DMSC, "Found matching audio type: %s %s for channel_type ="
-		       " { ch_indctr=0x%x, ch_rate_type=0x%x, perm_spch=[ %s] }\n",
-		       req->ch_mode_rate_pref.full_rate ? "full rate" : "half rate",
-		       get_value_string(gsm48_chan_mode_names, req->ch_mode_rate_pref.chan_mode),
-		       ct->ch_indctr, ct->ch_rate_type, osmo_hexdump(ct->perm_spch, ct->perm_spch_len));
-
 	}
 
+	req->n_ch_mode_rate = nc;
+
 	return 0;
 }
 
+static int select_sign_chan(struct assignment_request *req, struct gsm0808_channel_type *ct)
+{
+	int i, nc = 0;
+
+	switch (ct->ch_rate_type) {
+	case GSM0808_SIGN_ANY:
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_SDCCH;
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_HALF;
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_FULL;
+		break;
+	case GSM0808_SIGN_SDCCH:
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_SDCCH;
+		break;
+	case GSM0808_SIGN_SDCCH_FULL_BM:
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_SDCCH;
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_FULL;
+		break;
+	case GSM0808_SIGN_SDCCH_HALF_LM:
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_SDCCH;
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_HALF;
+		break;
+	case GSM0808_SIGN_FULL_BM:
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_FULL;
+		break;
+	case GSM0808_SIGN_HALF_LM:
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_HALF;
+		break;
+	case GSM0808_SIGN_FULL_PREF:
+	case GSM0808_SIGN_FULL_PREF_NO_CHANGE:
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_FULL;
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_HALF;
+		break;
+	case GSM0808_SIGN_HALF_PREF:
+	case GSM0808_SIGN_HALF_PREF_NO_CHANGE:
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_HALF;
+		req->ch_mode_rate[nc++].chan_rate = CH_RATE_FULL;
+		break;
+	default:
+		break;
+	}
+
+	for (i = 0; i < nc; i++)
+		req->ch_mode_rate[i].chan_mode = GSM48_CMODE_SIGN;
+
+	req->n_ch_mode_rate = nc;
+
+	return nc > 0 ? 0 : -EINVAL;
+}
+
 /*
  * Handle the assignment request message.
  *
@@ -729,7 +757,6 @@
 	uint8_t cause;
 	int rc;
 	struct assignment_request req = {};
-	struct channel_mode_and_rate ch_mode_rate_pref = {};
 
 	if (!conn) {
 		LOGP(DMSC, LOGL_ERROR,
@@ -850,14 +877,15 @@
 		}
 		break;
 	case GSM0808_CHAN_SIGN:
-		ch_mode_rate_pref = (struct channel_mode_and_rate) {
-			.chan_mode = GSM48_CMODE_SIGN,
-		};
-
 		req = (struct assignment_request){
 			.aoip = aoip,
-			.ch_mode_rate_pref = ch_mode_rate_pref,
 		};
+
+		rc = select_sign_chan(&req, &ct);
+		if (rc < 0) {
+			cause = GSM0808_CAUSE_INCORRECT_VALUE;
+			goto reject;
+		}
 		break;
 	default:
 		cause = GSM0808_CAUSE_INVALID_MESSAGE_CONTENTS;
diff --git a/tests/codec_pref/codec_pref_test.c b/tests/codec_pref/codec_pref_test.c
index bb5468a..ce82f3d 100644
--- a/tests/codec_pref/codec_pref_test.c
+++ b/tests/codec_pref/codec_pref_test.c
@@ -407,7 +407,7 @@
 
 	rc = match_codec_pref(&ch_mode_rate, ct, scl, msc, bts, RATE_PREF_NONE);
 	printf(" * result: rc=%i, full_rate=%i, s15_s0=%04x, chan_mode=%s\n",
-	       rc, ch_mode_rate.full_rate, ch_mode_rate.s15_s0, gsm48_chan_mode_name(ch_mode_rate.chan_mode));
+	       rc, ch_mode_rate.chan_rate == CH_RATE_FULL, ch_mode_rate.s15_s0, gsm48_chan_mode_name(ch_mode_rate.chan_mode));
 
 	printf("\n");
 

-- 
To view, visit https://gerrit.osmocom.org/13818
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: I7513d2cbe8b695ba6f031ad11560c63a6535cf2d
Gerrit-Change-Number: 13818
Gerrit-PatchSet: 2
Gerrit-Owner: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder (1000002)
Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: tnt <tnt at 246tNt.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190503/5af415cc/attachment.htm>


More information about the gerrit-log mailing list