neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-msc/+/30124 )
Change subject: [codecs filter] apply BSS codecs from Assignment Complete
......................................................................
[codecs filter] apply BSS codecs from Assignment Complete
Codec List (BSS Supported) is received once in Complete Layer 3 and
again in Assignment Complete messages. Use the most recent one, i.e. the
one from Assignment Complete, when it occurs.
Related: SYS#5066
Change-Id: I5e66ecc7987fa926f39d8be8eaf5799b931ab20a
---
M src/libmsc/msc_a.c
1 file changed, 5 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/24/30124/1
diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c
index 484617e..12ddae3 100644
--- a/src/libmsc/msc_a.c
+++ b/src/libmsc/msc_a.c
@@ -47,6 +47,7 @@
#include <osmocom/msc/rtp_stream.h>
#include <osmocom/msc/msc_ho.h>
#include <osmocom/msc/codec_mapping.h>
+#include <osmocom/msc/codec_filter.h>
#define MSC_A_USE_WAIT_CLEAR_COMPLETE "wait-Clear-Complete"
@@ -1353,6 +1354,10 @@
rtp_stream_commit(rtps_to_ran);
+ /* Remember the Codec List (BSS Supported) */
+ if (ac->assignment_complete.codec_list_bss_supported)
+ codec_filter_set_bss(&cc_trans->cc.codecs, ac->assignment_complete.codec_list_bss_supported);
+
/* Setup CN side endpoint CI:
* Now that
* - the first CI has been created and a definitive endpoint name is assigned to the call_leg's MGW
--
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/30124
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: I5e66ecc7987fa926f39d8be8eaf5799b931ab20a
Gerrit-Change-Number: 30124
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newchange
neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-msc/+/30120 )
Change subject: [codecs filter] MT call: apply BSS codec list
......................................................................
[codecs filter] MT call: apply BSS codec list
For MT call, initialize the codecs filter and apply the
Codec List (BSS Supported) from Compl L3.
Related: SYS#5066
Change-Id: I530409a64d11da48518a3dc60aa3a4e47c384663
---
M src/libmsc/gsm_04_08_cc.c
1 file changed, 10 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/20/30120/1
diff --git a/src/libmsc/gsm_04_08_cc.c b/src/libmsc/gsm_04_08_cc.c
index 032d9fe..5c7ff1f 100644
--- a/src/libmsc/gsm_04_08_cc.c
+++ b/src/libmsc/gsm_04_08_cc.c
@@ -674,6 +674,16 @@
gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
+ /* MT call leg is starting. Gather all codecs information so far known.
+ * (Usually) paging has succeeded, and now we're processing the MNCC Setup from the remote MO call leg.
+ * Initialize the codecs filter with this side's BSS' codec list, received at Complete Layer 3.
+ * We must not pass bearer_cap to codec_filter_init(), because we haven't received the MT MS's Bearer
+ * Capabilities yet; the Bearer Capabilities handled here are actually the remote call leg's Bearer
+ * Capabilities. */
+ codec_filter_init(&trans->cc.codecs);
+ codec_filter_set_ran(&trans->cc.codecs, trans->msc_a->c.ran->type);
+ codec_filter_set_bss(&trans->cc.codecs, &trans->msc_a->cc.compl_l3_codec_list_bss_supported);
+
/* bearer capability */
if (setup->fields & MNCC_F_BEARER_CAP) {
/* Create a copy of the bearer capability in the transaction struct, so we
--
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/30120
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: I530409a64d11da48518a3dc60aa3a4e47c384663
Gerrit-Change-Number: 30120
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newchange
neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-msc/+/30122 )
Change subject: [codecs filter] MT call: store MS Bearer Cap from CC Call Conf
......................................................................
[codecs filter] MT call: store MS Bearer Cap from CC Call Conf
Related: SYS#5066
Change-Id: Ic3d0f05af57a493d500700c63b121c8114e7fbf4
---
M src/libmsc/gsm_04_08_cc.c
1 file changed, 4 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/22/30122/1
diff --git a/src/libmsc/gsm_04_08_cc.c b/src/libmsc/gsm_04_08_cc.c
index d12220d..649b533 100644
--- a/src/libmsc/gsm_04_08_cc.c
+++ b/src/libmsc/gsm_04_08_cc.c
@@ -800,6 +800,10 @@
* this information later */
memcpy(&trans->bearer_cap, &call_conf.bearer_cap,
sizeof(trans->bearer_cap));
+
+ /* This is the MT call leg's Call Conf, containing the MS Bearer Capabilities of the MT MS.
+ * Store in codecs filter. */
+ codec_filter_set_ms_from_bc(&trans->cc.codecs, &call_conf.bearer_cap);
}
/* cause */
--
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/30122
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: Ic3d0f05af57a493d500700c63b121c8114e7fbf4
Gerrit-Change-Number: 30122
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newchange
neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-msc/+/30121 )
Change subject: [codecs filter] MT call: apply remote call leg codecs
......................................................................
[codecs filter] MT call: apply remote call leg codecs
Use either the SDP or the Bearer Capabilites indicated in the incoming
MNCC to apply the remote call leg's codecs selection to the codecs
filter. Use the codecs filter result for outgoing Bearer Capabilites.
So far, we just forwarded the Bearer Capabilities received in MNCC from
the remote call leg, and omitted Bearer Cap if the remote call leg did
not provide any.
Instead, always include Bearer Cap, and compose it from the codecs
filter result. Hence the Bearer Cap is now an intersection of MS, BSS
and remote call leg, instead of just the remote call leg.
Related: SYS#5066
Change-Id: I84d9bbca3e4061da622b1b2fc0bde8868e7e3521
---
M src/libmsc/gsm_04_08_cc.c
M tests/msc_vlr/msc_vlr_test_call.c
M tests/msc_vlr/msc_vlr_test_call.err
3 files changed, 64 insertions(+), 11 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/21/30121/1
diff --git a/src/libmsc/gsm_04_08_cc.c b/src/libmsc/gsm_04_08_cc.c
index 5c7ff1f..d12220d 100644
--- a/src/libmsc/gsm_04_08_cc.c
+++ b/src/libmsc/gsm_04_08_cc.c
@@ -639,6 +639,7 @@
struct gsm48_hdr *gh;
struct gsm_mncc *setup = arg;
int rc, trans_id;
+ struct gsm_mncc_bearer_cap bearer_cap;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
@@ -683,14 +684,60 @@
codec_filter_init(&trans->cc.codecs);
codec_filter_set_ran(&trans->cc.codecs, trans->msc_a->c.ran->type);
codec_filter_set_bss(&trans->cc.codecs, &trans->msc_a->cc.compl_l3_codec_list_bss_supported);
-
- /* bearer capability */
- if (setup->fields & MNCC_F_BEARER_CAP) {
- /* Create a copy of the bearer capability in the transaction struct, so we
- * can use this information later */
- memcpy(&trans->bearer_cap, &setup->bearer_cap, sizeof(trans->bearer_cap));
- gsm48_encode_bearer_cap(msg, 0, &setup->bearer_cap);
+ /* sdp.remote: if SDP is included in the MNCC, take that as definitive list of remote audio codecs. */
+ if (setup->sdp[0]) {
+ rc = sdp_msg_from_sdp_str(&trans->cc.codecs.remote, setup->sdp);
+ if (rc)
+ LOG_TRANS(trans, LOGL_ERROR, "Failed to parse remote call leg SDP: %d\n", rc);
}
+ /* sdp.remote: if there is no SDP information or we failed to parse it, try using the Bearer Capability from
+ * MNCC, if any. */
+ if (!trans->cc.codecs.remote.audio_codecs.count && (setup->fields & MNCC_F_BEARER_CAP)) {
+ trans->cc.codecs.remote = (struct sdp_msg){};
+ sdp_audio_codecs_from_bearer_cap(&trans->cc.codecs.remote.audio_codecs,
+ &setup->bearer_cap);
+ }
+ LOG_TRANS(trans, LOGL_DEBUG, "codecs: %s\n", codec_filter_to_str(&trans->cc.codecs));
+ if (!trans->cc.codecs.remote.audio_codecs.count)
+ LOG_TRANS(trans, LOGL_INFO,
+ "Got no information of remote audio codecs: neither SDP nor Bearer Capability. Trying anyway.\n");
+
+ codec_filter_run(&trans->cc.codecs);
+ LOG_TRANS(trans, LOGL_DEBUG, "codecs: %s\n", codec_filter_to_str(&trans->cc.codecs));
+
+ /* Compose Bearer Capability information that reflects only the codecs (Speech Versions) remaining after
+ * intersecting MS, BSS and remote call leg restrictions. To store in trans for later use, and to include in
+ * the outgoing CC Setup message. */
+ bearer_cap = (struct gsm_mncc_bearer_cap){
+ .speech_ver = { -1 },
+ };
+ sdp_audio_codecs_to_bearer_cap(&bearer_cap, &trans->cc.codecs.result.audio_codecs);
+ rc = bearer_cap_set_radio(&bearer_cap);
+ if (rc) {
+ LOG_TRANS(trans, LOGL_ERROR, "Error composing Bearer Capability for CC Setup\n");
+ trans_free(trans);
+ msgb_free(msg);
+ return rc;
+ }
+ /* Create a copy of the bearer capability in the transaction struct, so we can use this information later */
+ trans->bearer_cap = bearer_cap;
+ /* If no resulting codecs remain, error out. We cannot find a codec that matches both call legs. If the MGW were
+ * able to transcode, we could use non-identical codecs on each conn of the MGW endpoint, but we are aiming for
+ * finding a matching codec. */
+ if (bearer_cap.speech_ver[0] == -1) {
+ LOG_TRANS(trans, LOGL_ERROR, "%s: no codec match possible: %s\n",
+ get_mncc_name(setup->msg_type), codec_filter_to_str(&trans->cc.codecs));
+
+ /* incompatible codecs */
+ rc = mncc_release_ind(trans->net, trans, trans->callref,
+ GSM48_CAUSE_LOC_PRN_S_LU,
+ GSM48_CC_CAUSE_INCOMPAT_DEST /* TODO: correct cause code? */);
+ trans_free(trans);
+ msgb_free(msg);
+ return rc;
+ }
+ gsm48_encode_bearer_cap(msg, 0, &bearer_cap);
+
/* facility */
if (setup->fields & MNCC_F_FACILITY)
gsm48_encode_facility(msg, 0, &setup->facility);
diff --git a/tests/msc_vlr/msc_vlr_test_call.c b/tests/msc_vlr/msc_vlr_test_call.c
index a547935..d169650 100644
--- a/tests/msc_vlr/msc_vlr_test_call.c
+++ b/tests/msc_vlr/msc_vlr_test_call.c
@@ -316,7 +316,7 @@
VERBOSE_ASSERT(security_mode_ctrl_sent, == true, "%d");
btw("MS sends SecurityModeControl acceptance, VLR accepts, sends CC Setup");
- dtap_expect_tx("0305" /* CC: Setup */);
+ dtap_expect_tx("0305" /* CC: Setup */ "04 07 60 04 05 0b 06 08 87" /* Bearer Cap */);
ms_sends_security_mode_complete(1);
btw("MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND");
@@ -419,7 +419,7 @@
VERBOSE_ASSERT(security_mode_ctrl_sent, == true, "%d");
btw("MS sends SecurityModeControl acceptance, VLR accepts, sends CC Setup");
- dtap_expect_tx("0305" /* CC: Setup */);
+ dtap_expect_tx("0305" /* CC: Setup */ "04 07 60 04 05 0b 06 08 87" /* Bearer Cap */);
ms_sends_security_mode_complete(1);
btw("MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND");
diff --git a/tests/msc_vlr/msc_vlr_test_call.err b/tests/msc_vlr/msc_vlr_test_call.err
index 0018d86..1c0799c 100644
--- a/tests/msc_vlr/msc_vlr_test_call.err
+++ b/tests/msc_vlr/msc_vlr_test_call.err
@@ -761,10 +761,13 @@
DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED
DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING
DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting timer T303 with 30 seconds
+DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{(no-codecs)} (from: RAN={AMR:octet-align=1#112,AMR-WB:octet-align=1#113})
+DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) Got no information of remote audio codecs: neither SDP nor Bearer Capability. Trying anyway.
+DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112,AMR-WB:octet-align=1#113} (from: RAN={AMR:octet-align=1#112,AMR-WB:octet-align=1#113})
DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state NULL -> CALL_PRESENT
DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_SETUP
DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on UTRAN-Iu
-- DTAP --UTRAN-Iu--> MS: GSM48_MT_CC_SETUP: 0305
+- DTAP --UTRAN-Iu--> MS: GSM48_MT_CC_SETUP: 030504076004050b060887
- DTAP matches expected message
DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST
DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - Paging: now used by 3 (attached,CC,active-conn)
@@ -1231,10 +1234,13 @@
DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED
DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING
DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting timer T303 with 30 seconds
+DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{(no-codecs)} (from: RAN={AMR:octet-align=1#112,AMR-WB:octet-align=1#113})
+DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) Got no information of remote audio codecs: neither SDP nor Bearer Capability. Trying anyway.
+DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112,AMR-WB:octet-align=1#113} (from: RAN={AMR:octet-align=1#112,AMR-WB:octet-align=1#113})
DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state NULL -> CALL_PRESENT
DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_SETUP
DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on UTRAN-Iu
-- DTAP --UTRAN-Iu--> MS: GSM48_MT_CC_SETUP: 0305
+- DTAP --UTRAN-Iu--> MS: GSM48_MT_CC_SETUP: 030504076004050b060887
- DTAP matches expected message
DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST
DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - Paging: now used by 3 (attached,CC,active-conn)
--
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/30121
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: I84d9bbca3e4061da622b1b2fc0bde8868e7e3521
Gerrit-Change-Number: 30121
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newchange
neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-msc/+/30118 )
Change subject: [codecs filter] store BSS codec list from Compl L3
......................................................................
[codecs filter] store BSS codec list from Compl L3
The initial Compl L3 happens long before we establish a CC transaction.
Remember the Codec List (BSS Supported), so that we can feed the new
codecs filter with it. Subsequent patches implement feeding the filter.
Related: SYS#5066
Change-Id: I7cdc348218433141a43d2e42750af02591688240
---
M include/osmocom/msc/msc_a.h
M src/libmsc/msc_a.c
2 files changed, 15 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/18/30118/1
diff --git a/include/osmocom/msc/msc_a.h b/include/osmocom/msc/msc_a.h
index e56ea52..18eb76c 100644
--- a/include/osmocom/msc/msc_a.h
+++ b/include/osmocom/msc/msc_a.h
@@ -121,6 +121,9 @@
* \-------RTP--> (ISUP) <--RTP--> <--RTP-->
*/
struct {
+ /* Codec List (BSS Supported) as received during Complete Layer 3 Information */
+ struct gsm0808_speech_codec_list compl_l3_codec_list_bss_supported;
+
/* All of the RTP stream handling */
struct call_leg *call_leg;
struct mncc_call *mncc_forwarding_to_remote_ran;
diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c
index d7e97cd..484617e 100644
--- a/src/libmsc/msc_a.c
+++ b/src/libmsc/msc_a.c
@@ -46,6 +46,7 @@
#include <osmocom/msc/call_leg.h>
#include <osmocom/msc/rtp_stream.h>
#include <osmocom/msc/msc_ho.h>
+#include <osmocom/msc/codec_mapping.h>
#define MSC_A_USE_WAIT_CLEAR_COMPLETE "wait-Clear-Complete"
@@ -1442,6 +1443,17 @@
.lai.plmn = msc_a_net(msc_a)->plmn,
};
gsm0808_cell_id_to_cgi(&msc_a->via_cell, msg->compl_l3.cell_id);
+ /* If a codec list was sent along in the RAN_MSG_COMPL_L3, remember it for any upcoming codec
+ * resolution. */
+ if (msg->compl_l3.codec_list_bss_supported) {
+ msc_a->cc.compl_l3_codec_list_bss_supported = *msg->compl_l3.codec_list_bss_supported;
+ if (log_check_level(msc_a->c.ran->log_subsys, LOGL_DEBUG)) {
+ struct sdp_audio_codecs ac = {};
+ sdp_audio_codecs_from_speech_codec_list(&ac, &msc_a->cc.compl_l3_codec_list_bss_supported);
+ LOG_MSC_A(msc_a, LOGL_DEBUG, "Complete Layer 3: Codec List (BSS Supported): %s\n",
+ sdp_audio_codecs_to_str(&ac));
+ }
+ }
rc = msc_a_up_l3(msc_a, msg->compl_l3.msg);
if (!rc) {
struct ran_conn *conn = msub_ran_conn(msc_a->c.msub);
--
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/30118
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: I7cdc348218433141a43d2e42750af02591688240
Gerrit-Change-Number: 30118
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newchange
neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-msc/+/30116 )
Change subject: [codecs filter] add codec_filter.h,c
......................................................................
[codecs filter] add codec_filter.h,c
Add the infrastructure to store and filter all codec limitiations from
the different stages: MS, BSS, CN and remote call leg. Upcoming patches
will properly collect these and find an optimal codec.
No functional change, yet.
Related: SYS#5066
Change-Id: I4d90f7ca62f2307a7b93dd164aeecbf4bd98ff0a
---
M include/osmocom/msc/Makefile.am
A include/osmocom/msc/codec_filter.h
M src/libmsc/Makefile.am
A src/libmsc/codec_filter.c
4 files changed, 279 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/16/30116/1
diff --git a/include/osmocom/msc/Makefile.am b/include/osmocom/msc/Makefile.am
index 80f8972..34b4902 100644
--- a/include/osmocom/msc/Makefile.am
+++ b/include/osmocom/msc/Makefile.am
@@ -1,6 +1,7 @@
noinst_HEADERS = \
call_leg.h \
cell_id_list.h \
+ codec_filter.h \
codec_mapping.h \
db.h \
debug.h \
diff --git a/include/osmocom/msc/codec_filter.h b/include/osmocom/msc/codec_filter.h
new file mode 100644
index 0000000..16315c7
--- /dev/null
+++ b/include/osmocom/msc/codec_filter.h
@@ -0,0 +1,66 @@
+/* Filter/overlay codec selections for a voice call, across MS, RAN and CN limitations */
+/*
+ * (C) 2019-2022 by sysmocom - s.m.f.c. GmbH <info(a)sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#pragma once
+
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/mncc.h>
+#include <osmocom/mgcp_client/mgcp_client.h>
+
+#include <osmocom/msc/sdp_msg.h>
+
+struct gsm0808_speech_codec_list;
+
+/* Combine various codec selections to obtain a resulting set of codecs allowed by all of them.
+ * Members reflect the different entities/stages that select codecs in a voice call.
+ * Call codec_filter_run() and obtain the resulting set of codecs in codec_filter.result. */
+struct codec_filter {
+ /* The fixed set of codecs available on the RAN type, per definition. */
+ struct sdp_audio_codecs ran;
+ /* The codecs advertised by the MS Bearer Capabilities */
+ struct sdp_audio_codecs ms;
+ /* If known, the set of codecs the current RAN cell allows / has available.
+ * This may not be available if the BSC does not issue this information early enough.
+ * Should be ignored if empty. */
+ struct sdp_audio_codecs bss;
+
+ /* SDP as last received from the remote call leg. */
+ struct sdp_msg remote;
+
+ /* After a channel was assigned, this reflects the chosen codec. */
+ struct sdp_audio_codec assignment;
+
+ /* Resulting choice of supported codecs, usually the intersection of the above,
+ * and the local RTP address to be sent to the remote call leg.
+ * The RTP address:port in result.rtp is not modified by codec_filter_run() -- set it once. */
+ struct sdp_msg result;
+};
+
+void codec_filter_init(struct codec_filter *codec_filter);
+void codec_filter_set_ran(struct codec_filter *codec_filter, enum osmo_rat_type ran_type);
+void codec_filter_set_ms_from_bc(struct codec_filter *codec_filter, const struct gsm_mncc_bearer_cap *ms_bearer_cap);
+void codec_filter_set_bss(struct codec_filter *codec_filter,
+ const struct gsm0808_speech_codec_list *codec_list_bss_supported);
+int codec_filter_set_remote(struct codec_filter *codec_filter, const char *remote_sdp);
+void codec_filter_set_local_rtp(struct codec_filter *codec_filter, const struct osmo_sockaddr_str *rtp);
+int codec_filter_run(struct codec_filter *codec_filter);
+
+int codec_filter_to_str_buf(char *buf, size_t buflen, const struct codec_filter *codec_filter);
+char *codec_filter_to_str_c(void *ctx, const struct codec_filter *codec_filter);
+const char *codec_filter_to_str(const struct codec_filter *codec_filter);
diff --git a/src/libmsc/Makefile.am b/src/libmsc/Makefile.am
index c7fe4bb..bde70c9 100644
--- a/src/libmsc/Makefile.am
+++ b/src/libmsc/Makefile.am
@@ -27,6 +27,7 @@
libmsc_a_SOURCES = \
call_leg.c \
cell_id_list.c \
+ codec_filter.c \
codec_mapping.c \
sccp_ran.c \
msc_vty.c \
diff --git a/src/libmsc/codec_filter.c b/src/libmsc/codec_filter.c
new file mode 100644
index 0000000..e3c49c9
--- /dev/null
+++ b/src/libmsc/codec_filter.c
@@ -0,0 +1,211 @@
+/* Filter/overlay codec selections for a voice call, across MS, RAN and CN limitations */
+/*
+ * (C) 2019-2022 by sysmocom - s.m.f.c. GmbH <info(a)sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <osmocom/gsm/protocol/gsm_08_08.h>
+
+#include <osmocom/msc/codec_filter.h>
+#include <osmocom/msc/codec_mapping.h>
+#include <osmocom/msc/debug.h>
+
+/* Add all known payload types encountered in GSM networks */
+static void sdp_add_all_mobile_codecs(struct sdp_audio_codecs *ac)
+{
+ /* In order of preference. TODO: make configurable */
+ static const enum gsm48_bcap_speech_ver mobile_codecs[] = {
+ GSM48_BCAP_SV_AMR_F /*!< 4 GSM FR V3 (FR AMR) */,
+ GSM48_BCAP_SV_AMR_H /*!< 5 GSM HR V3 (HR_AMR) */,
+ GSM48_BCAP_SV_EFR /*!< 2 GSM FR V2 (GSM EFR) */,
+ GSM48_BCAP_SV_FR /*!< 0 GSM FR V1 (GSM FR) */,
+ GSM48_BCAP_SV_HR /*!< 1 GSM HR V1 (GSM HR) */,
+ };
+ int i;
+ for (i = 0; i < ARRAY_SIZE(mobile_codecs); i++)
+ sdp_audio_codecs_add_speech_ver(ac, mobile_codecs[i]);
+}
+
+/* Add all known AMR payload types encountered in UTRAN networks */
+static void sdp_add_all_utran_codecs(struct sdp_audio_codecs *ac)
+{
+ /* In order of preference. TODO: make configurable */
+ static const enum gsm48_bcap_speech_ver utran_codecs[] = {
+ GSM48_BCAP_SV_AMR_F /*!< 4 GSM FR V3 (FR AMR) */,
+ GSM48_BCAP_SV_AMR_H /*!< 5 GSM HR V3 (HR_AMR) */,
+ GSM48_BCAP_SV_AMR_OH /*!< 11 GSM HR V6 (OHR AMR) */,
+ GSM48_BCAP_SV_AMR_FW /*!< 8 GSM FR V5 (FR AMR-WB) */,
+ GSM48_BCAP_SV_AMR_OFW /*!< 6 GSM FR V4 (OFR AMR-WB) */,
+ GSM48_BCAP_SV_AMR_OHW /*!< 7 GSM HR V4 (OHR AMR-WB) */,
+ };
+ int i;
+ for (i = 0; i < ARRAY_SIZE(utran_codecs); i++)
+ sdp_audio_codecs_add_speech_ver(ac, utran_codecs[i]);
+}
+
+void codec_filter_init(struct codec_filter *codec_filter)
+{
+ *codec_filter = (struct codec_filter){};
+}
+
+void codec_filter_set_ran(struct codec_filter *codec_filter, enum osmo_rat_type ran_type)
+{
+ codec_filter->ran = (struct sdp_audio_codecs){};
+
+ switch (ran_type) {
+ default:
+ case OSMO_RAT_GERAN_A:
+ sdp_add_all_mobile_codecs(&codec_filter->ran);
+ break;
+
+ case OSMO_RAT_UTRAN_IU:
+ sdp_add_all_utran_codecs(&codec_filter->ran);
+ break;
+ }
+}
+
+void codec_filter_set_ms_from_bc(struct codec_filter *codec_filter, const struct gsm_mncc_bearer_cap *ms_bearer_cap)
+{
+ codec_filter->ms = (struct sdp_audio_codecs){0};
+ if (ms_bearer_cap)
+ sdp_audio_codecs_from_bearer_cap(&codec_filter->ms, ms_bearer_cap);
+}
+
+void codec_filter_set_bss(struct codec_filter *codec_filter,
+ const struct gsm0808_speech_codec_list *codec_list_bss_supported)
+{
+ codec_filter->bss = (struct sdp_audio_codecs){};
+ if (codec_list_bss_supported)
+ sdp_audio_codecs_from_speech_codec_list(&codec_filter->bss, codec_list_bss_supported);
+}
+
+int codec_filter_set_remote(struct codec_filter *codec_filter, const char *remote_sdp)
+{
+ return sdp_msg_from_sdp_str(&codec_filter->remote, remote_sdp);
+}
+
+void codec_filter_set_local_rtp(struct codec_filter *codec_filter, const struct osmo_sockaddr_str *rtp)
+{
+ if (!rtp)
+ codec_filter->result.rtp = (struct osmo_sockaddr_str){0};
+ else
+ codec_filter->result.rtp = *rtp;
+}
+
+/* Render intersections of all known audio codec constraints to reach a resulting choice of favorite audio codec, plus
+ * possible set of alternative audio codecs, in codec_filter->result. (The result.rtp address remains unchanged.) */
+int codec_filter_run(struct codec_filter *codec_filter)
+{
+ struct sdp_audio_codecs *r = &codec_filter->result.audio_codecs;
+ struct sdp_audio_codec *a = &codec_filter->assignment;
+ *r = codec_filter->ran;
+ if (codec_filter->ms.count)
+ sdp_audio_codecs_intersection(r, &codec_filter->ms, false);
+ if (codec_filter->bss.count)
+ sdp_audio_codecs_intersection(r, &codec_filter->bss, false);
+ if (codec_filter->remote.audio_codecs.count)
+ sdp_audio_codecs_intersection(r, &codec_filter->remote.audio_codecs, true);
+
+#if ALLOW_REASSIGNMENT
+ /* If osmo-msc were able to trigger a re-assignment after the remote side has picked a codec mismatching the
+ * initial Assignment, then this code here would make sense: keep the other codecs as available to choose from,
+ * but put the currently assigned codec in the first position. */
+ if (sdp_audio_codec_is_set(a)) {
+ /* Assignment has completed, the chosen codec should be the first of the resulting SDP.
+ * Make sure this is actually listed in the result SDP and move to first place. */
+ struct sdp_audio_codec *select = sdp_audio_codec_by_descr(r, a);
+
+ if (!select) {
+ /* Not present. Add. */
+ if (sdp_audio_codec_by_payload_type(r, a->payload_type, false)) {
+ /* Oh crunch, that payload type number is already in use.
+ * Find an unused one. */
+ for (a->payload_type = 96; a->payload_type <= 127; a->payload_type++) {
+ if (!sdp_audio_codec_by_payload_type(r, a->payload_type, false))
+ break;
+ }
+
+ if (a->payload_type > 127)
+ return -ENOSPC;
+ }
+ select = sdp_audio_codec_add_copy(r, a);
+ }
+
+ sdp_audio_codecs_select(r, select);
+ }
+#else
+ /* Currently, osmo-msc does not trigger re-assignment if the remote side has picked a codec that the local side
+ * would also support, but the local side has already assigned a mismatching codec before. Mismatching codecs
+ * means call failure. So, currently, if locally, Assignment has already happened, it makes sense to send only
+ * the assigned codec as available choice to the remote side. */
+ if (sdp_audio_codec_is_set(a)) {
+ /* Assignment has completed, the chosen codec should be the the only possible one. */
+ struct sdp_audio_codecs assigned_codec = {};
+ sdp_audio_codecs_add_copy(&assigned_codec, a);
+ sdp_audio_codecs_intersection(r, &assigned_codec, false);
+ }
+#endif
+ return 0;
+}
+
+int codec_filter_to_str_buf(char *buf, size_t buflen, const struct codec_filter *codec_filter)
+{
+ struct osmo_strbuf sb = { .buf = buf, .len = buflen };
+ OSMO_STRBUF_APPEND(sb, sdp_msg_to_str_buf, &codec_filter->result);
+ OSMO_STRBUF_PRINTF(sb, " (from:");
+
+ if (sdp_audio_codec_is_set(&codec_filter->assignment)) {
+ OSMO_STRBUF_PRINTF(sb, " assigned=");
+ OSMO_STRBUF_APPEND(sb, sdp_audio_codec_to_str_buf, &codec_filter->assignment);
+ }
+
+ if (codec_filter->remote.audio_codecs.count
+ || osmo_sockaddr_str_is_nonzero(&codec_filter->remote.rtp)) {
+ OSMO_STRBUF_PRINTF(sb, " remote=");
+ OSMO_STRBUF_APPEND(sb, sdp_msg_to_str_buf, &codec_filter->remote);
+ }
+
+ if (codec_filter->ms.count) {
+ OSMO_STRBUF_PRINTF(sb, " MS={");
+ OSMO_STRBUF_APPEND(sb, sdp_audio_codecs_to_str_buf, &codec_filter->ms);
+ OSMO_STRBUF_PRINTF(sb, "}");
+ }
+
+ if (codec_filter->bss.count) {
+ OSMO_STRBUF_PRINTF(sb, " bss={");
+ OSMO_STRBUF_APPEND(sb, sdp_audio_codecs_to_str_buf, &codec_filter->bss);
+ OSMO_STRBUF_PRINTF(sb, "}");
+ }
+
+ OSMO_STRBUF_PRINTF(sb, " RAN={");
+ OSMO_STRBUF_APPEND(sb, sdp_audio_codecs_to_str_buf, &codec_filter->ran);
+ OSMO_STRBUF_PRINTF(sb, "}");
+
+ OSMO_STRBUF_PRINTF(sb, ")");
+
+ return sb.chars_needed;
+}
+
+char *codec_filter_to_str_c(void *ctx, const struct codec_filter *codec_filter)
+{
+ OSMO_NAME_C_IMPL(ctx, 128, "codec_filter_to_str_c-ERROR", codec_filter_to_str_buf, codec_filter)
+}
+
+const char *codec_filter_to_str(const struct codec_filter *codec_filter)
+{
+ return codec_filter_to_str_c(OTC_SELECT, codec_filter);
+}
--
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/30116
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: I4d90f7ca62f2307a7b93dd164aeecbf4bd98ff0a
Gerrit-Change-Number: 30116
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newchange