blob: 6bcf55d7bb5a7d222e9c4e34e85b837031f8df42 [file] [log] [blame]
Ivan Kluchnikov5c2f9fb2012-02-05 02:27:17 +04001/*GPRSSocket.cpp
2 *
3 * Copyright (C) 2011 Ivan Klyuchnikov
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <Sockets.h>
21#include <Threads.h>
22#include <BitVector.h>
Ivan Kluchnikov34506402012-02-20 15:24:16 +040023#include <gsmtap.h>
Ivan Kluchnikov5c2f9fb2012-02-05 02:27:17 +040024#include "GPRSSocket.h"
Ivan Kluchnikov5c2f9fb2012-02-05 02:27:17 +040025#include "bssgp.h"
26
27#define MAX_UDP_LENGTH 1500
28
29#define RLCMAC_DATA_BLOCK 0
30#define RLCMAC_CONTROL_BLOCK 1
31
32// TODO: We should take ports and IP from config.
33UDPSocket GPRSRLCMACSocket(5070, "127.0.0.1", 5934);
Ivan Kluchnikov34506402012-02-20 15:24:16 +040034UDPSocket GSMTAPSocket(5077, "127.0.0.1", 4729);
35
36void sendToGSMTAP(uint8_t * data, unsigned len)
37{
38 char buffer[MAX_UDP_LENGTH];
39 int ofs = 0;
40
41 // Build header
42 struct gsmtap_hdr *header = (struct gsmtap_hdr *)buffer;
43 header->version = 2;
44 header->hdr_len = sizeof(struct gsmtap_hdr) >> 2;
45 header->type = 0x08;
46 header->timeslot = 5;
47 header->arfcn = 0;
48 header->signal_dbm = 0;
49 header->snr_db = 0;
50 header->frame_number = 0;
51 header->sub_type = 0;
52 header->antenna_nr = 0;
53 header->sub_slot = 0;
54 header->res = 0;
55
56 ofs += sizeof(*header);
57
58 // Add frame data
59 unsigned j = 0;
60 for (unsigned i = ofs; i < len+ofs; i++)
61 {
62 buffer[i] = (char)data[j];
63 j++;
64 }
65 ofs += len;
66 // Write the GSMTAP packet
67 GSMTAPSocket.write(buffer, ofs);
68}
69
Ivan Kluchnikov5c2f9fb2012-02-05 02:27:17 +040070
71void sendToOpenBTS(BitVector * vector)
72{
73 char buffer[MAX_UDP_LENGTH];
74 int ofs = 0;
75 vector->pack((unsigned char*)&buffer[ofs]);
76 ofs += vector->size() >> 3;
77 COUT("Send to OpenBTS: " << *vector);
78 GPRSRLCMACSocket.write(buffer, ofs);
79}
80
81void writePDassignment(BitVector * dest, uint8_t TFI, uint32_t TLLI)
82{
83 // TODO We should use our implementation of encode RLC/MAC Control messages.
84 unsigned wp = 0;
85 dest->writeField(wp,0x1,2); // Payload Type
86 dest->writeField(wp,0x0,2); // Uplink block with TDMA framenumber
87 dest->writeField(wp,0x1,1); // Suppl/Polling Bit
88 dest->writeField(wp,0x1,3); // Uplink state flag
89 dest->writeField(wp,0x2,6); // MESSAGE TYPE
90 dest->writeField(wp,0x0,2); // Page Mode
91
92 dest->writeField(wp,0x0,1); // switch PERSIST_LEVEL: off
93 dest->writeField(wp,0x2,2); // switch TLLI : on
94 dest->writeField(wp,TLLI,32); // TLLI
95
96 dest->writeField(wp,0x0,1); // Message escape
97 dest->writeField(wp,0x0,2); // Medium Access Method: Dynamic Allocation
98 dest->writeField(wp,0x0,1); // RLC acknowledged mode
99
100 dest->writeField(wp,0x0,1); // the network establishes no new downlink TBF for the mobile station
101 dest->writeField(wp,0x1,8); // timeslot 7
102 dest->writeField(wp,0x1,8); // TIMING_ADVANCE_INDEX
103
104 dest->writeField(wp,0x0,1); // switch TIMING_ADVANCE_VALUE = off
105 dest->writeField(wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
106 dest->writeField(wp,0xC,4); // TIMING_ADVANCE_INDEX
107 dest->writeField(wp,0x7,3); // TIMING_ADVANCE_TIMESLOT_NUMBER
108
109 dest->writeField(wp,0x0,1); // switch POWER CONTROL = off
110 dest->writeField(wp,0x1,1); // Frequency Parameters information elements = present
111
112 dest->writeField(wp,0x2,3); // Training Sequence Code (TSC) = 2
113 dest->writeField(wp,0x1,2); // Indirect encoding struct = present
114 dest->writeField(wp,0x0,6); // MAIO
115 dest->writeField(wp,0xE,4); // MA_Number
116 dest->writeField(wp,0x8,4); // CHANGE_MARK_1 CHANGE_MARK_2
117
118 dest->writeField(wp,0x1,1); // switch TFI : on
119 dest->writeField(wp,0x14,5);// TFI
120
121 dest->writeField(wp,0x1,1); // Power Control Parameters IE = present
122 dest->writeField(wp,0x0,4); // ALPHA power control parameter
123 dest->writeField(wp,0x0,1); // switch GAMMA_TN0 = off
124 dest->writeField(wp,0x0,1); // switch GAMMA_TN1 = off
125 dest->writeField(wp,0x0,1); // switch GAMMA_TN2 = off
126 dest->writeField(wp,0x0,1); // switch GAMMA_TN3 = off
127 dest->writeField(wp,0x0,1); // switch GAMMA_TN4 = off
128 dest->writeField(wp,0x0,1); // switch GAMMA_TN5 = off
129 dest->writeField(wp,0x0,1); // switch GAMMA_TN6 = off
130 dest->writeField(wp,0x1,1); // switch GAMMA_TN7 = on
131 dest->writeField(wp,0x0,5); // GAMMA_TN7
132
133 dest->writeField(wp,0x0,1); // TBF Starting TIME IE not present
134 dest->writeField(wp,0x0,1); // Measurement Mapping struct not present
135}
136
Ivan Kluchnikov34506402012-02-20 15:24:16 +0400137void writePUassignment(BitVector * dest, uint8_t TFI, uint32_t TLLI)
138{
139 // TODO We should use our implementation of encode RLC/MAC Control messages.
140 unsigned wp = 0;
141 dest->writeField(wp,0x1,2); // Payload Type
142 dest->writeField(wp,0x0,2); // Uplink block with TDMA framenumber
143 dest->writeField(wp,0x1,1); // Suppl/Polling Bit
144 dest->writeField(wp,0x1,3); // Uplink state flag
145
146
147 dest->writeField(wp,0xa,6); // MESSAGE TYPE
148
149 dest->writeField(wp,0x0,2); // Page Mode
150
151 dest->writeField(wp,0x0,1); // switch PERSIST_LEVEL: off
152 dest->writeField(wp,0x2,2); // switch TLLI : on
153 dest->writeField(wp,TLLI,32); // TLLI
154
155 dest->writeField(wp,0x0,1); // Message escape
156 dest->writeField(wp,0x0,2); // CHANNEL_CODING_COMMAND
157 dest->writeField(wp,0x0,1); // TLLI_BLOCK_CHANNEL_CODING
158
159 dest->writeField(wp,0x1,1); // switch TIMING_ADVANCE_VALUE = on
160 dest->writeField(wp,0x0,6); // TIMING_ADVANCE_VALUE
161 dest->writeField(wp,0x0,1); // switch TIMING_ADVANCE_INDEX = off
162
163 dest->writeField(wp,0x0,1); // Frequency Parameters = off
164
165 dest->writeField(wp,0x1,2); // Dynamic Allocation = off
166
167 dest->writeField(wp,0x0,1); // Dynamic Allocation
168 dest->writeField(wp,0x0,1); // P0 = off
169
170 dest->writeField(wp,0x1,1); // USF_GRANULARITY
171 dest->writeField(wp,0x1,1); // switch TFI : on
172 dest->writeField(wp,TFI,5);// TFI
173
174 dest->writeField(wp,0x0,1); //
175 dest->writeField(wp,0x0,1); // TBF Starting Time = off
176 dest->writeField(wp,0x0,1); // Timeslot Allocation
177
178 dest->writeField(wp,0x0,5); // USF_TN 0 - 4
179 dest->writeField(wp,0x1,1); // USF_TN 5
180 dest->writeField(wp,0x1,3); // USF_TN 5
181 dest->writeField(wp,0x0,2); // USF_TN 6 - 7
182// dest->writeField(wp,0x0,1); // Measurement Mapping struct not present
183}
184
185void writeIARestOctetsDownlinkAssignment(BitVector * dest, uint8_t TFI, uint32_t TLLI)
186{
187 // GMS 04.08 10.5.2.37b 10.5.2.16
188 unsigned wp = 0;
189 dest->writeField(wp, 3, 2); // "HH"
190 dest->writeField(wp, 1, 2); // "01" Packet Downlink Assignment
191 dest->writeField(wp,TLLI,32); // TLLI
192 dest->writeField(wp,0x1,1); // switch TFI : on
193 dest->writeField(wp,TFI,5); // TFI
194 dest->writeField(wp,0x0,1); // RLC acknowledged mode
195 dest->writeField(wp,0x0,1); // ALPHA = present
196 //dest->writeField(wp,0x0,4); // ALPHA power control parameter
197 dest->writeField(wp,0x0,5); // GAMMA power control parameter
198 dest->writeField(wp,0x1,1); // Polling Bit
199 dest->writeField(wp,0x1,1); // TA_VALID ???
200 dest->writeField(wp,0x1,1); // switch TIMING_ADVANCE_INDEX = on
201 dest->writeField(wp,0xC,4); // TIMING_ADVANCE_INDEX
202 dest->writeField(wp,0x1,1); // TBF Starting TIME present
203 dest->writeField(wp,0xffff,16); // TBF Starting TIME (we should set it in OpenBTS)
204 dest->writeField(wp,0x0,1); // P0 not present
205}
206
Ivan Kluchnikov5c2f9fb2012-02-05 02:27:17 +0400207void writePUack(BitVector * dest, uint8_t TFI, uint32_t TLLI, unsigned CV, unsigned BSN)
208{
209 // TODO We should use our implementation of encode RLC/MAC Control messages.
210 unsigned wp = 0;
211 dest->writeField(wp,0x1,2); // payload
212 dest->writeField(wp,0x0,2); // Uplink block with TDMA framenumber
213 if (CV == 0) dest->writeField(wp,0x1,1); // Suppl/Polling Bit
214 else dest->writeField(wp,0x0,1); //Suppl/Polling Bit
215 dest->writeField(wp,0x1,3); // Uplink state flag
216
217 //dest->writeField(wp,0x0,1); // Reduced block sequence number
218 //dest->writeField(wp,BSN+6,5); // Radio transaction identifier
219 //dest->writeField(wp,0x1,1); // Final segment
220 //dest->writeField(wp,0x1,1); // Address control
221
222 //dest->writeField(wp,0x0,2); // Power reduction: 0
223 //dest->writeField(wp,TFI,5); // Temporary flow identifier
224 //dest->writeField(wp,0x1,1); // Direction
225
226 dest->writeField(wp,0x09,6); // MESSAGE TYPE
227 dest->writeField(wp,0x0,2); // Page Mode
228
229 dest->writeField(wp,0x0,2);
230 dest->writeField(wp,TFI,5); // Uplink TFI
231 dest->writeField(wp,0x0,1);
232
233 dest->writeField(wp,0x0,2); // CS1
234 if (CV == 0) dest->writeField(wp,0x1,1); // FINAL_ACK_INDICATION
235 else dest->writeField(wp,0x0,1); // FINAL_ACK_INDICATION
236 dest->writeField(wp,BSN+1,7); // STARTING_SEQUENCE_NUMBER
237 // RECEIVE_BLOCK_BITMAP
238 for (unsigned i=0; i<8; i++) {
239 dest->writeField(wp,0xff,8);
240 }
241 dest->writeField(wp,0x1,1); // CONTENTION_RESOLUTION_TLLI = present
242 dest->writeField(wp,TLLI,8*4);
243 dest->writeField(wp,0x00,4); //spare
244}
245
Ivan Kluchnikov34506402012-02-20 15:24:16 +0400246void RLCMACExtractData(uint8_t* tfi, uint32_t* tlli, RlcMacUplinkDataBlock_t * dataBlock, uint8_t* rlc_data, unsigned* dataIndex)
247{
248 unsigned blockDataLen = 0;
249 unsigned dataOctetNum = 0;
250
251 *tfi = dataBlock->TFI;
252 if (dataBlock->E_1 == 0) // Extension octet follows immediately
253 {
254 // TODO We should implement case with several LLC PDU in one data block.
255 blockDataLen = dataBlock->LENGTH_INDICATOR[0];
256 }
257 else
258 {
259 blockDataLen = 20; // RLC data length without 3 header octets.
260 if(dataBlock->TI == 1) // TLLI field is present
261 {
262 *tlli = dataBlock->TLLI;
263 blockDataLen -= 4; // TLLI length
264 if (dataBlock->PI == 1) // PFI is present if TI field indicates presence of TLLI
265 {
266 blockDataLen -= 1; // PFI length
267 }
268 }
269 }
270
271 for (unsigned i = *dataIndex; i < *dataIndex + blockDataLen; i++)
272 {
273 rlc_data[i] = dataBlock->RLC_DATA[dataOctetNum];
274 dataOctetNum++;
275 }
276 *dataIndex += blockDataLen;
277}
278
279void sendUplinkAck(uint8_t tfi, uint32_t tlli, RlcMacUplinkDataBlock_t * dataBlock)
280{
281 BitVector packetUplinkAck(23*8);
282 packetUplinkAck.unhex("2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
283 writePUack(&packetUplinkAck, tfi, tlli, dataBlock->CV, dataBlock->BSN);
284 COUT("RLCMAC_CONTROL_BLOCK>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
285 RlcMacDownlink_t * pUA = (RlcMacDownlink_t *)malloc(sizeof(RlcMacUplink_t));
286 decode_gsm_rlcmac_downlink(&packetUplinkAck, pUA);
287 free(pUA);
288 COUT("RLCMAC_CONTROL_BLOCK_END------------------------------");
289 sendToOpenBTS(&packetUplinkAck);
290}
291
292void RLCMACDispatchDataBlock(unsigned* waitData, BitVector *vector, uint8_t* tfi, uint32_t* tlli, uint8_t* rlc_data, unsigned* dataIndex)
293{
294 static DataBlockDispatcherState state = WaitSequenceStart;
295 static unsigned prevBSN = -1;
296 if ((*waitData == 1)&&(state == WaitNextSequence))
297 {
298 state = WaitSequenceStart;
299 }
300
301 COUT("RLCMAC_DATA_BLOCK<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
302 RlcMacUplinkDataBlock_t * dataBlock = (RlcMacUplinkDataBlock_t *)malloc(sizeof(RlcMacUplinkDataBlock_t));
303 decode_gsm_rlcmac_uplink_data(vector, dataBlock);
304 COUT("RLCMAC_DATA_BLOCK_END------------------------------");
305
306 switch (state) {
307 case WaitSequenceStart:
308 if (dataBlock->BSN == 0)
309 {
310 *dataIndex = 0;
311 RLCMACExtractData(tfi, tlli, dataBlock, rlc_data, dataIndex);
312 sendUplinkAck(*tfi, *tlli, dataBlock);
313 state = WaitNextBlock;
314 prevBSN = 0;
315 }
316 break;
317 case WaitNextBlock:
318 if (prevBSN == (dataBlock->BSN - 1))
319 {
320 RLCMACExtractData(tfi, tlli, dataBlock, rlc_data, dataIndex);
321 sendUplinkAck(*tfi, *tlli, dataBlock);
322 if (dataBlock->CV == 0)
323 {
324 // Recieved last Data Block in this sequence.
325 sendToGSMTAP(rlc_data, *dataIndex);
326 state = WaitNextSequence;
327 prevBSN = -1;
328 *waitData = 0;
329 }
330 else
331 {
332 prevBSN = dataBlock->BSN;
333 state = WaitNextBlock;
334 }
335 }
336 else
337 {
338 // Recieved Data Block with unexpected BSN.
339 // We should try to find nesessary Data Block.
340 state = WaitNextBlock;
341 }
342 break;
343 case WaitNextSequence:
344 // Now we just ignore all Data Blocks and wait next Uplink TBF
345 break;
346 }
347 free(dataBlock);
348}
349
350void RLCMACDispatchControlBlock(unsigned* waitData, BitVector *vector, uint8_t* tfi, uint32_t* tlli, uint8_t* rlc_data, unsigned* dataIndex)
351{
352 static unsigned shutUp = 0;
353 COUT("RLCMAC_CONTROL_BLOCK<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
354 RlcMacUplink_t * controlBlock = (RlcMacUplink_t *)malloc(sizeof(RlcMacUplink_t));
355 decode_gsm_rlcmac_uplink(vector, controlBlock);
356 COUT("RLCMAC_CONTROL_BLOCK_END------------------------------");
357 switch (controlBlock->u.MESSAGE_TYPE) {
358 case MT_PACKET_CONTROL_ACK:
359 if (shutUp == 0)
360 {
361 COUT("SEND IA Rest Octets Downlink Assignment>>>>>>>>>>>>>>>>>>");
362 BitVector IARestOctetsDownlinkAssignment(23*8);
363 IARestOctetsDownlinkAssignment.unhex("2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
364 writeIARestOctetsDownlinkAssignment(&IARestOctetsDownlinkAssignment, 20, *tlli);
365 sendToOpenBTS(&IARestOctetsDownlinkAssignment);
366 usleep(500000);
367 sendToSGSN(*tfi, *tlli, rlc_data, *dataIndex);
368 //sendToGSMTAP(rlc_data, *dataIndex);
369 shutUp = 1;
370 }
371 break;
372 case MT_PACKET_DOWNLINK_ACK_NACK:
373 COUT("SEND PacketUplinkAssignment>>>>>>>>>>>>>>>>>>");
374 BitVector PacketUplinkAssignment(23*8);
375 PacketUplinkAssignment.unhex("2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
376 writePUassignment(&PacketUplinkAssignment, 21, *tlli);
377 sendToOpenBTS(&PacketUplinkAssignment);
378 *waitData = 1;
379 break;
380 }
381 free(controlBlock);
382
383}
384
385void RLCMACDispatchBlock(BitVector *vector)
Ivan Kluchnikov5c2f9fb2012-02-05 02:27:17 +0400386{
387 static uint8_t rlc_data[60];
Ivan Kluchnikov34506402012-02-20 15:24:16 +0400388 static uint8_t *tfi = (uint8_t *)malloc(sizeof(uint8_t));
389 static uint32_t *tlli = (uint32_t *)malloc(sizeof(uint32_t));
390 static unsigned *dataIndex = (unsigned *)malloc(sizeof(unsigned));
391 static unsigned waitData = 1;
392
Ivan Kluchnikov5c2f9fb2012-02-05 02:27:17 +0400393 unsigned readIndex = 0;
394 unsigned payload = vector->readField(readIndex, 2);
395
396 switch (payload) {
Ivan Kluchnikov34506402012-02-20 15:24:16 +0400397 case RLCMAC_DATA_BLOCK:
398 RLCMACDispatchDataBlock(&waitData,vector, tfi, tlli, rlc_data, dataIndex);
Ivan Kluchnikov5c2f9fb2012-02-05 02:27:17 +0400399 break;
400 case RLCMAC_CONTROL_BLOCK:
Ivan Kluchnikov34506402012-02-20 15:24:16 +0400401 RLCMACDispatchControlBlock(&waitData, vector, tfi, tlli, rlc_data, dataIndex);
Ivan Kluchnikov5c2f9fb2012-02-05 02:27:17 +0400402 break;
403 default:
404 COUT("Unknown RLCMAC block payload\n");
405 }
406}
407
408void *RLCMACSocket(void *)
409{
410 BitVector *vector = new BitVector(23*8);
411 GPRSRLCMACSocket.nonblocking();
412 while (1) {
413 char buf[MAX_UDP_LENGTH];
414 int count = GPRSRLCMACSocket.read(buf, 3000);
415 if (count>0) {
416 vector->unpack((const unsigned char*)buf);
417 COUT("Recieve from OpenBTS (MS): " << *vector);
Ivan Kluchnikov34506402012-02-20 15:24:16 +0400418 RLCMACDispatchBlock(vector);
Ivan Kluchnikov5c2f9fb2012-02-05 02:27:17 +0400419 }
420 }
421}