module STP_Tests_IPA_M3UA {

/* Osmocom STP test suite in in TTCN-3
 * (C) 2019 Harald Welte <laforge@gnumonks.org>
 * All rights reserved.
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

import from General_Types all;
import from Osmocom_Types all;
import from IPL4asp_Types all;
import from Misc_Helpers all;

import from Osmocom_VTY_Functions all;

import from M3UA_Types all;
import from M3UA_Templates all;
import from M3UA_CodecPort all;
import from M3UA_CodecPort_CtrlFunct all;

import from M3UA_Emulation all;
import from MTP3asp_Types all;
import from MTP3asp_PortType all;

import from SCCP_Types all;
import from SCCP_Templates all;
import from SCCPasp_Types all;
import from SCCP_Emulation all;

import from IPA_Emulation all;

import from STP_Tests_Common all;
import from STP_Tests_IPA all;
import from STP_Tests_M3UA all;


type component IPA_M3UA_CT extends RAW_M3UA_CT, IPA_CT {
};

const OCT1 c_M3UA_SI_SCCP := '03'O;

/* Test routing of SCCP between an M3UA and an IPA ASP */
testcase TC_m3ua_to_ipa() runs on IPA_M3UA_CT {
	var Misc_Helpers.ro_charstring ipa_asps := { "ipa-asp-dynamic-unknown" };
	var IpaConfigs ipa_configs := ipa_build_configs(ipa_asps);
	var Misc_Helpers.ro_charstring m3ua_asps := { "asp-sender" };
	var M3uaConfigs m3ua_configs := m3ua_build_configs(m3ua_asps);
	var OCT4 rctx_sender := int2oct(m3ua_configs[0].routing_ctx, 4);
	var OCT4 pc_sender := int2oct(m3ua_configs[0].point_code, 4);
	var OCT4 pc_receiver := int2oct(ipa_configs[0].point_code, 4);

	f_init_m3ua(m3ua_configs := m3ua_configs);
	f_init_ipa(ipa_configs := ipa_configs);

	f_connect_ipa(0);
	/* exp_duna_after_act = false: There's no other unavailable AS configured at the STP at this point. */
	f_M3UA_asp_up_act(0, omit, rctx_sender, exp_duna_after_act := false);

	/* send a well-formed, encoded SCCP message via M3UA */
	var octetstring sccp_enc := f_SCCP_UDT();
	var template (value) M3UA_Protocol_Data tx_pd;
	tx_pd := ts_M3UA_protocol_data(pc_sender, pc_receiver, c_M3UA_SI_SCCP, '00'O, '00'O, '00'O, sccp_enc);
	f_M3UA_send(0, ts_M3UA_DATA(rctx_sender, tx_pd), 1);

	/* expect to receive it via IPA */
	f_IPA_exp(0, sccp_enc);

	f_clear_m3ua();
}

/* test routing an SCCP message from IPA ASP to M3UA ASP */
testcase TC_ipa_to_m3ua() runs on IPA_M3UA_CT {
	var Misc_Helpers.ro_charstring ipa_asps := { "ipa-asp-dynamic-unknown" };
	var IpaConfigs ipa_configs := ipa_build_configs(ipa_asps);
	var Misc_Helpers.ro_charstring m3ua_asps := { "asp-sender" };
	var M3uaConfigs m3ua_configs := m3ua_build_configs(m3ua_asps);
	var OCT4 pc_sender := int2oct(ipa_configs[0].point_code, 4);
	var OCT4 rctx_receiver := int2oct(m3ua_configs[0].routing_ctx, 4);
	var OCT4 pc_receiver := int2oct(m3ua_configs[0].point_code, 4);

	f_init_common();
	f_vty_cs7_ipa_as_cmd(ipa_configs[0].as_name, "point-code override patch-sccp disabled");

	f_init_m3ua(m3ua_configs := m3ua_configs);
	f_init_ipa(ipa_configs := ipa_configs);

	f_connect_ipa(0);
	/* exp_duna_after_act = false: There's no other unavailable AS configured at the STP at this point. */
	f_M3UA_asp_up_act(0, omit, rctx_receiver, exp_duna_after_act := false);

	/* send a well-formed, encoded SCCP message via IPA */
	var octetstring sccp_enc := f_SCCP_UDT();
	f_IPA_send(0, sccp_enc);

	/* expect to receive it via M3UA */
	var template (present) M3UA_Protocol_Data rx_pd;
	rx_pd := tr_M3UA_protocol_data(pc_sender, pc_receiver, c_M3UA_SI_SCCP, '00'O, '00'O, ?, sccp_enc);
	f_M3UA_exp(0, tr_M3UA_DATA(rctx_receiver, rx_pd));

	f_clear_m3ua();
}

/* test routing an SCCP message from IPA ASP to M3UA ASP using national network indicator */
testcase TC_ipa_to_m3ua_ni() runs on IPA_M3UA_CT {
	var Misc_Helpers.ro_charstring ipa_asps := { "ipa-asp-dynamic-unknown" };
	var IpaConfigs ipa_configs := ipa_build_configs(ipa_asps);
	var Misc_Helpers.ro_charstring m3ua_asps := { "asp-sender" };
	var M3uaConfigs m3ua_configs := m3ua_build_configs(m3ua_asps);
	var OCT4 pc_sender := int2oct(ipa_configs[0].point_code, 4);
	var OCT4 rctx_receiver := int2oct(m3ua_configs[0].routing_ctx, 4);
	var OCT4 pc_receiver := int2oct(m3ua_configs[0].point_code, 4);

	f_init_common();
	f_vty_cs7_ipa_as_cmd(ipa_configs[0].as_name, "point-code override patch-sccp disabled");

	f_init_m3ua(m3ua_configs := m3ua_configs);
	f_init_ipa(ipa_configs := ipa_configs);

	f_connect_ipa(0);
	/* exp_duna_after_act = false: There's no other unavailable AS configured at the STP at this point. */
	f_M3UA_asp_up_act(0, omit, rctx_receiver, exp_duna_after_act := false);

	/* send a well-formed, encoded SCCP message via IPA */
	var octetstring sccp_enc := f_SCCP_UDT();
	f_vty_config2(VTY, {"cs7 instance 0"}, "network-indicator national");
	f_IPA_send(0, sccp_enc);

	/* expect to receive it via M3UA */
	var template (present) M3UA_Protocol_Data rx_pd;
	rx_pd := tr_M3UA_protocol_data(pc_sender, pc_receiver, c_M3UA_SI_SCCP, c_M3UA_NI_NATIONAL,
					'00'O, ?, sccp_enc);
	f_M3UA_exp(0, tr_M3UA_DATA(rctx_receiver, rx_pd));
	f_vty_config2(VTY, {"cs7 instance 0"}, "network-indicator international");
	f_clear_m3ua();
}


/* test routing an SCCP message from IPA ASP to M3UA ASP while patching PC into SCCP addresses */
testcase TC_ipa_to_m3ua_patch_sccp() runs on IPA_M3UA_CT {
	var Misc_Helpers.ro_charstring ipa_asps := { "ipa-asp-dynamic-unknown" };
	var IpaConfigs ipa_configs := ipa_build_configs(ipa_asps);
	var Misc_Helpers.ro_charstring m3ua_asps := { "asp-sender" };
	var M3uaConfigs m3ua_configs := m3ua_build_configs(m3ua_asps);
	var OCT4 pc_sender := int2oct(ipa_configs[0].point_code, 4);
	var OCT4 rctx_receiver := int2oct(m3ua_configs[0].routing_ctx, 4);
	var OCT4 pc_receiver := int2oct(m3ua_configs[0].point_code, 4);

	f_init_common();
	f_vty_cs7_ipa_as_cmd(ipa_configs[0].as_name, "point-code override patch-sccp both");

	f_init_m3ua(m3ua_configs := m3ua_configs);
	f_init_ipa();

	f_connect_ipa(0);
	/* exp_duna_after_act = false: There's no other unavailable AS configured at the STP at this point. */
	f_M3UA_asp_up_act(0, omit, rctx_receiver, exp_duna_after_act := false);

	/* send a well-formed, encoded SCCP message via IPA */
	var SCCP_PAR_Address calling := valueof(ts_SccpAddr_GT('5678'H));
	var SCCP_PAR_Address called := valueof(ts_SccpAddr_GT('1234'H));
	var octetstring data := f_rnd_octstring_rnd_len(100);
	var octetstring sccp_enc := f_SCCP_UDT(calling, called, data);
	f_IPA_send(0, sccp_enc);

	/* patch point codes into addresses */
	called := valueof(ts_SccpAddr_PC_GT(oct2int(pc_receiver), '83'O, "mtp3_itu", '1234'H));
	calling := valueof(ts_SccpAddr_PC_GT(oct2int(pc_sender), '83'O, "mtp3_itu", '5678'H));
	sccp_enc := f_SCCP_UDT(calling, called, data);

	/* expect to receive it via M3UA */
	var template (present) M3UA_Protocol_Data rx_pd;
	rx_pd := tr_M3UA_protocol_data(pc_sender, pc_receiver, c_M3UA_SI_SCCP, '00'O, '00'O, ?,
				       sccp_enc);
	f_M3UA_exp(0, tr_M3UA_DATA(rctx_receiver, rx_pd));

	f_clear_m3ua();
}



control {
	/* M3UA <-> IPA Tests */
	execute( TC_m3ua_to_ipa() );
	execute( TC_ipa_to_m3ua() );
	execute( TC_ipa_to_m3ua_ni() );
	execute( TC_ipa_to_m3ua_patch_sccp() );
}



}
