aboutsummaryrefslogtreecommitdiffstats
path: root/src/gprs_ms.h
blob: 246f71e4bd8f16f9b93e1c4f80bc9c19af3426d4 (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
/* gprs_ms.h
 *
 * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH
 * Author: Jacob Erlbeck <jerlbeck@sysmocom.de>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#pragma once

struct gprs_rlcmac_tbf;
struct gprs_rlcmac_dl_tbf;
struct gprs_rlcmac_ul_tbf;
struct gprs_codel;

#include "cxx_linuxlist.h"
#include "llc.h"
#include "tbf.h"
#include "pcu_l1_if.h"

extern "C" {
	#include <osmocom/core/timer.h>
}

#include <stdint.h>
#include <stddef.h>

struct BTS;
struct gprs_rlcmac_trx;

class GprsMs {
public:
	struct Callback {
		virtual void ms_idle(class GprsMs *) = 0;
		virtual void ms_active(class GprsMs *) = 0;
	};

	class Guard {
		public:
		Guard(GprsMs *ms);
		~Guard();

		bool is_idle() const;

		private:
		GprsMs * const m_ms;
	};

	GprsMs(BTS *bts, uint32_t tlli);
	~GprsMs();

	void set_callback(Callback *cb) {m_cb = cb;}

	void merge_old_ms(GprsMs *old_ms);

	gprs_rlcmac_ul_tbf *ul_tbf() const {return m_ul_tbf;}
	gprs_rlcmac_dl_tbf *dl_tbf() const {return m_dl_tbf;}
	gprs_rlcmac_tbf *tbf(enum gprs_rlcmac_tbf_direction dir) const;
	uint32_t tlli() const;
	void set_tlli(uint32_t tlli);
	bool confirm_tlli(uint32_t tlli);
	bool check_tlli(uint32_t tlli);

	void reset();
	GprsCodingScheme::Mode mode() const;
	void set_mode(GprsCodingScheme::Mode mode);

	const char *imsi() const;
	void set_imsi(const char *imsi);

	uint8_t ta() const;
	void set_ta(uint8_t ta);
	uint8_t ms_class() const;
	uint8_t egprs_ms_class() const;
	void set_ms_class(uint8_t ms_class);
	void set_egprs_ms_class(uint8_t ms_class);

	GprsCodingScheme current_cs_ul() const;
	GprsCodingScheme current_cs_dl() const;
	GprsCodingScheme max_cs_ul() const;
	GprsCodingScheme max_cs_dl() const;

	int first_common_ts() const;
	uint8_t dl_slots() const;
	uint8_t ul_slots() const;
	uint8_t reserved_dl_slots() const;
	uint8_t reserved_ul_slots() const;
	gprs_rlcmac_trx *current_trx() const;
	void set_reserved_slots(gprs_rlcmac_trx *trx,
		uint8_t ul_slots, uint8_t dl_slots);

	gprs_llc_queue *llc_queue();
	const gprs_llc_queue *llc_queue() const;
	gprs_codel *codel_state() const;

	void set_timeout(unsigned secs);

	void attach_tbf(gprs_rlcmac_tbf *tbf);
	void attach_ul_tbf(gprs_rlcmac_ul_tbf *tbf);
	void attach_dl_tbf(gprs_rlcmac_dl_tbf *tbf);

	void detach_tbf(gprs_rlcmac_tbf *tbf);

	void update_error_rate(gprs_rlcmac_tbf *tbf, int percent);

	bool is_idle() const;
	bool need_dl_tbf() const;

	void* operator new(size_t num);
	void operator delete(void* p);

	LListHead<GprsMs>& list() {return this->m_list;}
	const LListHead<GprsMs>& list() const {return this->m_list;}
	const LListHead<gprs_rlcmac_tbf>& old_tbfs() const {return m_old_tbfs;}

	void update_l1_meas(const pcu_l1_meas *meas);
	const pcu_l1_meas* l1_meas() const {return &m_l1_meas;};
	unsigned nack_rate_dl() const;

	/* internal use */
	static void timeout(void *priv_);

protected:
	void update_status();
	GprsMs *ref();
	void unref();
	void start_timer();
	void stop_timer();
	void update_cs_ul(const pcu_l1_meas*);

private:
	BTS *m_bts;
	Callback * m_cb;
	gprs_rlcmac_ul_tbf *m_ul_tbf;
	gprs_rlcmac_dl_tbf *m_dl_tbf;
	LListHead<gprs_rlcmac_tbf> m_old_tbfs;

	uint32_t m_tlli;
	uint32_t m_new_ul_tlli;
	uint32_t m_new_dl_tlli;

	/* store IMSI for look-up and PCH retransmission */
	char m_imsi[16];
	uint8_t m_ta;
	uint8_t m_ms_class;
	uint8_t m_egprs_ms_class;
	/* current coding scheme */
	GprsCodingScheme m_current_cs_ul;
	GprsCodingScheme m_current_cs_dl;

	gprs_llc_queue m_llc_queue;

	bool m_is_idle;
	int m_ref;
	LListHead<GprsMs> m_list;
	struct osmo_timer_list m_timer;
	unsigned m_delay;

	int64_t m_last_cs_not_low;

	pcu_l1_meas m_l1_meas;
	unsigned m_nack_rate_dl;
	uint8_t m_reserved_dl_slots;
	uint8_t m_reserved_ul_slots;
	gprs_rlcmac_trx *m_current_trx;

	struct gprs_codel *m_codel_state;
	GprsCodingScheme::Mode m_mode;
};

