blob: b911c75ebd37f2c55a4e49550067f2fe666c55e8 [file] [log] [blame]
Harald Welte43e060a2017-07-30 22:38:03 +02001#include "RLCMAC_Types.hh"
2#include "GSM_Types.hh"
3/* Decoding of TS 44.060 GPRS RLC/MAC blocks, portions requiring manual functions
4 * beyond what TITAN RAW coder can handle internally.
5 *
6 * (C) 2017 by Harald Welte <laforge@gnumonks.org>
7 */
8
9namespace RLCMAC__Types {
10
11OCTETSTRING enc__RlcmacDlDataBlock(const RlcmacDlDataBlock& si)
12{
13 RlcmacDlDataBlock in = si;
14 OCTETSTRING ret_val;
15 TTCN_Buffer ttcn_buffer;
16 int i;
17
18 /* Fix 'e' bit of initial header based on following blocks */
Harald Welte244cd8a2017-08-26 09:25:20 +020019 if (!in.blocks().is_bound() ||
20 (in.blocks().size_of() == 1 && !in.blocks()[0].hdr().is_bound()))
Harald Welte43e060a2017-07-30 22:38:03 +020021 in.mac__hdr().hdr__ext().e() = true;
22 else
23 in.mac__hdr().hdr__ext().e() = false;
24
25 /* use automatic/generated decoder for header */
26 in.mac__hdr().encode(DlMacDataHeader_descr_, ttcn_buffer, TTCN_EncDec::CT_RAW);
27
28 /* Add LI octets, if any */
29 if (in.blocks().is_bound() &&
30 (in.blocks().size_of() != 1 || in.blocks()[0].hdr().is_bound())) {
31 /* first write LI octets */
32 for (i = 0; i < in.blocks().size_of(); i++) {
33 /* fix the 'E' bit in case it is not clear */
34 if (i < in.blocks().size_of()-1)
Harald Welte060e27a2018-03-03 20:38:19 +010035 in.blocks()[i].hdr()().e() = false;
Harald Welte43e060a2017-07-30 22:38:03 +020036 else
Harald Welte060e27a2018-03-03 20:38:19 +010037 in.blocks()[i].hdr()().e() = true;
Harald Welte43e060a2017-07-30 22:38:03 +020038 in.blocks()[i].hdr().encode(LlcBlockHdr_descr_, ttcn_buffer, TTCN_EncDec::CT_RAW);
39 }
40 }
41 if (in.blocks().is_bound()) {
42 for (i = 0; i < in.blocks().size_of(); i++) {
43 if (!in.blocks()[i].is_bound())
44 continue;
45 ttcn_buffer.put_string(in.blocks()[i].payload());
46 }
47 }
48
49 ttcn_buffer.get_string(ret_val);
50 return ret_val;
51}
52
53RlcmacDlDataBlock dec__RlcmacDlDataBlock(const OCTETSTRING& stream)
54{
55 RlcmacDlDataBlock ret_val;
56 TTCN_Buffer ttcn_buffer(stream);
57 int num_llc_blocks = 0;
58
59 /* use automatic/generated decoder for header */
60 ret_val.mac__hdr().decode(DlMacDataHeader_descr_, ttcn_buffer, TTCN_EncDec::CT_RAW);
61
62 /* optional extension octets, containing LI+M+E of Llc blocks */
63 if (ret_val.mac__hdr().hdr__ext().e() == false) {
64 /* extension octet follows, i.e. optional Llc length octets */
65 while (1) {
66 /* decode one more extension octet with LlcBlocHdr inside */
67 LlcBlock lb;
68 lb.hdr().decode(LlcBlockHdr_descr_, ttcn_buffer, TTCN_EncDec::CT_RAW);
69 ret_val.blocks()[num_llc_blocks++] = lb;
70
71 /* if E == '1'B, we can proceed further */
Harald Welte060e27a2018-03-03 20:38:19 +010072 if (lb.hdr()().e() == true)
Harald Welte43e060a2017-07-30 22:38:03 +020073 break;
74 }
75 }
76
77 /* RLC blocks at end */
78 if (ret_val.mac__hdr().hdr__ext().e() == true) {
79 LlcBlock lb;
80 unsigned int length = ttcn_buffer.get_read_len();
81 /* LI not present: The Upper Layer PDU that starts with the current RLC data block either
82 * fills the current RLC data block precisely or continues in the following in-sequence RLC
83 * data block */
84 lb.payload() = OCTETSTRING(length, ttcn_buffer.get_read_data());
85 ttcn_buffer.increase_pos(length);
86 ret_val.blocks()[0] = lb;
87 } else {
88 if (ret_val.blocks().is_bound()) {
89 for (int i = 0; i < ret_val.blocks().size_of(); i++) {
Harald Welte060e27a2018-03-03 20:38:19 +010090 unsigned int length = ret_val.blocks()[i].hdr()().length__ind();
Harald Welte43e060a2017-07-30 22:38:03 +020091 if (length > ttcn_buffer.get_read_len())
92 length = ttcn_buffer.get_read_len();
93 ret_val.blocks()[i].payload() = OCTETSTRING(length, ttcn_buffer.get_read_data());
94 ttcn_buffer.increase_pos(length);
95 }
96 }
97 }
98
99 return ret_val;
100}
101
102
103OCTETSTRING enc__RlcmacUlDataBlock(const RlcmacUlDataBlock& si)
104{
105 RlcmacUlDataBlock in = si;
106 OCTETSTRING ret_val;
107 TTCN_Buffer ttcn_buffer;
108 int i;
109
Harald Welte060e27a2018-03-03 20:38:19 +0100110 if (!in.blocks().is_bound()) {
111 /* we don't have nay blocks: Add length value (zero) */
112 in.mac__hdr().e() = false; /* E=0: extension octet follows */
113 } else if (in.blocks().size_of() == 1 && in.blocks()[0].hdr() == OMIT_VALUE) {
114 /* If there's only a single block, and that block has no HDR value defined, */
115 in.mac__hdr().e() = true; /* E=0: extension octet follows */
116 } else {
117 /* Length value */
Harald Welte43e060a2017-07-30 22:38:03 +0200118 in.mac__hdr().e() = false;
Harald Welte060e27a2018-03-03 20:38:19 +0100119 }
Harald Welte43e060a2017-07-30 22:38:03 +0200120
121 /* Fix other presence indications */
Harald Welte2072ab62017-07-31 18:33:35 +0200122 in.mac__hdr().tlli__ind() = in.tlli().is_bound() && in.tlli() != OMIT_VALUE;
123 in.mac__hdr().pfi__ind() = in.pfi().is_bound() && in.pfi() != OMIT_VALUE;
Harald Welte43e060a2017-07-30 22:38:03 +0200124
Harald Welte060e27a2018-03-03 20:38:19 +0100125 /* use automatic/generated encoder for header */
Harald Welte43e060a2017-07-30 22:38:03 +0200126 in.mac__hdr().encode(UlMacDataHeader_descr_, ttcn_buffer, TTCN_EncDec::CT_RAW);
127
Harald Welte060e27a2018-03-03 20:38:19 +0100128 if (in.mac__hdr().e() == false) {
129 /* Add LI octets, if any */
130 if (!in.blocks().is_bound()) {
131 ttcn_buffer.put_c(0x01); /* M=0, E=1 LEN=0 */
132 } else {
133 for (i = 0; i < in.blocks().size_of(); i++) {
134#if 0
135 /* check for penultimate block */
136 if (i == in.blocks().size_of()-2) {
137 /* if last block has no header, no more LI */
138 if (in.blocks()[i+1].hdr() == OMIT_VALUE) {
139 in.blocks()[i].hdr()().more() = true;
140 } else {
141 /* header present, we have to encode LI */
142 in.blocks()[i].hdr()().more() = false;
143 in.blocks()[i].hdr()().length__ind() =
144 in.blocks()[i+1].payload().lengthof();
145 }
146 } else if (i < in.blocks().size_of()-2) {
147 /* one of the first blocks, before the penultimate or last */
148 in.blocks()[i].hdr()().e() = false; /* LI present */
149 /* re-compute length */
150 in.blocks()[i].hdr()().length__ind() =
151 in.blocks()[i+1].payload().lengthof();
152 }
153 /* Encode LI octet if E=0 */
154 }
155#endif
156 if (in.blocks()[i].hdr() != OMIT_VALUE) {
157 in.blocks()[i].hdr()().encode(LlcBlockHdr_descr_, ttcn_buffer,
158 TTCN_EncDec::CT_RAW);
159 }
160 }
Harald Welte43e060a2017-07-30 22:38:03 +0200161 }
162 }
163
164 if (in.mac__hdr().tlli__ind()) {
Harald Welteacc93ab2018-03-02 21:39:09 +0100165 ttcn_buffer.put_string(in.tlli());
Harald Welte43e060a2017-07-30 22:38:03 +0200166 }
167
168 if (in.mac__hdr().pfi__ind()) {
169 in.pfi().encode(RlcmacUlDataBlock_pfi_descr_, ttcn_buffer, TTCN_EncDec::CT_RAW);
170 }
171
172 if (in.blocks().is_bound()) {
173 for (i = 0; i < in.blocks().size_of(); i++) {
174 if (!in.blocks()[i].is_bound())
175 continue;
176 ttcn_buffer.put_string(in.blocks()[i].payload());
177 }
178 }
179
180 ttcn_buffer.get_string(ret_val);
181 return ret_val;
182}
183
184RlcmacUlDataBlock dec__RlcmacUlDataBlock(const OCTETSTRING& stream)
185{
186 RlcmacUlDataBlock ret_val;
187 TTCN_Buffer ttcn_buffer(stream);
188 int num_llc_blocks = 0;
189
190 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);
191 TTCN_Logger::log_event_str("==================================\n"
192 "dec_RlcmacUlDataBlock(): Stream before decoding: ");
193 stream.log();
194 TTCN_Logger::end_event();
195
196 /* use automatic/generated decoder for header */
197 ret_val.mac__hdr().decode(UlMacDataHeader_descr_, ttcn_buffer, TTCN_EncDec::CT_RAW);
198
199 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);
200 TTCN_Logger::log_event_str("dec_RlcmacUlDataBlock(): Stream after decoding hdr: ");
201 ttcn_buffer.log();
202 TTCN_Logger::end_event();
203 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);
204 TTCN_Logger::log_event_str("dec_RlcmacUlDataBlock(): ret_val after decoding hdr: ");
205 ret_val.log();
206 TTCN_Logger::end_event();
207
208 /* Manually decoder remainder of ttcn_buffer, containing optional header octets,
209 * optional tlli, optional pfi and LLC Blocks */
210
211 /* optional extension octets, containing LI+M+E of Llc blocks */
212 if (ret_val.mac__hdr().e() == false) {
213 /* extension octet follows, i.e. optional Llc length octets */
214 while (1) {
215 /* decode one more extension octet with LlcBlocHdr inside */
216 LlcBlock lb;
217 lb.hdr().decode(LlcBlockHdr_descr_, ttcn_buffer, TTCN_EncDec::CT_RAW);
218 ret_val.blocks()[num_llc_blocks++] = lb;
219
220 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);
221 TTCN_Logger::log_event_str("dec_RlcmacUlDataBlock(): Stream after decoding ExtOct: ");
222 ttcn_buffer.log();
223 TTCN_Logger::end_event();
224 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);
225 TTCN_Logger::log_event_str("dec_RlcmacUlDataBlock(): ret_val after decoding ExtOct: ");
226 ret_val.log();
227 TTCN_Logger::end_event();
228
229 /* if E == '1'B, we can proceed further */
Harald Welte060e27a2018-03-03 20:38:19 +0100230 if (lb.hdr()().e() == true)
Harald Welte43e060a2017-07-30 22:38:03 +0200231 break;
232 }
233 }
234
235 /* parse optional TLLI */
236 if (ret_val.mac__hdr().tlli__ind()) {
Harald Welteacc93ab2018-03-02 21:39:09 +0100237 ret_val.tlli() = OCTETSTRING(4, ttcn_buffer.get_read_data());
Harald Welte43e060a2017-07-30 22:38:03 +0200238 ttcn_buffer.increase_pos(4);
239 }
240 /* parse optional PFI */
241 if (ret_val.mac__hdr().pfi__ind()) {
242 ret_val.pfi().decode(RlcmacUlDataBlock_pfi_descr_, ttcn_buffer, TTCN_EncDec::CT_RAW);
243 }
244
245 /* RLC blocks at end */
246 if (ret_val.mac__hdr().e() == true) {
247 LlcBlock lb;
248 unsigned int length = ttcn_buffer.get_read_len();
249 /* LI not present: The Upper Layer PDU that starts with the current RLC data block either
250 * fills the current RLC data block precisely or continues in the following in-sequence RLC
251 * data block */
252 lb.payload() = OCTETSTRING(length, ttcn_buffer.get_read_data());
253 ttcn_buffer.increase_pos(length);
254 ret_val.blocks()[0] = lb;
255 } else {
256 if (ret_val.blocks().is_bound()) {
257 for (int i = 0; i < ret_val.blocks().size_of(); i++) {
Harald Welte060e27a2018-03-03 20:38:19 +0100258 unsigned int length = ret_val.blocks()[i].hdr()().length__ind();
Harald Welte43e060a2017-07-30 22:38:03 +0200259 if (length > ttcn_buffer.get_read_len())
260 length = ttcn_buffer.get_read_len();
261 ret_val.blocks()[i].payload() = OCTETSTRING(length, ttcn_buffer.get_read_data());
262 ttcn_buffer.increase_pos(length);
263 }
264 }
265 }
266
267 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);
268 TTCN_Logger::log_event_str("dec_RlcmacUlDataBlock(): Stream before return: ");
269 ttcn_buffer.log();
270 TTCN_Logger::end_event();
271 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);
272 TTCN_Logger::log_event_str("dec_RlcmacUlDataBlock(): ret_val before return: ");
273 ret_val.log();
274 TTCN_Logger::end_event();
275
276 return ret_val;
277}
278
Harald Welte78a1af62017-07-31 17:33:56 +0200279OCTETSTRING enc__RlcmacUlBlock(const RlcmacUlBlock& si)
280{
281 if (si.ischosen(RlcmacUlBlock::ALT_data))
282 return enc__RlcmacUlDataBlock(si.data());
283 else
284 return enc__RlcmacUlCtrlBlock(si.ctrl());
285}
286
287OCTETSTRING enc__RlcmacDlBlock(const RlcmacDlBlock& si)
288{
289 if (si.ischosen(RlcmacDlBlock::ALT_data))
290 return enc__RlcmacDlDataBlock(si.data());
291 else
292 return enc__RlcmacDlCtrlBlock(si.ctrl());
293}
294
295
296RlcmacUlBlock dec__RlcmacUlBlock(const OCTETSTRING& stream)
297{
298 RlcmacUlBlock ret_val;
299 unsigned char pt = stream[0].get_octet() >> 6;
300
301 if (pt == MacPayloadType::MAC__PT__RLC__DATA)
302 ret_val.data() = dec__RlcmacUlDataBlock(stream);
303 else
304 ret_val.ctrl() = dec__RlcmacUlCtrlBlock(stream);
305
306 return ret_val;
307}
308
309RlcmacDlBlock dec__RlcmacDlBlock(const OCTETSTRING& stream)
310{
311 RlcmacDlBlock ret_val;
312 unsigned char pt = stream[0].get_octet() >> 6;
313
314 if (pt == MacPayloadType::MAC__PT__RLC__DATA)
315 ret_val.data() = dec__RlcmacDlDataBlock(stream);
316 else
317 ret_val.ctrl() = dec__RlcmacDlCtrlBlock(stream);
318
319 return ret_val;
320}
321
Harald Welte43e060a2017-07-30 22:38:03 +0200322
323} // namespace