aboutsummaryrefslogtreecommitdiffstats
path: root/pcu/RAW_NS.ttcn
blob: 9c31820c19b00ab88d5c0914851637b3102a04c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
module RAW_NS {

/* Osmocom NS test suite for NS in TTCN-3
 * (C) 2018-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 SGSN_Components all;
import from Osmocom_Gb_Types all;
import from NS_CodecPort all;
import from NS_Types all;
import from BSSGP_Types all;
import from NS_CodecPort all;
import from NS_CodecPort_CtrlFunct all;
import from NS_Emulation all;
import from Native_Functions all;
import from IPL4asp_Types all;

public type component RAW_NS_CT {
	/* UDP port towards the bottom (IUT) */
	port NS_CODEC_PT NSCP[4];
	var ConnectionId g_ns_conn_id[4] := {-1, -1, -1, -1};
	var NSConfiguration g_nsconfig[4];
	timer g_T_guard;
}

public altstep as_Tguard() runs on RAW_NS_CT {
	[] g_T_guard.timeout {
		setverdict(fail, "Timeout of T_guard");
		mtc.stop;
		}
}

function f_init_ns_codec(NSConfiguration ns_config, integer idx := 0, float guard_secs := 60.0, integer tc_offset := 0) runs on RAW_NS_CT {
	var Result res;

	if (not g_T_guard.running) {
		g_T_guard.start(guard_secs);
		activate(as_Tguard());
	}

	if (not isbound(g_nsconfig) or not isbound(g_nsconfig[idx])) {
		/* copy most parts from mp_nsconfig */
		g_nsconfig[idx] := ns_config;
		/* adjust those parts different for each NS-VC */
		g_nsconfig[idx].nsvci := ns_config.nsvci + idx;
		g_nsconfig[idx].local_udp_port := ns_config.local_udp_port + idx + tc_offset;
	}

	map(self:NSCP[idx], system:NSCP);
	/* Connect the UDP socket */
	log("connecting NSCP[", idx, "] to ", g_nsconfig[idx]);
	res := f_IPL4_connect(NSCP[idx], g_nsconfig[idx].remote_ip, g_nsconfig[idx].remote_udp_port,
				g_nsconfig[idx].local_ip, g_nsconfig[idx].local_udp_port, 0, { udp := {}});
	if (not ispresent(res.connId)) {
		setverdict(fail, "Could not connect NS UDP socket, check your configuration ", g_nsconfig[idx]);
		mtc.stop;
	}
	g_ns_conn_id[idx] := res.connId;

}

function f_ns_exp(template PDU_NS exp_rx, integer idx := 0) runs on RAW_NS_CT return PDU_NS {
	var NS_RecvFrom nrf;
	log("f_ns_exp() expecting ", exp_rx);
	alt {
	[] NSCP[idx].receive(t_NS_RecvFrom(exp_rx)) -> value nrf { }
	[] NSCP[idx].receive(t_NS_RecvFrom(?)) -> value nrf {
		setverdict(fail, "Received unexpected NS: ", nrf);
		mtc.stop;
		}
	}
	return nrf.msg;
}

/* perform outbound NS-ALIVE procedure */
function f_outgoing_ns_alive(integer idx := 0) runs on RAW_NS_CT {
	NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE));
	alt {
	[] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE_ACK));
	[] NSCP[idx].receive { repeat; }
	}
}

/* perform outbound NS-ALIVE procedure */
function f_outgoing_ns_alive_no_ack(integer idx := 0, float tout := 10.0) runs on RAW_NS_CT {
	timer T := tout;
	NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE));
	T.start;
	alt {
	[] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE_ACK)) {
		setverdict(fail, "Received unexpected NS-ALIVE ACK");
		}
	[] NSCP[idx].receive { repeat; }
	[] T.timeout {
		setverdict(pass);
		}
	}
}

function f_outgoing_ns_reset(integer idx := 0, float tout := 10.0) runs on RAW_NS_CT {
	timer T := tout;
	var template PDU_NS reset := ts_NS_RESET(NS_CAUSE_EQUIPMENT_FAILURE, g_nsconfig[idx].nsvci, g_nsconfig[idx].nsei)
	NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], reset));
	T.start;
	alt {
	[] NSCP[idx].receive(t_NS_RecvFrom(ts_NS_RESET_ACK(g_nsconfig[idx].nsvci, g_nsconfig[idx].nsei))) {
		setverdict(pass);
		}
	[] NSCP[idx].receive { repeat; }
	[] T.timeout {
		setverdict(fail, "Failed to receive a RESET ACK");
		}
	}
}