inline bool GprsMs::is_idle() const
{
	return !m_ul_tbf && !m_dl_tbf && !m_ref && llist_empty(&m_old_tbfs);
}

inline bool GprsMs::need_dl_tbf() const
{
	if (dl_tbf() != NULL && dl_tbf()->state_is_not(GPRS_RLCMAC_WAIT_RELEASE))
		return false;

	return llc_queue()->size() > 0;
}

inline uint32_t GprsMs::tlli() const
{
	return m_new_ul_tlli ? m_new_ul_tlli :
	       m_tlli        ? m_tlli :
			       m_new_dl_tlli;
}

inline bool GprsMs::check_tlli(uint32_t tlli)
{
	return tlli != 0 &&
		(tlli == m_tlli || tlli == m_new_ul_tlli || tlli == m_new_dl_tlli);
}

inline const char *GprsMs::imsi() const
{
	return m_imsi;
}

inline uint8_t GprsMs::ta() const
{
	return m_ta;
}

inline uint8_t GprsMs::ms_class() const
{
	return m_ms_class;
}

inline uint8_t GprsMs::egprs_ms_class() const
{
	return m_egprs_ms_class;
}

inline GprsCodingScheme GprsMs::current_cs_ul() const
{
	return m_current_cs_ul;
}

inline GprsCodingScheme::Mode GprsMs::mode() const
{
	return m_mode;
}

inline void GprsMs::set_timeout(unsigned secs)
{
	m_delay = secs;
}

inline gprs_llc_queue *GprsMs::llc_queue()
{
	return &m_llc_queue;
}

inline const gprs_llc_queue *GprsMs::llc_queue() const
{
	return &m_llc_queue;
}

inline gprs_codel *GprsMs::codel_state() const
{
	return m_codel_state;
}

inline unsigned GprsMs::nack_rate_dl() const
{
	return m_nack_rate_dl;
}

inline uint8_t GprsMs::reserved_dl_slots() const
{
	return m_reserved_dl_slots;
}

inline uint8_t GprsMs::reserved_ul_slots() const
{
	return m_reserved_ul_slots;
}

inline gprs_rlcmac_trx *GprsMs::current_trx() const
{
	return m_current_trx;
}