/* OsmoS1GW (S1AP Gateway) test suite in TTCN-3
 *
 * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
 * Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
 *
 * 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
 */

module S1GW_Tests {

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

import from S1AP_CodecPort all;
import from S1AP_CodecPort_CtrlFunct all;
import from S1AP_Types all;
import from S1AP_Templates all;
import from S1AP_PDU_Descriptions all;
import from S1AP_IEs all;
import from S1AP_PDU_Contents all;
import from S1AP_Constants all;

import from SCTP_Templates all;
import from S1AP_Server all;

modulepar {
	charstring mp_s1gw_enb_ip;	/* eNB facing address of the S1GW */
	charstring mp_s1gw_mme_ip;	/* MME facing address of the S1GW */
	charstring mp_mme_bind_ip;	/* MME address on which we get connections from S1GW */
}

private type record of ConnHdlr ConnHdlrList;

type component ConnHdlr extends S1APSRV_ConnHdlr {
	port S1AP_CODEC_PT S1AP_ENB;
	var ConnectionId g_s1ap_conn_id := -1;
};

type component test_CT {
	timer g_Tguard;
	var S1AP_Server_CT vc_S1APSRV;
};

private altstep as_Tguard() runs on test_CT {
	[] g_Tguard.timeout {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout");
	}
}

template Global_ENB_ID
ts_Global_ENB_ID(integer enb_id := 0,
		 OCT3 plmn_id := '00f110'O) := {
	pLMNidentity := plmn_id,
	eNB_ID := {
		macroENB_ID := int2bit(enb_id, 20)
	},
	iE_Extensions := omit
}

function f_init(float Tval := 20.0) runs on test_CT {
	g_Tguard.start(Tval);
	activate(as_Tguard());
}

function f_init_s1ap_srv() runs on test_CT {
	var S1APSRV_ConnParams cpars := {
		local_ip := mp_mme_bind_ip,
		local_port := 36412
	};

	vc_S1APSRV := S1AP_Server_CT.create("S1APSRV-" & testcasename());
	vc_S1APSRV.start(S1AP_Server.main(cpars));
}

type record ConnHdlrPars {
	Global_ENB_ID genb_id
};

template (value) ConnHdlrPars
t_ConnHdlrPars(integer enb_id := 0) := {
	genb_id := ts_Global_ENB_ID(enb_id)
}

type function void_fn(ConnHdlrPars pars) runs on ConnHdlr;

function f_ConnHdlr_spawn(void_fn fn, ConnHdlrPars pars)
runs on test_CT return ConnHdlr {
	var ConnHdlr vc_conn;

	vc_conn := ConnHdlr.create("ConnHdlr-" & testcasename());
	if (vc_S1APSRV.running) {
		connect(vc_conn:S1AP_CONN, vc_S1APSRV:S1AP_CLIENT);
		connect(vc_conn:S1AP_PROC, vc_S1APSRV:S1AP_PROC);
	}
	vc_conn.start(derefers(fn)(pars));

	return vc_conn;
}

function f_ConnHdlr_connect() runs on ConnHdlr {
	var Result res;
	timer T;

	map(self:S1AP_ENB, system:S1AP_CODEC_PT);

	/* initiate SCTP connection establishment */
	res := S1AP_CodecPort_CtrlFunct.f_IPL4_connect(S1AP_ENB,
						       mp_s1gw_enb_ip, 36412,
						       "0.0.0.0", 0, -1,
						       { sctp := c_SctpTuple_S1AP });
	if (not ispresent(res.connId)) {
		setverdict(fail, "Could not create an S1AP socket, check your configuration");
		mtc.stop;
	}
	g_s1ap_conn_id := res.connId;

	/* wait for the establishment confirmation */
	T.start(2.0);
	alt {
	[] S1AP_ENB.receive(tr_SctpAssocChange(SCTP_COMM_UP, g_s1ap_conn_id)) {
		log("eNB connection established");
		}
	[] S1AP_ENB.receive(PortEvent:{sctpEvent := ?}) { repeat; }
	[] T.timeout {
		setverdict(fail, "eNB connection establishment timeout");
		self.stop;
		}
	}
}

function f_ConnHdlr_disconnect() runs on ConnHdlr {
	var Result res;

	S1AP_CodecPort_CtrlFunct.f_IPL4_close(S1AP_ENB, g_s1ap_conn_id,
					      { sctp := c_SctpTuple_S1AP });
	g_s1ap_conn_id := -1;
	unmap(self:S1AP_ENB, system:S1AP_CODEC_PT);

	S1AP_CONN.receive(S1APSRV_Event:S1APSRV_EVENT_CONN_DOWN);

	log("eNB connection closed");
}

function f_ConnHdlr_expect_shutdown() runs on ConnHdlr {
	S1AP_ENB.receive(tr_SctpShutDownEvent(g_s1ap_conn_id));
	S1AP_ENB.receive(tr_SctpAssocChange(SCTP_SHUTDOWN_COMP, g_s1ap_conn_id));
	S1AP_ENB.receive(PortEvent:{connClosed := ?});
}

function f_ConnHdlr_tx_s1ap_from_enb(template (value) S1AP_PDU pdu)
runs on ConnHdlr {
	S1AP_ENB.send(t_S1AP_Send(g_s1ap_conn_id, pdu));
}

function f_ConnHdlr_tx_s1ap_from_mme(template (value) S1AP_PDU pdu)
runs on ConnHdlr {
	S1AP_CONN.send(pdu);
}

function f_ConnHdlr_rx_s1ap_from_enb(out S1AP_PDU pdu,
				     template (present) S1AP_PDU tr_pdu := ?,
				     float Tval := 0.5)
runs on ConnHdlr {
	timer T := Tval;

	T.start;
	alt {
	[] S1AP_CONN.receive(tr_pdu) -> value pdu {
		setverdict(pass);
		T.stop;
		}
	[] S1AP_CONN.receive(S1AP_PDU:?) -> value pdu {
		setverdict(fail, "Rx unexpected S1AP PDU from eNB: ", pdu);
		T.stop;
		}
	[] T.timeout {
		setverdict(fail, "Timeout waiting for S1AP PDU from eNB: ", tr_pdu);
		}
	}
}

function f_ConnHdlr_rx_s1ap_from_mme(out S1AP_PDU pdu,
				     template (present) S1AP_PDU tr_pdu := ?,
				     float Tval := 0.5)
runs on ConnHdlr {
	var S1AP_RecvFrom recv;
	timer T := Tval;

	T.start;
	alt {
	[] S1AP_ENB.receive(t_S1AP_RecvFrom(tr_pdu)) -> value recv {
		pdu := recv.msg;
		setverdict(pass);
		T.stop;
		}
	[] S1AP_ENB.receive(t_S1AP_RecvFrom(?)) -> value recv {
		pdu := recv.msg;
		setverdict(fail, "Rx unexpected S1AP PDU from MME: ", pdu);
		T.stop;
		}
	[] T.timeout {
		setverdict(fail, "Timeout waiting for S1AP PDU from MME: ", tr_pdu);
		}
	}
}

function f_ConnHdlr_setup(Global_ENB_ID genb_id) runs on ConnHdlr {
	var S1AP_PDU pdu;
	timer T;

	var SupportedTAs supported_tas_dummy := {
		{
			tAC := '0000'O,
			broadcastPLMNs := { '00f000'O },
			iE_Extensions := omit
		}
	};

	f_ConnHdlr_tx_s1ap_from_enb(ts_S1AP_SetupReq(genb_id,
						     supported_tas_dummy,
						     v32));
	T.start(1.0);
	alt {
	[] S1AP_CONN.receive(S1APSRV_Event:S1APSRV_EVENT_CONN_UP) { repeat; }
	[] S1AP_CONN.receive(tr_S1AP_SetupReq) {
		setverdict(pass);
		T.stop;
		}
	[] S1AP_CONN.receive(S1AP_PDU:?) -> value pdu {
		setverdict(fail, "Rx unexpected S1AP PDU: ", pdu);
		T.stop;
		}
	[] T.timeout {
		setverdict(fail, "Timeout waiting for S1AP SetupReq");
		}
	}
}


function f_TC_setup(ConnHdlrPars pars) runs on ConnHdlr {
	f_ConnHdlr_register(pars.genb_id);

	f_ConnHdlr_connect();
	f_ConnHdlr_setup(pars.genb_id);
	f_sleep(0.5); /* keep the connection idle for some time */
	f_ConnHdlr_disconnect();

	f_ConnHdlr_unregister(pars.genb_id);
}
testcase TC_setup() runs on test_CT {
	var ConnHdlrPars pars := valueof(t_ConnHdlrPars);
	var ConnHdlr vc_conn;

	f_init();
	f_init_s1ap_srv();

	vc_conn := f_ConnHdlr_spawn(refers(f_TC_setup), pars);
	vc_conn.done;
}
testcase TC_setup_multi() runs on test_CT {
	var ConnHdlrList vc_conns := { };

	f_init();
	f_init_s1ap_srv();

	for (var integer i := 0; i < 42; i := i + 1) {
		var ConnHdlrPars pars := valueof(t_ConnHdlrPars(i));
		var ConnHdlr vc_conn := f_ConnHdlr_spawn(refers(f_TC_setup), pars);
		vc_conns := vc_conns & { vc_conn };
	}

	for (var integer i := 0; i < 42; i := i + 1) {
		vc_conns[i].done;
	}
}


/* MME terminates connection, expect S1GW to terminate the eNB connection */
function f_TC_conn_term_by_mme(ConnHdlrPars pars) runs on ConnHdlr {
	f_ConnHdlr_register(pars.genb_id);

	f_ConnHdlr_connect();
	f_ConnHdlr_setup(pars.genb_id);
	f_sleep(0.5); /* keep the connection idle for some time */

	/* MME (S1AP_Server_CT) terminates connection */
	f_ConnHdlr_close_conn(pars.genb_id);
	/* expect our eNB connection to be released gracefully */
	f_ConnHdlr_expect_shutdown();

	f_ConnHdlr_unregister(pars.genb_id);
}
testcase TC_conn_term_by_mme() runs on test_CT {
	var ConnHdlrPars pars := valueof(t_ConnHdlrPars);
	var ConnHdlr vc_conn;

	f_init();
	f_init_s1ap_srv();

	vc_conn := f_ConnHdlr_spawn(refers(f_TC_conn_term_by_mme), pars);
	vc_conn.done;
}


/* MME is not available, expect S1GW to terminate the eNB connection */
function f_TC_conn_term_mme_unavail(ConnHdlrPars pars) runs on ConnHdlr {
	/* establish an eNB connection to the S1GW */
	f_ConnHdlr_connect();
	/* expect our eNB connection to be released gracefully */
	f_ConnHdlr_expect_shutdown();
	setverdict(pass);
}
testcase TC_conn_term_mme_unavail() runs on test_CT {
	var ConnHdlrPars pars := valueof(t_ConnHdlrPars);
	var ConnHdlr vc_conn;

	f_init();
	f_init_s1ap_srv();
	vc_S1APSRV.stop;

	vc_conn := f_ConnHdlr_spawn(refers(f_TC_conn_term_mme_unavail), pars);
	vc_conn.done;
}

function f_TC_e_rab_setup(ConnHdlrPars pars) runs on ConnHdlr {
	const integer mme_id := 7;
	const integer enb_id := 9;
	const integer erab_id := 6;
	var S1AP_PDU pdu;

	f_ConnHdlr_register(pars.genb_id);
	f_ConnHdlr_connect();
	f_ConnHdlr_setup(pars.genb_id);

	log("eNB -> [S1GW] -> MME: E-RAB SETUP REQUEST");
	var template (value) E_RABToBeSetupListBearerSUReq items_req;
	var E_RABToBeSetupItemBearerSUReq item_req := {
		e_RAB_ID := erab_id,
		e_RABlevelQoSParameters := {
			qCI := 5,
			allocationRetentionPriority := {
				priorityLevel := 1,
				pre_emptionCapability := shall_not_trigger_pre_emption,
				pre_emptionVulnerability := not_pre_emptable,
				iE_Extensions := omit
			},
			gbrQosInformation := omit,
			iE_Extensions := omit
		},
		transportLayerAddress := -,
		gTP_TEID := f_rnd_octstring(4),
		nAS_PDU := ''O,
		iE_Extensions := omit
	};

	/* eNB -> S1GW */
	item_req.transportLayerAddress := oct2bit(f_inet_addr("1.2.3.4"));
	items_req := ts_S1AP_RABToBeSetupListBearerSUReq(item_req);
	f_ConnHdlr_tx_s1ap_from_enb(ts_S1AP_RABSetupReq(mme_id, enb_id, items_req));

	/* S1GW -> MME */
	item_req.transportLayerAddress := oct2bit(f_inet_addr(mp_s1gw_mme_ip));
	items_req := ts_S1AP_RABToBeSetupListBearerSUReq(item_req);
	f_ConnHdlr_rx_s1ap_from_enb(pdu, tr_S1AP_RABSetupReq(mme_id, enb_id, items_req));


	log("eNB <- [S1GW] <- MME: E-RAB SETUP RESPONSE");
	var template (value) E_RABSetupListBearerSURes items_res;
	var E_RABSetupItemBearerSURes item_res := {
		e_RAB_ID := erab_id,
		transportLayerAddress := -,
		gTP_TEID := f_rnd_octstring(4),
		iE_Extensions := omit
	};

	/* MME -> S1GW */
	item_res.transportLayerAddress := oct2bit(f_inet_addr("4.3.2.1"));
	items_res := ts_S1AP_RABSetupListBearerSURes(item_res);
	f_ConnHdlr_tx_s1ap_from_mme(ts_S1AP_RABSetupRsp(mme_id, enb_id, items_res));

	/* S1GW -> eNB */
	item_res.transportLayerAddress := oct2bit(f_inet_addr(mp_s1gw_enb_ip));
	items_res := ts_S1AP_RABSetupListBearerSURes(item_res);
	f_ConnHdlr_rx_s1ap_from_mme(pdu, tr_S1AP_RABSetupRsp(mme_id, enb_id, items_res));

	f_ConnHdlr_disconnect();
	f_ConnHdlr_unregister(pars.genb_id);
}
testcase TC_e_rab_setup() runs on test_CT {
	var ConnHdlrPars pars := valueof(t_ConnHdlrPars);
	var ConnHdlr vc_conn;

	f_init();
	f_init_s1ap_srv();

	vc_conn := f_ConnHdlr_spawn(refers(f_TC_e_rab_setup), pars);
	vc_conn.done;
}

control {
	execute( TC_setup() );
	execute( TC_setup_multi() );
	execute( TC_conn_term_by_mme() );
	execute( TC_conn_term_mme_unavail() );
	execute( TC_e_rab_setup() );
}

}
