msc_vlr_test_call: test codecs resolution
Related: SYS#5066 Change-Id: I879ec61f523ad4ffc69a0b02810591f7c0261ff9
This commit is contained in:
parent
7f4fd0f2a7
commit
4b53b035b8
|
@ -24,6 +24,7 @@
|
|||
#include "msc_vlr_tests.h"
|
||||
|
||||
#include <osmocom/msc/gsm_04_08.h>
|
||||
#include <osmocom/msc/codec_sdp_cc_t9n.h>
|
||||
|
||||
#define mncc_sends_to_cc(MSG_TYPE, MNCC) do { \
|
||||
(MNCC)->msg_type = MSG_TYPE; \
|
||||
|
@ -163,6 +164,44 @@ static void lu_utran_tmsi()
|
|||
vlr_subscr_put(vsub, __func__);
|
||||
}
|
||||
|
||||
static void lu_geran_noauth()
|
||||
{
|
||||
rx_from_ran = OSMO_RAT_GERAN_A;
|
||||
net->authentication_required = false;
|
||||
net->vlr->cfg.assign_tmsi = false;
|
||||
|
||||
btw("Location Update request causes a GSUP LU request to HLR");
|
||||
lu_result_sent = RES_NONE;
|
||||
gsup_expect_tx("04010809710000000156f0280102" VLR_TO_HLR);
|
||||
ms_sends_msg("0508" /* MM LU */
|
||||
"7" /* ciph key seq: no key available */
|
||||
"0" /* LU type: normal */
|
||||
"09f107" "0017" /* LAI, LAC */
|
||||
"57" /* classmark 1: R99, early classmark, no power lvl */
|
||||
"089910070000106005" /* IMSI */
|
||||
"3303575886" /* classmark 2 */
|
||||
);
|
||||
OSMO_ASSERT(gsup_tx_confirmed);
|
||||
VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
|
||||
|
||||
btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
|
||||
gsup_rx("10010809710000000156f00804036470f1" HLR_TO_VLR,
|
||||
"12010809710000000156f0" VLR_TO_HLR);
|
||||
VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
|
||||
|
||||
btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
|
||||
expect_bssap_clear();
|
||||
gsup_rx("06010809710000000156f0" HLR_TO_VLR, NULL);
|
||||
|
||||
btw("LU was successful, and the conn has already been closed");
|
||||
VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
|
||||
VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
|
||||
|
||||
ran_sends_clear_complete();
|
||||
EXPECT_CONN_COUNT(0);
|
||||
}
|
||||
|
||||
|
||||
static void test_call_mo()
|
||||
{
|
||||
struct gsm_mncc mncc = {
|
||||
|
@ -232,7 +271,7 @@ static void test_call_mo()
|
|||
|
||||
btw("Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC");
|
||||
cc_to_mncc_expect_tx("", MNCC_RTP_CREATE);
|
||||
ms_sends_assignment_complete(CODEC_AMR_8000_1);
|
||||
ms_sends_assignment_complete("AMR");
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
|
||||
btw("MNCC says that's fine");
|
||||
|
@ -359,7 +398,7 @@ static void test_call_mt()
|
|||
|
||||
btw("Assignment completes, triggering CRCX to CN");
|
||||
expect_crcx(RTP_TO_CN);
|
||||
ms_sends_assignment_complete(CODEC_AMR_8000_1);
|
||||
ms_sends_assignment_complete("AMR");
|
||||
|
||||
btw("MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP");
|
||||
mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc);
|
||||
|
@ -481,7 +520,7 @@ static void test_call_mt2()
|
|||
OSMO_ASSERT(iu_rab_assignment_sent);
|
||||
|
||||
btw("Assignment completes, triggering CRCX to CN");
|
||||
ms_sends_assignment_complete(CODEC_AMR_8000_1);
|
||||
ms_sends_assignment_complete("AMR");
|
||||
|
||||
btw("When the CN side RTP address is known, ack MNCC_RTP_CREATE with full SDP");
|
||||
cc_to_mncc_expect_tx("", MNCC_RTP_CREATE);
|
||||
|
@ -584,7 +623,7 @@ static void test_call_mo_to_unknown()
|
|||
|
||||
btw("Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC");
|
||||
cc_to_mncc_expect_tx("", MNCC_RTP_CREATE);
|
||||
ms_sends_assignment_complete(CODEC_AMR_8000_1);
|
||||
ms_sends_assignment_complete("AMR");
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
|
||||
btw("MNCC says that's fine");
|
||||
|
@ -680,7 +719,7 @@ static void test_call_mo_to_unknown_timeout()
|
|||
|
||||
btw("Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC");
|
||||
cc_to_mncc_expect_tx("", MNCC_RTP_CREATE);
|
||||
ms_sends_assignment_complete(CODEC_AMR_8000_1);
|
||||
ms_sends_assignment_complete("AMR");
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
|
||||
btw("MNCC says that's fine");
|
||||
|
@ -709,6 +748,694 @@ static void test_call_mo_to_unknown_timeout()
|
|||
comment_end();
|
||||
}
|
||||
|
||||
#define LIST_END 0xffff
|
||||
|
||||
struct codec_test {
|
||||
const char *desc;
|
||||
|
||||
/* What to send during Complete Layer 3 as Codec List (BSS Supported). List ends with a LIST_END entry */
|
||||
enum gsm0808_speech_codec_type mo_rx_compl_l3_codec_list_bss_supported[8];
|
||||
|
||||
/* What to send during CC Setup as MS Bearer Capability. List ends with a LIST_END entry */
|
||||
enum gsm48_bcap_speech_ver mo_rx_ms_bcap[8];
|
||||
|
||||
/* What codecs should osmo-msc send in the MNCC_SETUP_IND message.
|
||||
* Just the SDP subtype names like "GSM", "GSM-EFR", "AMR", ..., list ends with NULL entry */
|
||||
const char *mo_tx_sdp_mncc_setup_ind[8];
|
||||
|
||||
/* What codecs the remote call leg should send as SDP via MNCC during MNCC_RTP_CREATE (if any). */
|
||||
const char *mo_rx_sdp_mncc_rtp_create[8];
|
||||
|
||||
/* What the MSC should send as Channel Type IE in the Assignment Command to the BSS. List ends with a
|
||||
* LIST_END entry */
|
||||
enum gsm0808_permitted_speech mo_tx_assignment_perm_speech[8];
|
||||
|
||||
/* What codec to assign in the Assignment Complete's Codec (Chosen) IE. Just a subtype name. */
|
||||
const char *mo_rx_assigned_codec;
|
||||
|
||||
/* MO acks the MNCC_RTP_CREATE with these codecs (if any). */
|
||||
const char *mo_tx_sdp_mncc_rtp_create[8];
|
||||
|
||||
/* mt_rx_sdp_mncc_setup_req == mo_tx_sdp_mncc_rtp_create */
|
||||
#define mt_rx_sdp_mncc_setup_req mo_tx_sdp_mncc_rtp_create
|
||||
|
||||
enum gsm0808_speech_codec_type mt_rx_compl_l3_codec_list_bss_supported[8];
|
||||
bool expect_codec_mismatch_on_paging_response;
|
||||
enum gsm48_bcap_speech_ver mt_tx_cc_setup_bcap[8];
|
||||
enum gsm48_bcap_speech_ver mt_rx_ms_bcap[8];
|
||||
bool expect_codec_mismatch_on_cc_call_conf;
|
||||
const char *mt_tx_sdp_mncc_call_conf_ind[8];
|
||||
|
||||
enum gsm0808_permitted_speech mt_tx_assignment_perm_speech[8];
|
||||
const char *mt_rx_assigned_codec;
|
||||
|
||||
const char *mt_rx_sdp_mncc_rtp_create[8];
|
||||
const char *mt_tx_sdp_mncc_rtp_create[8];
|
||||
|
||||
const char *mt_tx_sdp_mncc_alert_ind[8];
|
||||
const char *mt_tx_sdp_mncc_setup_cnf[8];
|
||||
const char *mt_rx_sdp_mncc_setup_compl_req[8];
|
||||
|
||||
/* mo_rx_sdp_mncc_alert_req == mt_tx_sdp_mncc_alert_ind */
|
||||
#define mo_rx_sdp_mncc_alert_req mt_tx_sdp_mncc_alert_ind
|
||||
#define mo_rx_sdp_mncc_setup_rsp mt_tx_sdp_mncc_alert_ind
|
||||
|
||||
const char *mo_tx_sdp_mncc_setup_compl_ind[8];
|
||||
};
|
||||
|
||||
#define CODEC_LIST_ALL_GSM { \
|
||||
GSM0808_SCT_FR1, \
|
||||
GSM0808_SCT_FR2, \
|
||||
GSM0808_SCT_FR3, \
|
||||
GSM0808_SCT_HR1, \
|
||||
GSM0808_SCT_HR3, \
|
||||
LIST_END \
|
||||
}
|
||||
|
||||
#define BCAP_ALL_GSM { \
|
||||
GSM48_BCAP_SV_AMR_F, \
|
||||
GSM48_BCAP_SV_AMR_H, \
|
||||
GSM48_BCAP_SV_AMR_OH, \
|
||||
GSM48_BCAP_SV_EFR, \
|
||||
GSM48_BCAP_SV_FR, \
|
||||
GSM48_BCAP_SV_HR, \
|
||||
LIST_END \
|
||||
}
|
||||
|
||||
#define PERM_SPEECH_ALL_GSM { \
|
||||
GSM0808_PERM_FR3, \
|
||||
GSM0808_PERM_HR3, \
|
||||
GSM0808_PERM_FR2, \
|
||||
GSM0808_PERM_FR1, \
|
||||
GSM0808_PERM_HR1, \
|
||||
LIST_END \
|
||||
}
|
||||
|
||||
#define SDP_CODECS_ALL_GSM { \
|
||||
"AMR", \
|
||||
"GSM-EFR", \
|
||||
"GSM", \
|
||||
"GSM-HR-08", \
|
||||
}
|
||||
|
||||
static const struct codec_test codec_tests[] = {
|
||||
{
|
||||
.desc = "AMR picked by both MO and MT",
|
||||
.mo_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM,
|
||||
.mo_rx_ms_bcap = BCAP_ALL_GSM,
|
||||
.mo_tx_sdp_mncc_setup_ind = SDP_CODECS_ALL_GSM,
|
||||
.mo_rx_sdp_mncc_rtp_create = {},
|
||||
.mo_tx_assignment_perm_speech = PERM_SPEECH_ALL_GSM,
|
||||
.mo_rx_assigned_codec = "AMR",
|
||||
.mo_tx_sdp_mncc_rtp_create = { "AMR" },
|
||||
/* mt_rx_sdp_mncc_setup_req == mo_tx_sdp_mncc_rtp_create */
|
||||
.mt_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM,
|
||||
.mt_tx_cc_setup_bcap = {
|
||||
GSM48_BCAP_SV_AMR_F,
|
||||
GSM48_BCAP_SV_AMR_H,
|
||||
GSM48_BCAP_SV_AMR_OH,
|
||||
LIST_END
|
||||
},
|
||||
.mt_rx_ms_bcap = BCAP_ALL_GSM,
|
||||
.mt_tx_sdp_mncc_call_conf_ind = {},
|
||||
.mt_rx_sdp_mncc_rtp_create = {},
|
||||
.mt_tx_assignment_perm_speech = { GSM0808_PERM_FR3, GSM0808_PERM_HR3, LIST_END },
|
||||
.mt_rx_assigned_codec = "AMR",
|
||||
.mt_tx_sdp_mncc_rtp_create = { "AMR" },
|
||||
.mt_tx_sdp_mncc_alert_ind = { "AMR" },
|
||||
.mt_tx_sdp_mncc_setup_cnf = { "AMR" },
|
||||
.mo_tx_sdp_mncc_setup_compl_ind = {},
|
||||
},
|
||||
|
||||
{
|
||||
.desc = "FR1 picked by MO from Codec List (BSS Supported), MT hence also picks FR1",
|
||||
.mo_rx_compl_l3_codec_list_bss_supported = { GSM0808_SCT_FR1, LIST_END },
|
||||
.mo_rx_ms_bcap = BCAP_ALL_GSM,
|
||||
.mo_tx_sdp_mncc_setup_ind = { "GSM" },
|
||||
.mo_rx_sdp_mncc_rtp_create = {},
|
||||
.mo_tx_assignment_perm_speech = { GSM0808_PERM_FR1, LIST_END },
|
||||
.mo_rx_assigned_codec = "GSM",
|
||||
.mo_tx_sdp_mncc_rtp_create = { "GSM" },
|
||||
/* .mt_rx_sdp_mncc_setup_req == .mo_tx_sdp_mncc_setup_ind */
|
||||
.mt_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM,
|
||||
.mt_tx_cc_setup_bcap = { GSM48_BCAP_SV_FR, LIST_END },
|
||||
.mt_rx_ms_bcap = BCAP_ALL_GSM,
|
||||
.mt_tx_sdp_mncc_call_conf_ind = {},
|
||||
.mt_rx_sdp_mncc_rtp_create = {},
|
||||
.mt_tx_assignment_perm_speech = { GSM0808_PERM_FR1, LIST_END },
|
||||
.mt_rx_assigned_codec = "GSM",
|
||||
.mt_tx_sdp_mncc_rtp_create = { "GSM" },
|
||||
.mt_tx_sdp_mncc_alert_ind = { "GSM" },
|
||||
.mt_tx_sdp_mncc_setup_cnf = { "GSM" },
|
||||
.mo_tx_sdp_mncc_setup_compl_ind = {},
|
||||
},
|
||||
|
||||
{
|
||||
.desc = "FR1 picked by MO from Bearer Cap, MT hence also picks FR1",
|
||||
.mo_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM,
|
||||
.mo_rx_ms_bcap = { GSM48_BCAP_SV_FR, LIST_END },
|
||||
.mo_tx_sdp_mncc_setup_ind = { "GSM" },
|
||||
.mo_rx_sdp_mncc_rtp_create = {},
|
||||
.mo_tx_assignment_perm_speech = { GSM0808_PERM_FR1, LIST_END },
|
||||
.mo_rx_assigned_codec = "GSM",
|
||||
.mo_tx_sdp_mncc_rtp_create = { "GSM" },
|
||||
/* .mt_rx_sdp_mncc_setup_req == .mo_tx_sdp_mncc_setup_ind */
|
||||
.mt_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM,
|
||||
.mt_tx_cc_setup_bcap = { GSM48_BCAP_SV_FR, LIST_END },
|
||||
.mt_rx_ms_bcap = BCAP_ALL_GSM,
|
||||
.mt_tx_sdp_mncc_call_conf_ind = {},
|
||||
.mt_rx_sdp_mncc_rtp_create = {},
|
||||
.mt_tx_assignment_perm_speech = { GSM0808_PERM_FR1, LIST_END },
|
||||
.mt_rx_assigned_codec = "GSM",
|
||||
.mt_tx_sdp_mncc_rtp_create = { "GSM" },
|
||||
.mt_tx_sdp_mncc_alert_ind = { "GSM" },
|
||||
.mt_tx_sdp_mncc_setup_cnf = { "GSM" },
|
||||
.mo_tx_sdp_mncc_setup_compl_ind = {},
|
||||
},
|
||||
|
||||
{
|
||||
.desc = "FR1 picked by MT's Codec List (BSS Supported), hence MO also picks FR1 (EXPECTED FAILURE)",
|
||||
/* Currently the MO Assignment happens before MT gets a chance to send its available codecs.
|
||||
* So even though the MO side would be able to assign FR1 and match MT, this is established too late
|
||||
* and MO mismatches MT. This can only be fixed by a) moving MO Assignment to after MT Assignment
|
||||
* or b) doing a Channel Mode Change or re-assignment after MT Assignment -- since re-assigning might
|
||||
* need an lchan type change and means more overhead, a) would be the best option. */
|
||||
.mo_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM,
|
||||
.mo_rx_ms_bcap = BCAP_ALL_GSM,
|
||||
.mo_tx_sdp_mncc_setup_ind = SDP_CODECS_ALL_GSM,
|
||||
.mo_rx_sdp_mncc_rtp_create = {},
|
||||
.mo_tx_assignment_perm_speech = PERM_SPEECH_ALL_GSM,
|
||||
.mo_rx_assigned_codec = "AMR", /* <- Early Assignment means codec mismatch */
|
||||
.mo_tx_sdp_mncc_rtp_create = { "AMR" },
|
||||
|
||||
.mt_rx_compl_l3_codec_list_bss_supported = { GSM0808_SCT_FR1, LIST_END },
|
||||
.expect_codec_mismatch_on_paging_response = true,
|
||||
/* The mismatching codec AMR vs. GSM means the call fails (in the lack of transcoding) */
|
||||
},
|
||||
|
||||
{
|
||||
.desc = "FR1 picked by MT's MS Bearer Capability, hence MO also picks FR1 (EXPECTED FAILURE)",
|
||||
/* Like above, MO Assignment happens too early to be able to match MT's codec availability. */
|
||||
.mo_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM,
|
||||
.mo_rx_ms_bcap = BCAP_ALL_GSM,
|
||||
.mo_tx_sdp_mncc_setup_ind = SDP_CODECS_ALL_GSM,
|
||||
.mo_rx_sdp_mncc_rtp_create = {},
|
||||
.mo_tx_assignment_perm_speech = PERM_SPEECH_ALL_GSM,
|
||||
.mo_rx_assigned_codec = "AMR", /* <- Early Assignment means codec mismatch */
|
||||
.mo_tx_sdp_mncc_rtp_create = { "AMR" },
|
||||
|
||||
.mt_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM,
|
||||
.mt_tx_cc_setup_bcap = {
|
||||
GSM48_BCAP_SV_AMR_F,
|
||||
GSM48_BCAP_SV_AMR_H,
|
||||
GSM48_BCAP_SV_AMR_OH,
|
||||
LIST_END
|
||||
},
|
||||
.mt_rx_ms_bcap = { GSM48_BCAP_SV_FR, LIST_END },
|
||||
.mt_tx_sdp_mncc_call_conf_ind = {},
|
||||
.mt_rx_sdp_mncc_rtp_create = {},
|
||||
.mt_tx_assignment_perm_speech = { GSM0808_PERM_FR3, GSM0808_PERM_HR3, LIST_END },
|
||||
.expect_codec_mismatch_on_cc_call_conf = true,
|
||||
/* The mismatching codec AMR vs. GSM means the call fails (in the lack of transcoding) */
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static char namebuf[4][1024];
|
||||
static int use_namebuf = 0;
|
||||
|
||||
static const char *codec_list_name(const enum gsm0808_speech_codec_type compl_l3_codec_list_bss_supported[])
|
||||
{
|
||||
struct osmo_strbuf sb = { .buf = namebuf[use_namebuf], .len = sizeof(namebuf[0]) };
|
||||
use_namebuf = (use_namebuf + 1) % ARRAY_SIZE(namebuf);
|
||||
|
||||
const enum gsm0808_speech_codec_type *pos;
|
||||
sb.buf[0] = '\0';
|
||||
for (pos = compl_l3_codec_list_bss_supported; *pos != LIST_END; pos++)
|
||||
OSMO_STRBUF_PRINTF(sb, " %s", gsm0808_speech_codec_type_name(*pos));
|
||||
return sb.buf;
|
||||
}
|
||||
|
||||
static const struct gsm0808_speech_codec_list *codec_list(const enum gsm0808_speech_codec_type compl_l3_codec_list_bss_supported[])
|
||||
{
|
||||
static struct gsm0808_speech_codec_list scl;
|
||||
scl = (struct gsm0808_speech_codec_list){};
|
||||
const enum gsm0808_speech_codec_type *pos;
|
||||
for (pos = compl_l3_codec_list_bss_supported; *pos != LIST_END; pos++) {
|
||||
scl.codec[scl.len] = (struct gsm0808_speech_codec){
|
||||
.fi = true,
|
||||
.type = *pos,
|
||||
};
|
||||
scl.len++;
|
||||
}
|
||||
return &scl;
|
||||
}
|
||||
|
||||
static const char *bcap_name(const enum gsm48_bcap_speech_ver ms_bcap[])
|
||||
{
|
||||
struct osmo_strbuf sb = { .buf = namebuf[use_namebuf], .len = sizeof(namebuf[0]) };
|
||||
use_namebuf = (use_namebuf + 1) % ARRAY_SIZE(namebuf);
|
||||
|
||||
const enum gsm48_bcap_speech_ver *pos;
|
||||
sb.buf[0] = '\0';
|
||||
for (pos = ms_bcap; *pos != LIST_END; pos++) {
|
||||
const struct codec_mapping *m = codec_mapping_by_speech_ver(*pos);
|
||||
OSMO_STRBUF_PRINTF(sb, " %s", m? m->sdp.subtype_name : "NULL");
|
||||
}
|
||||
return sb.buf;
|
||||
}
|
||||
|
||||
static const char *perm_speech_name(const enum gsm0808_permitted_speech perm_speech[])
|
||||
{
|
||||
struct osmo_strbuf sb = { .buf = namebuf[use_namebuf], .len = sizeof(namebuf[0]) };
|
||||
use_namebuf = (use_namebuf + 1) % ARRAY_SIZE(namebuf);
|
||||
|
||||
const enum gsm0808_permitted_speech *pos;
|
||||
sb.buf[0] = '\0';
|
||||
for (pos = perm_speech; *pos != LIST_END; pos++) {
|
||||
OSMO_STRBUF_PRINTF(sb, " %s", gsm0808_permitted_speech_name(*pos));
|
||||
}
|
||||
return sb.buf;
|
||||
}
|
||||
|
||||
static const char *strlist_name(const char *const* strs)
|
||||
{
|
||||
struct osmo_strbuf sb = { .buf = namebuf[use_namebuf], .len = sizeof(namebuf[0]) };
|
||||
use_namebuf = (use_namebuf + 1) % ARRAY_SIZE(namebuf);
|
||||
|
||||
const char * const *pos;
|
||||
sb.buf[0] = '\0';
|
||||
for (pos = strs; *pos != NULL; pos++)
|
||||
OSMO_STRBUF_PRINTF(sb, " %s", *pos);
|
||||
return sb.buf;
|
||||
}
|
||||
|
||||
static bool validate_sdp(const char *func, const char *desc,
|
||||
const char *sdp_str, const char * const expected_codecs[])
|
||||
{
|
||||
const char * const *expect_pos;
|
||||
struct sdp_audio_codec *codec;
|
||||
struct sdp_msg sdp;
|
||||
if (sdp_msg_from_sdp_str(&sdp, sdp_str)) {
|
||||
BTW("%s: %s: ERROR: failed to parse SDP\n%s", func, desc, sdp_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
expect_pos = expected_codecs;
|
||||
foreach_sdp_audio_codec(codec, &sdp.audio_codecs) {
|
||||
if (!*expect_pos) {
|
||||
BTW("%s: %s: ERROR: did not expect %s", func, desc, codec->subtype_name);
|
||||
return false;
|
||||
}
|
||||
if (strcmp(*expect_pos, codec->subtype_name)) {
|
||||
BTW("%s: %s: ERROR: mismatch: in idx %d, expect %s, got %s", func, desc,
|
||||
(int)(expect_pos - expected_codecs), *expect_pos, codec->subtype_name);
|
||||
return false;
|
||||
}
|
||||
expect_pos++;
|
||||
}
|
||||
if (*expect_pos) {
|
||||
BTW("%s: %s: ERROR: mismatch: expected %s to be listed, but not found", func, desc, *expect_pos);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define VALIDATE_SDP(GOT_SDP_STR, EXPECT_SDP_STR) do { \
|
||||
if (validate_sdp(__func__, t->desc, GOT_SDP_STR, EXPECT_SDP_STR)) { \
|
||||
btw("VALIDATE_SDP OK: " #GOT_SDP_STR " == " #EXPECT_SDP_STR " ==%s", strlist_name(EXPECT_SDP_STR)); \
|
||||
} else { \
|
||||
btw("Failed to validate SDP:\nexpected%s\ngot\n%s", \
|
||||
strlist_name(EXPECT_SDP_STR), GOT_SDP_STR); \
|
||||
OSMO_ASSERT(false); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static bool validate_perm_speech(const char *func, const char *desc,
|
||||
const struct gsm0808_channel_type *ct,
|
||||
const enum gsm0808_permitted_speech perm_speech[])
|
||||
{
|
||||
const enum gsm0808_permitted_speech *pos;
|
||||
const uint8_t *pos2 = ct->perm_spch;
|
||||
for (pos = perm_speech; *pos != LIST_END; pos++, pos2++) {
|
||||
if (pos2 - ct->perm_spch >= ct->perm_spch_len) {
|
||||
BTW("%s: %s: ERROR: mismatch: expected %s to be listed, but not found", func, desc,
|
||||
gsm0808_permitted_speech_name(*pos));
|
||||
return false;
|
||||
}
|
||||
if (*pos2 != *pos) {
|
||||
BTW("%s: %s: ERROR: mismatch: in idx %d, expect %s", func, desc,
|
||||
(int)(pos - perm_speech), gsm0808_permitted_speech_name(*pos));
|
||||
btw("in idx %d, got %s", (int)(pos - perm_speech), gsm0808_permitted_speech_name(*pos2));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (pos2 - ct->perm_spch < ct->perm_spch_len) {
|
||||
BTW("%s: %s: ERROR: did not expect %s", func, desc, gsm0808_permitted_speech_name(*pos2));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define VALIDATE_PERM_SPEECH(GOT_PERM_SPEECH, EXPECT_PERM_SPEECH) do { \
|
||||
if (validate_perm_speech(__func__, t->desc, GOT_PERM_SPEECH, EXPECT_PERM_SPEECH)) { \
|
||||
btw("VALIDATE_PERM_SPEECH OK: " #GOT_PERM_SPEECH " == " #EXPECT_PERM_SPEECH " ==%s", \
|
||||
perm_speech_name(EXPECT_PERM_SPEECH)); \
|
||||
} else { \
|
||||
btw("Failed to validate Permitted Speech:\nexpected%s", \
|
||||
perm_speech_name(EXPECT_PERM_SPEECH)); \
|
||||
btw("got:"); \
|
||||
int i; \
|
||||
for (i = 0; i < (GOT_PERM_SPEECH)->perm_spch_len; i++) { \
|
||||
btw("%s", gsm0808_permitted_speech_name((GOT_PERM_SPEECH)->perm_spch[i])); \
|
||||
}\
|
||||
OSMO_ASSERT(false); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static struct sdp_msg *sdp_from_subtype_names(const char *const *subtype_names)
|
||||
{
|
||||
static struct sdp_msg sdp;
|
||||
sdp = (struct sdp_msg){};
|
||||
const char *const *subtype_name;
|
||||
osmo_sockaddr_str_from_str(&sdp.rtp, "1.2.3.4", 56);
|
||||
for (subtype_name = subtype_names; *subtype_name; subtype_name++) {
|
||||
const struct codec_mapping *m = codec_mapping_by_subtype_name(*subtype_name);
|
||||
if (!m) {
|
||||
BTW("ERROR: unknown subtype_name: %s", *subtype_name);
|
||||
abort();
|
||||
}
|
||||
sdp_audio_codecs_add_copy(&sdp.audio_codecs, &m->sdp);
|
||||
}
|
||||
return &sdp;
|
||||
}
|
||||
|
||||
static int sdp_str_from_subtype_names(char *buf, size_t buflen, const char *const *subtype_names)
|
||||
{
|
||||
if (!subtype_names[0]) {
|
||||
buf[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
return sdp_msg_to_sdp_str_buf(buf, buflen, sdp_from_subtype_names(subtype_names));
|
||||
}
|
||||
|
||||
static const char *bcap_hexstr(const enum gsm48_bcap_speech_ver ms_bcap[])
|
||||
{
|
||||
struct gsm_mncc_bearer_cap bcap = {
|
||||
.transfer = GSM_MNCC_BCAP_SPEECH,
|
||||
.speech_ver = { -1 },
|
||||
.radio = GSM48_BCAP_RRQ_DUAL_FR,
|
||||
};
|
||||
const enum gsm48_bcap_speech_ver *pos;
|
||||
for (pos = ms_bcap; *pos != LIST_END; pos++) {
|
||||
bearer_cap_add_speech_ver(&bcap, *pos);
|
||||
}
|
||||
struct msgb *msg = msgb_alloc(128, "bcap");
|
||||
gsm48_encode_bearer_cap(msg, 0, &bcap);
|
||||
char *ret = osmo_hexdump_nospc(msg->data, msg->len);
|
||||
msgb_free(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void test_codecs_mo(const struct codec_test *t)
|
||||
{
|
||||
struct gsm_mncc mncc = {
|
||||
.imsi = IMSI,
|
||||
};
|
||||
|
||||
struct gsm_mncc_rtp *mncc_rtp = (void*)&mncc;
|
||||
|
||||
BTW("======================== MO call: %s", t->desc);
|
||||
btw("CM Service Request with Codec List (BSS Supported) =%s",
|
||||
codec_list_name(t->mo_rx_compl_l3_codec_list_bss_supported));
|
||||
|
||||
cm_service_result_sent = RES_NONE;
|
||||
ms_sends_compl_l3("052471"
|
||||
"03575886" /* classmark 2 */
|
||||
"089910070000106005" /* IMSI */,
|
||||
codec_list(t->mo_rx_compl_l3_codec_list_bss_supported));
|
||||
VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d");
|
||||
EXPECT_ACCEPTED(true);
|
||||
|
||||
btw("MS sends CC SETUP with Bearer Capability = %s",
|
||||
bcap_name(t->mo_rx_ms_bcap));
|
||||
expect_crcx(RTP_TO_CN);
|
||||
expect_crcx(RTP_TO_RAN);
|
||||
ms_sends_msgf("0385" /* CC, seq = 2 -> 0x80 | CC Setup = 0x5 */
|
||||
"%s" /* Bearer Capability */
|
||||
"5e038121f3" /* Called Number BCD */
|
||||
"15020100" /* CC Capabilities */
|
||||
"4008" /* Supported Codec List */
|
||||
"04026000" /* UMTS: AMR 2 | AMR */
|
||||
"00021f00" /* GSM: HR AMR | FR AMR | GSM EFR | GSM HR | GSM FR */,
|
||||
bcap_hexstr(t->mo_rx_ms_bcap)
|
||||
);
|
||||
OSMO_ASSERT(crcx_scheduled(RTP_TO_CN));
|
||||
OSMO_ASSERT(crcx_scheduled(RTP_TO_RAN));
|
||||
|
||||
btw("As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered");
|
||||
cc_to_mncc_expect_tx(IMSI, MNCC_SETUP_IND);
|
||||
crcx_ok(RTP_TO_CN);
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
mncc.callref = cc_to_mncc_tx_got_callref;
|
||||
VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mo_tx_sdp_mncc_setup_ind);
|
||||
|
||||
btw("MNCC replies with MNCC_RTP_CREATE, causing MGW endpoint CRCX to RAN");
|
||||
sdp_str_from_subtype_names(mncc_rtp->sdp, sizeof(mncc_rtp->sdp), t->mo_rx_sdp_mncc_rtp_create);
|
||||
mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc);
|
||||
|
||||
btw("MGW acknowledges the CRCX, triggering Assignment with%s", perm_speech_name(t->mo_tx_assignment_perm_speech));
|
||||
expect_bssap_assignment();
|
||||
crcx_ok(RTP_TO_RAN);
|
||||
OSMO_ASSERT(bssap_assignment_sent);
|
||||
VALIDATE_PERM_SPEECH(&bssap_assignment_command_last_channel_type, t->mo_tx_assignment_perm_speech);
|
||||
|
||||
btw("Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC");
|
||||
cc_to_mncc_expect_tx("", MNCC_RTP_CREATE);
|
||||
ms_sends_assignment_complete(t->mo_rx_assigned_codec);
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mo_tx_sdp_mncc_rtp_create);
|
||||
|
||||
btw("MNCC says that's fine");
|
||||
dtap_expect_tx("8302" /* CC: Call Proceeding */);
|
||||
mncc_sends_to_cc(MNCC_CALL_PROC_REQ, &mncc);
|
||||
OSMO_ASSERT(dtap_tx_confirmed);
|
||||
|
||||
fake_time_passes(1, 23);
|
||||
|
||||
btw("The other call leg got established (not shown here), MNCC tells us so, with codecs %s",
|
||||
strlist_name(t->mo_rx_sdp_mncc_alert_req));
|
||||
dtap_expect_tx("8301" /* CC: Call Alerting */);
|
||||
sdp_str_from_subtype_names(mncc.sdp, sizeof(mncc.sdp), t->mo_rx_sdp_mncc_alert_req);
|
||||
mncc_sends_to_cc(MNCC_ALERT_REQ, &mncc);
|
||||
OSMO_ASSERT(dtap_tx_confirmed);
|
||||
|
||||
dtap_expect_tx("8307" /* CC: Connect */);
|
||||
sdp_str_from_subtype_names(mncc.sdp, sizeof(mncc.sdp), t->mo_rx_sdp_mncc_setup_rsp);
|
||||
mncc_sends_to_cc(MNCC_SETUP_RSP, &mncc);
|
||||
OSMO_ASSERT(dtap_tx_confirmed);
|
||||
|
||||
fake_time_passes(1, 23);
|
||||
|
||||
cc_to_mncc_expect_tx("", MNCC_SETUP_COMPL_IND);
|
||||
ms_sends_msg("03cf" /* CC: Connect Acknowledge */);
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mo_tx_sdp_mncc_setup_compl_ind);
|
||||
|
||||
BTW("RTP stream goes ahead, not shown here.");
|
||||
fake_time_passes(123, 45);
|
||||
|
||||
BTW("Call ends");
|
||||
cc_to_mncc_expect_tx("", MNCC_DISC_IND);
|
||||
ms_sends_msg("032502e090" /* CC: Disconnect, cause: Normal Call Clearing */);
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
|
||||
dtap_expect_tx("832d" /* CC: Release */);
|
||||
mncc_sends_to_cc(MNCC_REL_REQ, &mncc);
|
||||
OSMO_ASSERT(dtap_tx_confirmed);
|
||||
|
||||
cc_to_mncc_expect_tx("", MNCC_REL_CNF);
|
||||
expect_bssap_clear();
|
||||
ms_sends_msg("036a" /* CC: Release Complete */);
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
OSMO_ASSERT(bssap_clear_sent);
|
||||
|
||||
ran_sends_clear_complete();
|
||||
EXPECT_CONN_COUNT(0);
|
||||
BTW("======================== SUCCESS: MO call: %s", t->desc);
|
||||
}
|
||||
|
||||
static void test_codecs_mt(const struct codec_test *t)
|
||||
{
|
||||
struct gsm_mncc mncc = {
|
||||
.imsi = IMSI,
|
||||
.callref = 0x423,
|
||||
.fields = MNCC_F_BEARER_CAP,
|
||||
.bearer_cap = {
|
||||
.speech_ver = { GSM48_BCAP_SV_FR, -1, },
|
||||
},
|
||||
};
|
||||
struct gsm_mncc_rtp *mncc_rtp = (void*)&mncc;
|
||||
|
||||
BTW("======================== MT call: %s", t->desc);
|
||||
|
||||
BTW("MNCC asks us to setup a call, causing Paging");
|
||||
|
||||
paging_expect_imsi(IMSI);
|
||||
paging_sent = false;
|
||||
sdp_str_from_subtype_names(mncc.sdp, sizeof(mncc.sdp), t->mt_rx_sdp_mncc_setup_req);
|
||||
mncc_sends_to_cc(MNCC_SETUP_REQ, &mncc);
|
||||
mncc.sdp[0] = '\0';
|
||||
|
||||
VERBOSE_ASSERT(paging_sent, == true, "%d");
|
||||
|
||||
btw("MS replies with Paging Response, with Codec List (BSS Supported) =%s",
|
||||
codec_list_name(t->mt_rx_compl_l3_codec_list_bss_supported));
|
||||
|
||||
if (t->expect_codec_mismatch_on_paging_response) {
|
||||
btw("VLR accepts, but MSC notices a codec mismatch and aborts");
|
||||
cc_to_mncc_expect_tx("", MNCC_REL_IND);
|
||||
dtap_expect_tx("032d0802e1af" /* CC Release */);
|
||||
expect_bssap_clear();
|
||||
ms_sends_compl_l3("062707"
|
||||
"03575886" /* classmark 2 */
|
||||
"089910070000106005" /* IMSI */,
|
||||
codec_list(t->mt_rx_compl_l3_codec_list_bss_supported));
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
OSMO_ASSERT(bssap_clear_sent);
|
||||
|
||||
ran_sends_clear_complete();
|
||||
EXPECT_CONN_COUNT(0);
|
||||
|
||||
BTW("======================== SUCCESS: MT call: %s", t->desc);
|
||||
return;
|
||||
}
|
||||
|
||||
btw("VLR accepts, MSC sends CC Setup with Bearer Capability = %s",
|
||||
bcap_name(t->mt_tx_cc_setup_bcap));
|
||||
char *cc_setup_bcap = talloc_asprintf(msc_vlr_tests_ctx, "0305%s",
|
||||
bcap_hexstr(t->mt_tx_cc_setup_bcap));
|
||||
dtap_expect_tx(cc_setup_bcap);
|
||||
ms_sends_compl_l3("062707"
|
||||
"03575886" /* classmark 2 */
|
||||
"089910070000106005" /* IMSI */,
|
||||
codec_list(t->mt_rx_compl_l3_codec_list_bss_supported));
|
||||
OSMO_ASSERT(dtap_tx_confirmed);
|
||||
talloc_free(cc_setup_bcap);
|
||||
|
||||
btw("MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND");
|
||||
expect_crcx(RTP_TO_CN);
|
||||
expect_crcx(RTP_TO_RAN);
|
||||
cc_to_mncc_expect_tx(IMSI, MNCC_CALL_CONF_IND);
|
||||
ms_sends_msgf("8348" /* CC: Call Confirmed */
|
||||
"%s" /* Bearer Capability */
|
||||
"15020100" /* Call Control Capabilities */
|
||||
"40080402600400021f00" /* Supported Codec List */,
|
||||
bcap_hexstr(t->mt_rx_ms_bcap)
|
||||
);
|
||||
OSMO_ASSERT(crcx_scheduled(RTP_TO_CN));
|
||||
OSMO_ASSERT(crcx_scheduled(RTP_TO_RAN));
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mt_tx_sdp_mncc_call_conf_ind);
|
||||
|
||||
btw("MGW acknowledges the CRCX to RAN, triggering Assignment with%s", perm_speech_name(t->mt_tx_assignment_perm_speech));
|
||||
|
||||
if (t->expect_codec_mismatch_on_cc_call_conf) {
|
||||
btw("MS Bearer Capability leads to a codec mismatch, Assignment aborts");
|
||||
|
||||
dtap_expect_tx("032d0802e1af" /* CC Release */);
|
||||
cc_to_mncc_expect_tx("", MNCC_REL_IND);
|
||||
expect_bssap_clear();
|
||||
crcx_ok(RTP_TO_RAN);
|
||||
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
OSMO_ASSERT(bssap_clear_sent);
|
||||
|
||||
ran_sends_clear_complete();
|
||||
EXPECT_CONN_COUNT(0);
|
||||
BTW("======================== SUCCESS: MT call: %s", t->desc);
|
||||
return;
|
||||
}
|
||||
|
||||
expect_bssap_assignment();
|
||||
crcx_ok(RTP_TO_RAN);
|
||||
OSMO_ASSERT(bssap_assignment_sent);
|
||||
VALIDATE_PERM_SPEECH(&bssap_assignment_command_last_channel_type, t->mt_tx_assignment_perm_speech);
|
||||
|
||||
btw("Assignment completes, triggering CRCX to CN");
|
||||
ms_sends_assignment_complete(t->mt_rx_assigned_codec);
|
||||
|
||||
btw("MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP");
|
||||
sdp_str_from_subtype_names(mncc_rtp->sdp, sizeof(mncc_rtp->sdp), t->mt_rx_sdp_mncc_rtp_create);
|
||||
mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc);
|
||||
|
||||
btw("When the CN side RTP address is known, ack MNCC_RTP_CREATE");
|
||||
cc_to_mncc_expect_tx("", MNCC_RTP_CREATE);
|
||||
crcx_ok(RTP_TO_CN);
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mt_tx_sdp_mncc_rtp_create);
|
||||
|
||||
fake_time_passes(1, 23);
|
||||
|
||||
cc_to_mncc_expect_tx("", MNCC_ALERT_IND);
|
||||
ms_sends_msg("8381" /* CC: Alerting */);
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mt_tx_sdp_mncc_alert_ind);
|
||||
|
||||
fake_time_passes(1, 23);
|
||||
|
||||
cc_to_mncc_expect_tx(IMSI, MNCC_SETUP_CNF);
|
||||
ms_sends_msg("83c7" /* CC: Connect */);
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mt_tx_sdp_mncc_setup_cnf);
|
||||
|
||||
dtap_expect_tx("030f" /* CC: Connect Acknowledge */);
|
||||
sdp_str_from_subtype_names(mncc.sdp, sizeof(mncc.sdp), t->mt_rx_sdp_mncc_setup_compl_req);
|
||||
mncc_sends_to_cc(MNCC_SETUP_COMPL_REQ, &mncc);
|
||||
|
||||
BTW("RTP stream goes ahead, not shown here.");
|
||||
fake_time_passes(123, 45);
|
||||
|
||||
BTW("Call ends");
|
||||
cc_to_mncc_expect_tx("", MNCC_DISC_IND);
|
||||
ms_sends_msg("832502e090" /* CC: Disconnect, cause: Normal Call Clearing */);
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
|
||||
dtap_expect_tx("032d" /* CC: Release */);
|
||||
mncc_sends_to_cc(MNCC_REL_REQ, &mncc);
|
||||
OSMO_ASSERT(dtap_tx_confirmed);
|
||||
|
||||
cc_to_mncc_expect_tx("", MNCC_REL_CNF);
|
||||
expect_bssap_clear();
|
||||
ms_sends_msg("836a" /* CC: Release Complete */);
|
||||
OSMO_ASSERT(cc_to_mncc_tx_confirmed);
|
||||
OSMO_ASSERT(bssap_clear_sent);
|
||||
|
||||
ran_sends_clear_complete();
|
||||
EXPECT_CONN_COUNT(0);
|
||||
BTW("======================== SUCCESS: MT call: %s", t->desc);
|
||||
}
|
||||
|
||||
static void test_codecs()
|
||||
{
|
||||
const struct codec_test *t;
|
||||
clear_vlr();
|
||||
|
||||
comment_start();
|
||||
|
||||
fake_time_start();
|
||||
|
||||
lu_geran_noauth();
|
||||
|
||||
for (t = codec_tests; t - codec_tests < ARRAY_SIZE(codec_tests); t++) {
|
||||
test_codecs_mo(t);
|
||||
test_codecs_mt(t);
|
||||
}
|
||||
|
||||
EXPECT_CONN_COUNT(0);
|
||||
clear_vlr();
|
||||
comment_end();
|
||||
}
|
||||
|
||||
msc_vlr_test_func_t msc_vlr_tests[] = {
|
||||
test_call_mo,
|
||||
|
@ -716,5 +1443,6 @@ msc_vlr_test_func_t msc_vlr_tests[] = {
|
|||
test_call_mt2,
|
||||
test_call_mo_to_unknown,
|
||||
test_call_mo_to_unknown_timeout,
|
||||
test_codecs,
|
||||
NULL
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -77,6 +77,7 @@ bool bssap_clear_sent = false;
|
|||
|
||||
bool bssap_assignment_expected = false;
|
||||
bool bssap_assignment_sent = false;
|
||||
struct gsm0808_channel_type bssap_assignment_command_last_channel_type;
|
||||
bool iu_rab_assignment_expected = false;
|
||||
bool iu_rab_assignment_sent = false;
|
||||
|
||||
|
@ -84,6 +85,7 @@ uint32_t cc_to_mncc_tx_expected_msg_type = 0;
|
|||
const char *cc_to_mncc_tx_expected_imsi = NULL;
|
||||
bool cc_to_mncc_tx_confirmed = false;
|
||||
uint32_t cc_to_mncc_tx_got_callref = 0;
|
||||
char cc_to_mncc_tx_last_sdp[1024] = {};
|
||||
|
||||
bool expecting_crcx[2] = {};
|
||||
bool got_crcx[2] = {};
|
||||
|
@ -308,14 +310,18 @@ static int bssap_validate_cipher_mode_cmd(const struct ran_cipher_mode_command *
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void bssap_validate_assignment_cmd()
|
||||
static void bssap_validate_assignment_cmd(const struct ran_assignment_command *assignment_command)
|
||||
{
|
||||
OSMO_ASSERT(bssap_assignment_expected);
|
||||
bssap_assignment_expected = false;
|
||||
bssap_assignment_sent = true;
|
||||
if (assignment_command->channel_type)
|
||||
bssap_assignment_command_last_channel_type = *assignment_command->channel_type;
|
||||
else
|
||||
bssap_assignment_command_last_channel_type = (struct gsm0808_channel_type){};
|
||||
}
|
||||
|
||||
static void iucs_validate_assignment_cmd()
|
||||
static void iucs_validate_assignment_cmd(const struct ran_assignment_command *assignment_command)
|
||||
{
|
||||
OSMO_ASSERT(iu_rab_assignment_expected);
|
||||
iu_rab_assignment_expected = false;
|
||||
|
@ -375,10 +381,10 @@ struct msgb *dont_ran_encode(struct osmo_fsm_inst *caller_fi, const struct ran_m
|
|||
case RAN_MSG_ASSIGNMENT_COMMAND:
|
||||
switch (ran_type) {
|
||||
case OSMO_RAT_GERAN_A:
|
||||
bssap_validate_assignment_cmd();
|
||||
bssap_validate_assignment_cmd(&ran_enc_msg->assignment_command);
|
||||
break;
|
||||
case OSMO_RAT_UTRAN_IU:
|
||||
iucs_validate_assignment_cmd();
|
||||
iucs_validate_assignment_cmd(&ran_enc_msg->assignment_command);
|
||||
break;
|
||||
default:
|
||||
OSMO_ASSERT(false);
|
||||
|
@ -420,7 +426,7 @@ static int fake_msc_a_ran_dec(const struct ran_msg *ran_dec_msg)
|
|||
return msc_a_ran_decode_cb(g_msub->role[MSC_ROLE_A], &d, ran_dec_msg);
|
||||
}
|
||||
|
||||
void rx_from_ms(struct msgb *msg)
|
||||
void rx_from_ms(struct msgb *msg, const struct gsm0808_speech_codec_list *codec_list_bss_supported)
|
||||
{
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
struct ran_msg ran_dec_msg;
|
||||
|
@ -453,6 +459,7 @@ void rx_from_ms(struct msgb *msg)
|
|||
.compl_l3 = {
|
||||
.cell_id = &cell_id,
|
||||
.msg = msg,
|
||||
.codec_list_bss_supported = codec_list_bss_supported,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
|
@ -480,7 +487,30 @@ void ms_sends_msg(const char *hex)
|
|||
|
||||
msg = msgb_from_hex("ms_sends_msg", 1024, hex);
|
||||
msg->l1h = msg->l2h = msg->l3h = msg->data;
|
||||
rx_from_ms(msg);
|
||||
rx_from_ms(msg, NULL);
|
||||
msgb_free(msg);
|
||||
}
|
||||
|
||||
void ms_sends_msgf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *hex;
|
||||
|
||||
va_start(ap, fmt);
|
||||
hex = talloc_vasprintf(msc_vlr_tests_ctx, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
ms_sends_msg(hex);
|
||||
talloc_free(hex);
|
||||
}
|
||||
|
||||
void ms_sends_compl_l3(const char *hex, const struct gsm0808_speech_codec_list *codec_list_bss_supported)
|
||||
{
|
||||
struct msgb *msg;
|
||||
|
||||
msg = msgb_from_hex("ms_sends_msg", 1024, hex);
|
||||
msg->l1h = msg->l2h = msg->l3h = msg->data;
|
||||
rx_from_ms(msg, codec_list_bss_supported);
|
||||
msgb_free(msg);
|
||||
}
|
||||
|
||||
|
@ -723,8 +753,18 @@ struct gsm_mncc *on_call_release_mncc_sends_to_cc_data = NULL;
|
|||
int mncc_recv(struct gsm_network *net, struct msgb *msg)
|
||||
{
|
||||
struct gsm_mncc *mncc = (void*)msg->data;
|
||||
log("MSC --> MNCC: callref 0x%x: %s", mncc->callref,
|
||||
get_mncc_name(mncc->msg_type));
|
||||
if (mncc->msg_type == MNCC_RTP_CREATE) {
|
||||
struct gsm_mncc_rtp *rtp = (void*)msg->data;
|
||||
log("MSC --> MNCC: callref 0x%x: %s\n%s", rtp->callref,
|
||||
get_mncc_name(rtp->msg_type),
|
||||
rtp->sdp);
|
||||
OSMO_STRLCPY_ARRAY(cc_to_mncc_tx_last_sdp, rtp->sdp);
|
||||
} else {
|
||||
log("MSC --> MNCC: callref 0x%x: %s\n%s", mncc->callref,
|
||||
get_mncc_name(mncc->msg_type),
|
||||
mncc->sdp);
|
||||
OSMO_STRLCPY_ARRAY(cc_to_mncc_tx_last_sdp, mncc->sdp);
|
||||
}
|
||||
|
||||
if (mncc->msg_type == MNCC_REL_IND && on_call_release_mncc_sends_to_cc_data) {
|
||||
|
||||
|
@ -1009,9 +1049,12 @@ void ms_sends_security_mode_complete(uint8_t utran_encryption)
|
|||
g_msub = NULL;
|
||||
}
|
||||
|
||||
void ms_sends_assignment_complete(enum mgcp_codecs assigned_codec)
|
||||
void ms_sends_assignment_complete(const char *sdp_codec_name)
|
||||
{
|
||||
struct ran_msg ran_dec;
|
||||
const struct codec_mapping *m = codec_mapping_by_subtype_name(sdp_codec_name);
|
||||
OSMO_ASSERT(m);
|
||||
enum mgcp_codecs assigned_codec = m->mgcp;
|
||||
|
||||
ran_dec = (struct ran_msg){
|
||||
.msg_type = RAN_MSG_ASSIGNMENT_COMPLETE,
|
||||
|
|
|
@ -56,6 +56,8 @@ extern bool _log_lines;
|
|||
#define comment_start() fprintf(stderr, "===== %s\n", __func__);
|
||||
#define comment_end() fprintf(stderr, "===== %s: SUCCESS\n\n", __func__);
|
||||
|
||||
extern void *msc_vlr_tests_ctx;
|
||||
|
||||
extern struct msub *g_msub;
|
||||
extern struct gsm_network *net;
|
||||
extern void *msgb_ctx;
|
||||
|
@ -116,6 +118,7 @@ extern uint32_t cc_to_mncc_tx_expected_msg_type;
|
|||
extern const char *cc_to_mncc_tx_expected_imsi;
|
||||
extern bool cc_to_mncc_tx_confirmed;
|
||||
extern uint32_t cc_to_mncc_tx_got_callref;
|
||||
extern char cc_to_mncc_tx_last_sdp[1024];
|
||||
|
||||
extern struct gsm_mncc *on_call_release_mncc_sends_to_cc_data;
|
||||
|
||||
|
@ -148,6 +151,7 @@ static inline void expect_release_clear(enum osmo_rat_type via_ran)
|
|||
|
||||
extern bool bssap_assignment_expected;
|
||||
extern bool bssap_assignment_sent;
|
||||
extern struct gsm0808_channel_type bssap_assignment_command_last_channel_type;
|
||||
extern bool iu_rab_assignment_expected;
|
||||
extern bool iu_rab_assignment_sent;
|
||||
|
||||
|
@ -183,10 +187,12 @@ void paging_expect_imsi(const char *imsi);
|
|||
void paging_expect_tmsi(uint32_t tmsi);
|
||||
|
||||
void ms_sends_msg(const char *hex);
|
||||
void ms_sends_msgf(const char *fmt, ...);
|
||||
void ms_sends_compl_l3(const char *hex, const struct gsm0808_speech_codec_list *codec_list_bss_supported);
|
||||
void ms_sends_classmark_update(const struct osmo_gsm48_classmark *classmark);
|
||||
void ms_sends_ciphering_mode_complete(const char *inner_nas_msg);
|
||||
void ms_sends_security_mode_complete(uint8_t utran_encryption);
|
||||
void ms_sends_assignment_complete(enum mgcp_codecs assigned_codec);
|
||||
void ms_sends_assignment_complete(const char *sdp_codec_name);
|
||||
void gsup_rx(const char *rx_hex, const char *expect_tx_hex);
|
||||
void send_sms(struct vlr_subscr *receiver,
|
||||
struct vlr_subscr *sender,
|
||||
|
|
Loading…
Reference in New Issue