aboutsummaryrefslogtreecommitdiffstats
path: root/library/GSM_SystemInformation.ttcn
blob: ab40e0047acbfbf9cbdb9d26966877c2cdb98a0e (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
/* Encoding/Decoding routines for GSM System Information messages
 * according to 3GPP TS 44.018 Version 12.3.0 Release 12
 *
 * (C) 2018 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
 */

module GSM_SystemInformation {

	import from General_Types all;
	import from GSM_Types all;
	import from GSM_RR_Types all;
	import from GSM_RestOctets all;
	import from Osmocom_Types all;

	type union ArfcnOrMaio {
		uint12_t	arfcn,
		MaioHsn		maio_hsn
	} with { variant "" };

	/* 24.008 10.5.1.1 */
	type uint16_t SysinfoCellIdentity;

	/* 44.018 10.5.2.1b */
	type octetstring CellChannelDescription with { variant "FIELDLENGTH(16)" };

	/* 44.018 10.5.2.3 */
	type enumerated CellOptions_DTX {
		MS_MAY_USE_UL_DTX	('00'B),
		MS_SHALL_USE_UL_DTX	('01'B),
		MS_SHALL_NOT_USE_UL_DTX	('10'B)
	} with { variant "FIELDLENGTH(2)" };
	type record CellOptions {
		boolean		dn_ind,
		boolean		pwrc,
		CellOptions_DTX	dtx,
		uint4_t		radio_link_tout_div4
	} with { variant "" };

	/* 44.018 10.5.2.3a */
	type record CellOptionsSacch {
		BIT1		dtx_ext,
		boolean		pwrc,
		BIT2		dtx,
		BIT4		radio_link_timeout
	} with { variant "" };

	/* 44.018 10.5.2.4 */
	type record CellSelectionParameters {
		uint3_t		cell_resel_hyst_2dB,
		uint5_t		ms_txpwr_max_cch,
		BIT1		acs,
		boolean		neci,
		uint6_t		rxlev_access_min
	} with { variant "" };

	/* 44.018 10.5.2.11 */
	type enumerated CtrlChanDesc_CC {
		CCHAN_DESC_1CCCH_NOT_COMBINED	('000'B),
		CCHAN_DESC_1CCCH_COMBINED	('001'B),
		CCHAN_DESC_2CCCH_NOT_COMBINED	('010'B),
		CCHAN_DESC_3CCCH_NOT_COMBINED	('100'B),
		CCHAN_DESC_4CCCH_NOT_COMBINED	('110'B)
	} with { variant "FIELDLENGTH(3)" };
	type enumerated CBQ3 {
		CBQ3_IU_MODE_NOT_SUPPORTED	('00'B),
		CBQ3_IU_MODE_MS_BARRED		('01'B),
		CBQ3_IU_MODE_NOT_BARRED		('10'B)
	} with { variant "FIELDLENGTH(2)" };
	type record ControlChannelDescription {
		boolean		msc_r99,
		boolean		att,
		uint3_t		bs_ag_blks_res,
		CtrlChanDesc_CC	ccch_conf,
		boolean		si22ind,
		CBQ3		cbq3,
		BIT2		spare,
		uint3_t		bs_pa_mfrms, /* off by 2 */
		uint8_t		t3212
	} with { variant "" };

	template ControlChannelDescription t_ControlChannelDescription := { ?, ?, ?, ?, ?, ?, '00'B, ?, ? };

	/* 44.018 10.5.2.22 */
	type octetstring NeighbourCellDescription with { variant "FIELDLENGTH(16)" };

	/* 44.018 10.5.2.22a */
	type octetstring NeighbourCellDescription2 with { variant "FIELDLENGTH(16)" };

	type bitstring AccessControlClass with { variant "FIELDLENGTH(16), BYTEORDER(last)" };

	/* 44.018 10.5.2.29 */
	type enumerated RachCtrlPar_MR {
		RACH_MAX_RETRANS_1	('00'B),
		RACH_MAX_RETRANS_2	('01'B),
		RACH_MAX_RETRANS_4	('10'B),
		RACH_MAX_RETRANS_7	('11'B)
	} with { variant "FIELDLENGTH(2)" };
	type record RachControlParameters {
		RachCtrlPar_MR	max_retrans,
		BIT4		tx_integer,
		boolean		cell_barr_access,
		boolean		re_not_allowed,
		AccessControlClass acc
	} with { variant (acc) "FIELDLENGTH(16)" };
	template (value) RachControlParameters
	ts_RachControlParameters(RachCtrlPar_MR max_retrans := RACH_MAX_RETRANS_1,
				 BIT4 tx_integer := '1111'B, boolean cell_barr_access := false,
				 boolean re_not_allowed := false,
				 AccessControlClass acc := '0000000000000000'B)
	:= {
		max_retrans := max_retrans,
		tx_integer := tx_integer,
		cell_barr_access := cell_barr_access,
		re_not_allowed := re_not_allowed,
		acc := acc
	}

	/* 44.018 9.1.31 */
	type record SystemInformationType1 {
		CellChannelDescription	cell_chan_desc,
		RachControlParameters	rach_control,
		RestOctets		rest_octets length(0..1)
	} with { variant "" };

	/* 44.018 9.1.32 */
	type record SystemInformationType2 {
		NeighbourCellDescription bcch_freq_list,
		BIT8			ncc_permitted,
		RachControlParameters	rach_control
	} with { variant "" };

	/* 44.018 9.1.33 */
	type record SystemInformationType2bis {
		NeighbourCellDescription	extd_bcch_freq_list,
		RachControlParameters		rach_control,
		RestOctets			rest_octets length(0..1)
	} with { variant "" };

	/* 44.018 9.1.34 */
	type record SystemInformationType2ter {
		NeighbourCellDescription2	extd_bcch_freq_list,
		RestOctets			rest_octets length(0..4)
	} with { variant "" };

	type record SystemInformationType2quater {
		SI2quaterRestOctets	rest_octets
	} with { variant "" };

	/* 44.018 9.1.35 */
	type record SystemInformationType3 {
		SysinfoCellIdentity		cell_id,
		LocationAreaIdentification	lai,
		ControlChannelDescription	ctrl_chan_desc,
		CellOptions			cell_options,
		CellSelectionParameters		cell_sel_par,
		RachControlParameters		rach_control,
		SI3RestOctets			rest_octets
	} with { variant "" };

	template SystemInformationType3 t_SI3 := {
		cell_id := ?,
		lai := ?,
		ctrl_chan_desc := t_ControlChannelDescription,
		cell_options := ?,
		cell_sel_par := ?,
		rach_control := ?,
		rest_octets := ?
	};


	/* 44.018 9.1.36 */
	type record SystemInformationType4 {
		LocationAreaIdentification	lai,
		CellSelectionParameters		cell_sel_par,
		RachControlParameters		rach_control,
		ChannelDescriptionTV		cbch_chan_desc optional,
		MobileAllocationTLV		cbch_mobile_alloc optional,
		SI4RestOctets			rest_octets /* see 10.5.2.35 */
	} with { variant "TAG(cbch_chan_desc, iei = '64'O; cbch_mobile_alloc, iei = '72'O)" };

	/* 44.018 9.1.37 */
	type record SystemInformationType5 {
		NeighbourCellDescription	bcch_freq_list
	} with { variant "" };

	/* 44.018 9.1.38 */
	type record SystemInformationType5bis {
		NeighbourCellDescription	extd_bcch_freq_list
	} with { variant "" };

	/* 44.018 9.1.39 */
	type record SystemInformationType5ter {
		NeighbourCellDescription2	extd_bcch_freq_list
	} with { variant "" };

	/* 44.018 9.1.40 */
	type record SystemInformationType6 {
		SysinfoCellIdentity		cell_id,
		LocationAreaIdentification	lai,
		CellOptionsSacch		cell_options,
		BIT8				ncc_permitted,
		RestOctets			rest_octets length(0..7)
	} with { variant "" };

	/* 44.018 9.1.43a */
	type record SystemInformationType13 {
		SI13RestOctets			rest_octets
	} with { variant "" };

	type union SystemInformationUnion {
		SystemInformationType1		si1,
		SystemInformationType2		si2,
		SystemInformationType2bis	si2bis,
		SystemInformationType2ter	si2ter,
		SystemInformationType2quater	si2quater,
		SystemInformationType3		si3,
		SystemInformationType4		si4,
		SystemInformationType5		si5,
		SystemInformationType5bis	si5bis,
		SystemInformationType5ter	si5ter,
		SystemInformationType6		si6,
		SystemInformationType13		si13,
		octetstring			other
	} with { variant "" };

	type record SystemInformation {
		RrHeader			header,
		SystemInformationUnion		payload
	} with { variant (payload) "CROSSTAG(si1, header.message_type = SYSTEM_INFORMATION_TYPE_1;
			      si2, header.message_type = SYSTEM_INFORMATION_TYPE_2;
			      si2bis, header.message_type = SYSTEM_INFORMATION_TYPE_2bis;
			      si2ter, header.message_type = SYSTEM_INFORMATION_TYPE_2ter;
			      si2quater, header.message_type = SYSTEM_INFORMATION_TYPE_2quater;
			      si3, header.message_type = SYSTEM_INFORMATION_TYPE_3;
			      si4, header.message_type = SYSTEM_INFORMATION_TYPE_4;
			      si5, header.message_type = SYSTEM_INFORMATION_TYPE_5;
			      si5bis, header.message_type = SYSTEM_INFORMATION_TYPE_5bis;
			      si5ter, header.message_type = SYSTEM_INFORMATION_TYPE_5ter;
			      si6, header.message_type = SYSTEM_INFORMATION_TYPE_6;
			      si13, header.message_type = SYSTEM_INFORMATION_TYPE_13;
			      other, OTHERWISE;
			)" };

	external function enc_SystemInformationNoPad(in SystemInformation si) return octetstring
		with { extension "prototype(convert) encode(RAW)" };
	external function dec_SystemInformation(in octetstring stream) return SystemInformation
		with { extension "prototype(convert) decode(RAW)" };

	/* Due to a buggy nature of TITAN's padding attributes, we have to apply padding manually. */
	function enc_SystemInformation(in SystemInformation si) return octetstring
	{
		var octetstring si_enc := enc_SystemInformationNoPad(si);

		/* Resulting message length depends on SI Type */
		select (si.header.message_type) {
		case (SYSTEM_INFORMATION_TYPE_5,
		      SYSTEM_INFORMATION_TYPE_5bis,
		      SYSTEM_INFORMATION_TYPE_5ter) {
			/* SACCH: no Rest Octets, return 'as-is' */
			return si_enc;
			}
		case (SYSTEM_INFORMATION_TYPE_6) {
			/* SACCH: pad to 19 octets, leave room for L1/LAPDm headers */
			return f_pad_oct(si_enc, 19, '2B'O);
			}
		case else {
			/* BCCH: pad to 23 octets */
			return f_pad_oct(si_enc, 23, '2B'O);
			}
		}
	}

	external function dec_SystemInformationSafeBT(in octetstring stream, out SystemInformation si)
		return integer /* Decoding result: successful (0) or unsuccessful (1) */
		with { extension "prototype(backtrack) decode(RAW)" };

	/* Some types of System Information (mostly the Rest Octets) are not fully implemented,
	 * so calling the generic dec_SystemInformation() may result in a DTE.  This function
	 * additionally checks RR Protocol Discriminator, and should be used in the most cases. */
	function dec_SystemInformationSafe(in octetstring stream, out SystemInformation si)
	return integer {
		/* Try to decode a given octetstring as System Information */
		if (dec_SystemInformationSafeBT(stream, si) != 0) {
			log("Failed to decode (RR) System Information: ", stream);
			return 1;
		}

		/* Check the protocol discriminator (we expect RR messages) */
		if (si.header.rr_protocol_discriminator != bit2int('0110'B)) {
			log("Protocol discriminator is not RR (!= '0110'B): ",
			    si.header.rr_protocol_discriminator);
			return 1;
		}

		return 0;
	}

	/* Generate a NeighbourCellDescription as per 44.018 10.5.2.22 */
	function f_gen_NeighbourCellDescription(bitstring arfcn_mask /*length(1024)*/) return NeighbourCellDescription {
		/* FIXME: so far only bitmap 0 is supported */
		var bitstring dst := '0000'B;
		for (var integer i := 123; i > 0; i := i -1) {
			dst := dst & arfcn_mask[i];
		}
		return bit2oct(dst);
	}

} with { encode "RAW"; variant "FIELDORDER(msb)" }