/* perform outbound NS-BLOCK procedure */
function f_outgoing_ns_block(NsCause cause, integer idx := 0) runs on RAW_NS_CT {
	NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_BLOCK(cause, g_nsconfig[idx].nsvci)));
	alt {
	[] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_BLOCK_ACK(g_nsconfig[idx].nsvci)));
	[] NSCP[idx].receive { repeat; }
	}
}

/* receive NS-ALIVE and ACK it */
altstep as_rx_alive_tx_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
	[] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE)) {
		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE_ACK));
		if (not oneshot) { repeat; }
		}
}

/* Transmit BSSGP RESET for given BVCI and expect ACK */
function f_tx_bvc_reset_rx_ack(BssgpBvci bvci, integer idx := 0, boolean exp_ack := true)
runs on RAW_NS_CT {
	var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET(BSSGP_CAUSE_NET_SV_CAP_MOD_GT_ZERO_KBPS, bvci,
							mp_gb_cfg.cell_id));
	timer T := 5.0;
	NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
	T.start;
	alt {
	[exp_ack] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
						  decmatch tr_BVC_RESET_ACK(bvci, ?)))) {
		setverdict(pass);
		}
	[exp_ack] T.timeout {
		setverdict(fail, "No response to BVC-RESET");
		}
	[not exp_ack] T.timeout {
		setverdict(pass);
		}
	[] NSCP[idx].receive { repeat; }
	}
}

/* Receive a BSSGP RESET for given BVCI and ACK it */
altstep as_rx_bvc_reset_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
	var NS_RecvFrom ns_rf;
	/* FIXME: nail down received cell_id in match */
	[] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
						  decmatch tr_BVC_RESET(?, bvci, ?))))
								-> value ns_rf {
		var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
		var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET_ACK(bvci, mp_gb_cfg.cell_id));
		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
		if (not oneshot) { repeat; }
		}
}


/* Receive a BSSGP UNBLOCK for given BVCI and ACK it */
altstep as_rx_bvc_unblock_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
	var NS_RecvFrom ns_rf;
	[] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
						  decmatch t_BVC_UNBLOCK(bvci))))
								-> value ns_rf {
		var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
		var PDU_BSSGP bssgp_tx := valueof(t_BVC_UNBLOCK_ACK(bvci));
		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
		if (not oneshot) { repeat; }
		}
}

/* Receive a BSSGP FLOW-CONTROL-BVC and ACK it */
altstep as_rx_bvc_fc_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
	var NS_RecvFrom ns_rf;
	[] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, bvci,
						  decmatch tr_BVC_FC_BVC)))
								-> value ns_rf {
		var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
		var OCT1 tag := bssgp_rx.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
		var PDU_BSSGP bssgp_tx := valueof(t_BVC_FC_BVC_ACK(tag));
		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, bvci, enc_PDU_BSSGP(bssgp_tx))));
		if (not oneshot) { repeat; }
		}
}

/**********************************************************************************
 * Classic Gb/IP bring-up test cases using NS-{RESET,BLOCK,UNBLOCK} and no IP-SNS *
 **********************************************************************************/

/* Receive a NS-RESET and ACK it */
public altstep as_rx_ns_reset_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
	var NS_RecvFrom ns_rf;
	[] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION, g_nsconfig[idx].nsvci,
						  g_nsconfig[idx].nsei))) -> value ns_rf {
		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_RESET_ACK(g_nsconfig[idx].nsvci,
									    g_nsconfig[idx].nsei)));
		if (not oneshot) { repeat; }
		}
}
/* Receive a NS-UNBLOCK and ACK it */
public altstep as_rx_ns_unblock_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
	var NS_RecvFrom ns_rf;
	[] NSCP[idx].receive(t_NS_RecvFrom(t_NS_UNBLOCK)) -> value ns_rf {
		NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_UNBLOCK_ACK));
		if (not oneshot) { repeat; }
		}
}

}