aboutsummaryrefslogtreecommitdiffstats
path: root/fr/FR_Tests.ttcn
blob: 5e4f9e83476fc4f0111b60ba2a83b8a67924997f (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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
module FR_Tests {

import from General_Types all;
import from Osmocom_Types all;
import from Osmocom_Gb_Types all;

import from NS_Emulation all;
import from BSSGP_Emulation all;
import from LLC_Types all;
import from LLC_Templates all;

modulepar {
	/* NS transport layer MTU (NS header and anything after it) */
	integer mp_ns_mtu := 1500;
	/* number of BVCs to bring up in one Gb instance */
	integer mp_num_bvc := 10;
	/* number of UEs to start in each PTP BVC */
	integer mp_num_ue_in_bvc := 10;
	/* NS configurations; one per NSE; each with any number of NSVC */
	NSConfigurations mp_nsconfig := {
		{
			nsei := 123,
			role_sgsn := false,
			handle_sns := false,
			nsvc := {
				{
					provider := {
						fr := {
							netdev := "hdlc1",
							dlci := 1
						}
					},
					nsvci := 101
				}, {
					provider := {
						fr := {
							netdev := "hdlc2",
							dlci := 2
						}
					},
					nsvci := 102
				}, {
					provider := {
						fr := {
							netdev := "hdlc3",
							dlci := 3
						}
					},
					nsvci := 103
				}, {
					provider := {
						fr := {
							netdev := "hdlc4",
							dlci := 4
						}
					},
					nsvci := 104
				}
			}
		}
	};
}

/* 4 bytes NS-UNITDATA,
 * >= 12 Bytes DL-UNITDATA or 18 bytes BSSGP UL-UNITDATA
 * 3 bytes LLC UI header
 * 3 bytes LLC  FCS
 * <= 3 bytes optional padding
 * --> at least 31 bytes required
 */
const integer c_LLC_BSSGP_NS_overhead := 40;

type record GbInstance {
	NS_CT vc_NS,
	BSSGP_CT vc_BSSGP,
	BssgpConfig cfg
};

type record of GbInstance GbInstances;
type record of NSConfiguration NSConfigurations;
type record of BssgpCellId BssgpCellIds;


type component test_CT {
	var GbInstances g_gb;
	port BSSGP_CT_PROC_PT BSSGP_PROC[16];
};

/* initialize one Gb interface */
private function f_init_gb(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
	var charstring id_idx := id & int2str(offset);
	gb.vc_NS := NS_CT.create(id_idx & "-NSemu");
	gb.vc_BSSGP := BSSGP_CT.create(id_idx & "-BSSGPemu");
	connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
	gb.vc_NS.start(NSStart(mp_nsconfig[offset], id_idx));
	connect(self:BSSGP_PROC[offset], gb.vc_BSSGP:PROC);
	gb.vc_BSSGP.start(BssgpStart(gb.cfg, testcasename()));
}

/* generate a BVC dynamically, using distinct number ranges for BVCI, CID, LAC, ... */
private function f_gen_bvc(integer base, integer idx) return BssgpBvcConfig {
	var BssgpBvcConfig bvc := {
		bvci := base + 100 + idx,
		cell_id := {
			ra_id := {
				lai := {
					mcc_mnc := '262F42'H,
					lac := base + 300 + idx
				},
				rac := 1
			},
			cell_id := base + 600 + idx
		},
		depth := BSSGP_DECODE_DEPTH_LLC,
		create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
	};
	return bvc;
}

/***********************************************************************
 * UE simulation component
 ***********************************************************************/

type component UE_CT extends BSSGP_Client_CT {
	var UE_Pars g_pars;
	timer g_Tguard;
	var LLC_Entities llc;
}
type record of UE_CT ro_ue;

type record UE_Pars {
	hexstring imsi,
	OCT4 tlli,
	float tguard,
	BssgpBvci bvci,
	BssgpCellId cell_id
};

type function void_fn(charstring id) runs on UE_CT;

private altstep as_ue_tguard() runs on UE_CT {
[] g_Tguard.timeout {
	setverdict(fail, "Tguard timeout after ", g_pars.tguard);
	self.stop;
	}
}

/* first function executed in UE_CT; creates LLC context, registers with BSSGP, starts Tguard */
function f_handler_init(void_fn fn, charstring id, UE_Pars pars) runs on UE_CT {
	g_pars := pars;
	llc := f_llc_create(false);
	f_bssgp_client_register(g_pars.imsi, g_pars.tlli);
	g_Tguard.start(g_pars.tguard);
	activate(as_ue_tguard());

	log(id, " Waiting for BVC-UNBLOCK");
	timer T := 15.0;
	T.start;
	alt {
	[] BSSGP[0].receive(BssgpStatusIndication:{*,?,BVC_S_UNBLOCKED}) { }
	[] BSSGP[0].receive { repeat; }
	[] T.timeout {
		setverdict(fail, id, " Timeout waiting for BVC-UNBLOCK");
		self.stop;
		}
	}

	log (id, " Entering main loop");
	fn.apply(id);
	log (id, "Leaving main loop");
	f_bssgp_client_unregister(g_pars.imsi);
}

/* start a single UE component; connect it to BSSGP */
function f_start_ue(void_fn fn, charstring id, BssgpBvcConfig bvc, integer imsi_suffix, BSSGP_BVC_CT bvc_comp, float t_guard := 40.0)
runs on test_CT return UE_CT
{
	var UE_CT ue_comp;
	var UE_Pars ue_pars := {
		imsi := f_gen_imsi(imsi_suffix),
		tlli := f_gprs_tlli_random(),
		tguard := t_guard,
		bvci := bvc.bvci,
		cell_id := bvc.cell_id
	};

	ue_comp := UE_CT.create(id);
	connect(ue_comp:BSSGP[0], bvc_comp:BSSGP_SP);
	connect(ue_comp:BSSGP_SIG[0], bvc_comp:BSSGP_SP_SIG);
	connect(ue_comp:BSSGP_PROC[0], bvc_comp:BSSGP_PROC);
	ue_comp.start(f_handler_init(fn, id, ue_pars));

	return ue_comp;
}


/* main test case body function; start Gb instances, start UE_CTs on top; wait for termination */
private function f_tc_body(void_fn ue_fn, integer ue_per_bvc := mp_num_ue_in_bvc,
			   float delay_between_ue := 0.005, float ue_tguard := 40.0) runs on test_CT {
	var ro_ue ues := {};

	for (var integer i := 0; i < lengthof(mp_nsconfig); i := i+1) {
		g_gb[i].cfg := {
			nsei := mp_nsconfig[i].nsei,
			sgsn_role := false,
			bvc := { }
		};
		/* create 'mp_num_bvc' number of BVCs */
		for (var integer j := 0; j < mp_num_bvc; j := j+1) {
			g_gb[i].cfg.bvc := g_gb[i].cfg.bvc & { f_gen_bvc(i * 1000, j) };
		}
		log("Initializing Gb interface ", i, ": NSEI=", g_gb[i].cfg.nsei);
		f_init_gb(g_gb[i], "gb", i);
	}

	for (var integer i := 0; i < lengthof(mp_nsconfig); i := i+1) {
		for (var integer j := 0; j < mp_num_bvc; j := j+1) {
			var BSSGP_BVC_CT bvc_comp := f_bssgp_get_bvci_ct(g_gb[i].cfg.bvc[j].bvci, BSSGP_PROC[i]);
			for (var integer k := 0; k < ue_per_bvc; k := k+1) {
				var charstring id := "gb" & int2str(i) & "-bvc" & int2str(g_gb[i].cfg.bvc[j].bvci) & "-UEsim" & int2str(k);
				var UE_CT ue;
				ue := f_start_ue(ue_fn, id, g_gb[i].cfg.bvc[j], i*10000+j*100+k, bvc_comp,
ue_tguard);
				ues := ues & { ue };
				/* a bit of staggering to ensure the timers above don't run all at the same time */
				f_sleep(delay_between_ue);
				/* FIXME: as the BSSGP emulation is already running, we must not
				 * take too long to start the UE components.  If we do, the
				 * BVC_S_UNBLOCKED notification will arrive before the components
				 * all are running, meaning we never get that one :( */
			}
		}
	}

	/* wait for all UE components to terminate */
	for (var integer i := 0; i < lengthof(ues); i := i + 1) {
		ues[i].done;
	}
	setverdict(pass);
}

private function f_ul_ud(charstring id) runs on UE_CT
{
	for (var integer num_pkts := 0; num_pkts < 50; num_pkts := num_pkts + 1) {
		var integer ran_index := 0;
		//BSSGP[ran_index].send(ts_BSSGP_UL_UD(g_pars.tlli, g_pars.bssgp_cell_id[ran_index], llc_enc));
		BSSGP[ran_index].send(ts_LLC_UI(f_rnd_octstring(512), '0000'B, '1'B, 0))
		f_sleep(0.5);
		/* 512 bytes + 32 bytes HDR every 0.5s (1088/s) means about 8704/s per UE */
		/* at 100 UE that ends up about 870 kBps */
	}
}
/* Generate uplink-unitdata traffic */
testcase TC_ul_ud() runs on test_CT
{
	f_tc_body(refers(f_ul_ud));
}


/* test bring-up of all BVCs */
private function f_pass(charstring id) runs on UE_CT
{
	setverdict(pass);
}
testcase TC_bvc_bringup() runs on test_CT
{
	f_tc_body(refers(f_pass), ue_per_bvc := 1, ue_tguard := 20.0);
}


private function f_ul2dl_ud(charstring id) runs on UE_CT
{
	var integer max_llc_payload_len := mp_ns_mtu - c_LLC_BSSGP_NS_overhead;

	for (var integer num_pkts := 0; num_pkts < 50; num_pkts := num_pkts + 1) {
		var integer ran_index := 0;
		var template (value) PDU_LLC llc_tx;
		var template (present) PDU_LLC llc_rx_exp;
		var octetstring llc_payload := f_rnd_octstring(f_rnd_int(max_llc_payload_len));
		var PDU_LLC llc_rx;
		timer T := 5.0;

		/* SAPI '0010'B is looped back by FRNET_Tests.ttcn */
		llc_tx := ts_LLC_UI(llc_payload, '0010'B, '1'B, 0);
		llc_rx_exp := llc_tx;
		llc_rx_exp.pDU_LLC_UI.fCS := ?;

		//BSSGP[ran_index].send(ts_BSSGP_UL_UD(g_pars.tlli, g_pars.cell_id, llc_enc));
		BSSGP[ran_index].send(llc_tx);
		T.start;
		alt {
		[] BSSGP[ran_index].receive(llc_rx_exp) -> value llc_rx { }
		[] BSSGP[ran_index].receive(PDU_LLC:?) ->  value llc_rx {
			setverdict(fail, "Unexpected LLC: ", llc_rx);
			break;
			}
		[] T.timeout {
			setverdict(fail, "Timeout waiting for ", llc_rx_exp);
			break;
			}
		}
		//f_sleep(0.1);
		/* 512 bytes + 32 bytes HDR every 0.5s (1088/s) means about 8704/s per UE */
		/* at 100 UE that ends up about 870 kBps */
	}
}
/* Generate uplink-unitdata traffic */
testcase TC_ul2dl_ud() runs on test_CT
{
	f_tc_body(refers(f_ul2dl_ud), ue_tguard := 100.0);
}


control {
	execute( TC_bvc_bringup() );
	execute( TC_ul_ud() );
	execute( TC_ul2dl_ud() );
}

}