hnodeb: Add audio SAPI

Change-Id: I20544f67c2450bc3cd4bcb3ee638de1958bf5783
diff --git a/hnodeb/HNB_Tests.ttcn b/hnodeb/HNB_Tests.ttcn
index 59dd1ee..05cd2bf 100644
--- a/hnodeb/HNB_Tests.ttcn
+++ b/hnodeb/HNB_Tests.ttcn
@@ -24,6 +24,7 @@
 import from General_Types all;
 import from Osmocom_Types all;
 import from IPL4asp_Types all;
+import from Native_Functions all;
 
 import from Osmocom_CTRL_Functions all;
 import from Osmocom_CTRL_Types all;
@@ -44,6 +45,9 @@
 import from HNBGW_ConnectionHandler all;
 import from Iuh_Emulation all;
 
+import from RTP_Types all;
+import from RTP_Emulation all;
+
 import from HNBLLIF_CodecPort all;
 import from HNBLLIF_Types all;
 import from HNBLLIF_Templates all;
@@ -63,6 +67,7 @@
 const hexstring ranap_auth_req := '00144032000002001040262505120217dc146aeac56cb5ff6d5fb51f47f19220108ca5a6d0c8110000b9e9272498872764003b400100'H;
 const hexstring ranap_auth_resp := '001440140000010010400d0c0554ccbdd0302104002f3ae4'H;
 const hexstring ranap_paging := '000e401e0000030003400100001740095000010100000000f10040400500b6cf4773'H;
+const hexstring ranap_rab_ass_req := '0000005900000100364052000001003500487824cd80102fa7201a2c0000f44c080a028000514000272028140067400000222814003c40000000503d02000227c03500010a0901a200000000000000000000000000401f4a0000400100'H;
 const hexstring iu_release_compl := '20010003000000'H;
 
 type component test_CT extends CTRL_Adapter_CT {
@@ -277,11 +282,89 @@
 	f_shutdown_helper();
 }
 
+private function f_tc_cs_mo_call(charstring id) runs on HNBGW_ConnHdlr {
+	const integer context_id := 30;
+	const bitstring context_id_bstr := '000000000000000000011110'B; /* encoded context_id */
+	const Establishment_Cause est_cause := normal_call;
+	var HNBLLIF_send_data sd;
+	var PDU_RTP rtp_pdu;
+	var octetstring rtp_payload;
+	var HostName hnodeb_rtp_addr;
+	var PortNumber hnodeb_rtp_port;
+	timer Tu;
+
+	f_handle_hnbap_hnb_register_req();
+
+	LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONFIGURE_IND(g_pars.mcc, g_pars.mnc, g_pars.cell_identity,
+						  g_pars.lac, g_pars.rac, g_pars.sac, g_pars.rnc_id)));
+
+	/* Now an UE attempts CM Service Request: */
+	LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_ESTABLISH_REQ(context_id, 0, enum2int(est_cause), hex2oct(ranap_cm_service_req))));
+	/* The related RUA Connect + RANAP message is received on Iuh: */
+	RUA.receive(tr_RUA_Connect(cs_domain, context_id_bstr, est_cause, hex2oct(ranap_cm_service_req)));
+
+	/* Now HNBGW answers with RUA-DirectTransfer(RANAP-RabASsReq) */
+	RUA.send(ts_RUA_DirectTransfer(cs_domain, context_id_bstr, hex2oct(ranap_rab_ass_req)));
+
+	/* Now on LLSK first the Conn establishment is confirmed and then we receive data */
+	LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONN_ESTABLISH_CNF(context_id, 0, 0)));
+	LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONN_DATA_IND(context_id, 0, hex2oct(ranap_rab_ass_req))));
+
+	/* Now LLSK provides the remote TransportLayerAddress from RabAssReq and asks SUT to provide a local address: */
+	LLSK.send(f_llsk_tx(ts_HNBLLIF_AUDIO_CONN_ESTABLISH_REQ(context_id, g_pars.hnbgw_rtp_port, HNBLL_IF_ADDR_TYPE_IPV4,
+								f_HNBLLIF_Addr(HNBLL_IF_ADDR_TYPE_IPV4, g_pars.hnbgw_addr))));
+	LLSK.receive(f_llsk_rx(tr_HNBLLIF_AUDIO_CONN_ESTABLISH_CNF(context_id, 0, ?, HNBLL_IF_ADDR_TYPE_IPV4, ?))) -> value sd;
+
+	hnodeb_rtp_addr := f_inet_ntoa(sd.data.u.audio.u.conn_establish.u.cnf.local_addr);
+	if (not match(g_pars.hnodeb_addr, hnodeb_rtp_addr)) {
+		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "hnodeb RTP local address doesn't match expectations");
+	}
+	hnodeb_rtp_port := sd.data.u.audio.u.conn_establish.u.cnf.local_rtp_port;
+	rtp_payload := f_rnd_octstring(6);
+	f_HNBGW_rtpem_activate(rtp_payload, hnodeb_rtp_addr, hnodeb_rtp_port);
+	/* Make sure that Uplink frames are received at the HNBGW */
+	RTPEM_DATA.clear;
+	LLSK.send(f_llsk_tx(ts_HNBLLIF_AUDIO_CONN_DATA_REQ(context_id, rtp_payload)));
+	Tu.start(2.0);
+	alt {
+	[] RTPEM_DATA.receive(PDU_RTP:?) -> value rtp_pdu {
+		if (rtp_pdu.data != rtp_payload) {
+				log("Unexpected RTP payload received!");
+				repeat;
+			}
+		}
+	[] RTPEM_DATA.receive { repeat; }
+	[] Tu.timeout {
+		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for Uplink speech frames");
+		}
+	}
+	Tu.stop;
+	/* We should also have received some RTP from the HNBGW: */
+	LLSK.receive(f_llsk_rx(tr_HNBLLIF_AUDIO_CONN_DATA_IND(context_id, rtp_payload)));
+
+	f_rtpem_mode(RTPEM_CTRL, RTPEM_MODE_NONE);
+
+	LLSK.send(f_llsk_tx(ts_HNBLLIF_AUDIO_CONN_RELEASE_REQ(context_id)));
+
+	/* UE sends Iu Release Complete to release the conn */
+	LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_RELEASE_REQ(context_id, 0, 0, 0, hex2oct(iu_release_compl))));
+	RUA.receive(tr_RUA_Disconnect(cs_domain, context_id_bstr, ts_RUA_Cause(normal), hex2oct(iu_release_compl)));
+}
+testcase TC_cs_mo_call() runs on test_CT {
+	var HNBGW_ConnHdlr vc_conn;
+
+	f_init();
+	vc_conn := f_start_handler(refers(f_tc_cs_mo_call));
+	vc_conn.done;
+	f_shutdown_helper();
+}
+
 control {
 	execute( TC_hnb_register_request_accept() );
 	execute( TC_hnb_register_request_reject() );
 	execute( TC_mo_conn() );
 	execute( TC_paging() );
+	execute( TC_cs_mo_call() );
 }
 
 }