blob: bf6ce4cd749c84f0be8a7e9da8ff217b55b4d144 [file] [log] [blame]
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +02001/*
2 * Copyright (C) 2013 by Holger Hans Peter Freyther
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#pragma once
20
Daniel Willmannafa72f52014-01-15 17:06:19 +010021#ifdef __cplusplus
22
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +020023#include "gprs_rlcmac.h"
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +010024#include "llc.h"
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010025#include "rlc.h"
Jacob Erlbeck6835cea2015-08-21 15:24:02 +020026#include "cxx_linuxlist.h"
Daniel Willmanneb100242014-08-08 11:43:53 +020027#include <gprs_debug.h>
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +020028
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020029#include <stdint.h>
Maxe66de5b2017-01-05 18:26:58 +010030extern "C" {
31#include <osmocom/core/utils.h>
32}
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020033
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020034struct bssgp_bvc_ctx;
Jacob Erlbeck20f6fd12015-06-08 11:05:45 +020035struct pcu_l1_meas;
Jacob Erlbeckfecece02015-05-08 12:13:08 +020036class GprsMs;
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020037
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020038/*
39 * TBF instance
40 */
41
Maxb2de1f72017-12-20 18:05:29 +010042#define T_ASS_AGCH_USEC 200000 /* waiting after IMM.ASS confirm */
43#define T_ASS_PACCH_SEC 2 /* timeout for pacch assigment */
44#define T_REJ_PACCH_USEC 2000 /* timeout for tbf reject for PRR*/
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020045
46enum gprs_rlcmac_tbf_state {
47 GPRS_RLCMAC_NULL = 0, /* new created TBF */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +020048 GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020049 GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
50 GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
51 GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
52 GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
53};
54
Maxf60cf622017-07-10 14:40:09 +020055enum gprs_rlcmac_tbf_poll_type {
56 GPRS_RLCMAC_POLL_UL_ASS,
57 GPRS_RLCMAC_POLL_DL_ASS,
58 GPRS_RLCMAC_POLL_UL_ACK,
59 GPRS_RLCMAC_POLL_DL_ACK,
60};
61
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020062enum gprs_rlcmac_tbf_poll_state {
63 GPRS_RLCMAC_POLL_NONE = 0,
64 GPRS_RLCMAC_POLL_SCHED, /* a polling was scheduled */
65};
66
67enum gprs_rlcmac_tbf_dl_ass_state {
68 GPRS_RLCMAC_DL_ASS_NONE = 0,
69 GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
70 GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
71};
72
Maxe66de5b2017-01-05 18:26:58 +010073extern const struct value_string gprs_rlcmac_tbf_dl_ass_state_names[];
74
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020075enum gprs_rlcmac_tbf_ul_ass_state {
76 GPRS_RLCMAC_UL_ASS_NONE = 0,
77 GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
aravind sirsikared3413e2016-11-11 17:15:10 +053078 GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020079 GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
80};
81
Maxe66de5b2017-01-05 18:26:58 +010082extern const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[];
83
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020084enum gprs_rlcmac_tbf_ul_ack_state {
85 GPRS_RLCMAC_UL_ACK_NONE = 0,
86 GPRS_RLCMAC_UL_ACK_SEND_ACK, /* send acknowledge on next RTS */
87 GPRS_RLCMAC_UL_ACK_WAIT_ACK, /* wait for PACKET CONTROL ACK */
88};
89
90enum gprs_rlcmac_tbf_direction {
91 GPRS_RLCMAC_DL_TBF,
92 GPRS_RLCMAC_UL_TBF
93};
94
Maxd0532b52017-12-13 18:27:32 +010095enum tbf_dl_prio {
96 DL_PRIO_NONE,
97 DL_PRIO_SENT_DATA, /* the data has been sent and not (yet) nacked */
98 DL_PRIO_LOW_AGE, /* the age has reached the first threshold */
99 DL_PRIO_NEW_DATA, /* the data has not been sent yet or nacked */
100 DL_PRIO_HIGH_AGE, /* the age has reached the second threshold */
101 DL_PRIO_CONTROL, /* a control block needs to be sent */
102};
103
sivasankari53950732016-12-08 17:15:17 +0530104enum tbf_counters {
105 TBF_CTR_RLC_NACKED,
106};
107
108enum tbf_gprs_counters {
109 TBF_CTR_GPRS_DL_CS1,
110 TBF_CTR_GPRS_DL_CS2,
111 TBF_CTR_GPRS_DL_CS3,
112 TBF_CTR_GPRS_DL_CS4,
113};
114
115enum tbf_egprs_counters {
116 TBF_CTR_EGPRS_DL_MCS1,
117 TBF_CTR_EGPRS_DL_MCS2,
118 TBF_CTR_EGPRS_DL_MCS3,
119 TBF_CTR_EGPRS_DL_MCS4,
120 TBF_CTR_EGPRS_DL_MCS5,
121 TBF_CTR_EGPRS_DL_MCS6,
122 TBF_CTR_EGPRS_DL_MCS7,
123 TBF_CTR_EGPRS_DL_MCS8,
124 TBF_CTR_EGPRS_DL_MCS9,
125};
126
sivasankarida7250a2016-12-16 12:57:18 +0530127enum tbf_gprs_ul_counters {
128 TBF_CTR_GPRS_UL_CS1,
129 TBF_CTR_GPRS_UL_CS2,
130 TBF_CTR_GPRS_UL_CS3,
131 TBF_CTR_GPRS_UL_CS4,
132};
133
134enum tbf_egprs_ul_counters {
135 TBF_CTR_EGPRS_UL_MCS1,
136 TBF_CTR_EGPRS_UL_MCS2,
137 TBF_CTR_EGPRS_UL_MCS3,
138 TBF_CTR_EGPRS_UL_MCS4,
139 TBF_CTR_EGPRS_UL_MCS5,
140 TBF_CTR_EGPRS_UL_MCS6,
141 TBF_CTR_EGPRS_UL_MCS7,
142 TBF_CTR_EGPRS_UL_MCS8,
143 TBF_CTR_EGPRS_UL_MCS9,
144};
145
Maxc21f0072017-12-15 17:36:45 +0100146#define LOGPTBF(tbf, level, fmt, args...) LOGP(DRLCMAC, level, "%s " fmt, tbf_name(tbf), ## args)
147#define LOGPTBFUL(tbf, level, fmt, args...) LOGP(DRLCMACUL, level, "%s " fmt, tbf_name(tbf), ## args)
148#define LOGPTBFDL(tbf, level, fmt, args...) LOGP(DRLCMACDL, level, "%s " fmt, tbf_name(tbf), ## args)
149
Maxee5be3a2017-12-20 17:31:13 +0100150enum tbf_timers {
Maxb2de1f72017-12-20 18:05:29 +0100151 /* internal assign/reject timer */
152 T0,
153
Maxee5be3a2017-12-20 17:31:13 +0100154 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
155 T3169,
156
157 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
158 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
159 T3191,
160
161 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
162 MS for this TBF. */
163 T3193,
164
165 /* Wait for reuse of TFI(s) when there is no response from the MS
166 (radio failure or cell change) for this TBF/MBMS radio bearer. */
167 T3195,
168 T_MAX
169};
170
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200171#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
172#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
173#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
174#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
175#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
176#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
177#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
178#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
179#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
180
Max467f6332017-12-20 18:13:29 +0100181#define T_START(tbf, t, sec, usec, r, f) tbf->t_start(t, sec, usec, r, f, __FILE__, __LINE__)
182
Max2399b1d2018-01-12 15:48:12 +0100183#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
184#define TBF_SET_ASS_ON(t, fl, chk) do { t->set_assigned_on(fl, chk, __FILE__, __LINE__); } while(0)
185
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200186struct gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200187 gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200188
189 static void free_all(struct gprs_rlcmac_trx *trx);
Holger Hans Peter Freyther4f6a4e5d2013-10-16 17:58:46 +0200190 static void free_all(struct gprs_rlcmac_pdch *pdch);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200191
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200192 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
193 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max2399b1d2018-01-12 15:48:12 +0100194 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max8dce1de2018-01-02 14:17:04 +0100195 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100196 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200197 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200198
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100199 const char *name() const;
200
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100201 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
202 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530203 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200204
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200205 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200206 void set_ms(GprsMs *ms);
207
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100208 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100209
Holger Hans Peter Freyther7380bab2013-10-16 18:09:19 +0200210 int rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200211
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200212 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200213 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100214 void stop_timers(const char *reason);
215 bool timers_pending(enum tbf_timers t);
216 void t_stop(enum tbf_timers t, const char *reason);
Max467f6332017-12-20 18:13:29 +0100217 void t_start(enum tbf_timers t, uint32_t sec, uint32_t microsec, const char *reason, bool force,
218 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200219 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200220
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100221 int check_polling(uint32_t fn, uint8_t ts,
222 uint32_t *poll_fn, unsigned int *rrbp);
Maxf60cf622017-07-10 14:40:09 +0200223 void set_polling(uint32_t poll_fn, uint8_t ts, enum gprs_rlcmac_tbf_poll_type t);
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200224 void poll_timeout();
225
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100226 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100227 uint32_t tlli() const;
228 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100229
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200230 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200231 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200232
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100233 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100234 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100235
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100236 const char *imsi() const;
237 void assign_imsi(const char *imsi);
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200238 uint8_t ta() const;
239 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200240 uint8_t ms_class() const;
241 void set_ms_class(uint8_t);
Jacob Erlbeckcb728902016-01-05 15:33:03 +0100242 GprsCodingScheme current_cs() const;
Max869c0c22018-01-03 12:00:36 +0100243 size_t llc_queue_size() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100244
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100245 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200246 uint8_t dl_slots() const;
247 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100248
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100249 bool is_control_ts(uint8_t ts) const;
250
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100251 /* EGPRS */
252 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100253 void disable_egprs();
254
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100255 /* attempt to make things a bit more fair */
256 void rotate_in_list();
257
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200258 LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}
259 const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}
260
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100261 LListHead<gprs_rlcmac_tbf>& list();
262 const LListHead<gprs_rlcmac_tbf>& list() const;
263
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200264 uint32_t state_flags;
265 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200266 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200267 uint8_t first_ts; /* first TS used by TBF */
268 uint8_t first_common_ts; /* first TS that the phone can send and
269 reveive simultaniously */
270 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200271 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100272
273 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200274
275 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
276 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
277 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
278
279 enum gprs_rlcmac_tbf_poll_state poll_state;
280 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100281 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200282
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100283 gprs_rlc m_rlc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200284
285 uint8_t n3105; /* N3105 counter */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200286
287 struct osmo_gsm_timer_list gsm_timer;
288 unsigned int fT; /* fTxxxx number */
289 unsigned int num_fT_exp; /* number of consecutive fT expirations */
290
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200291 struct Meas {
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200292 struct timeval rssi_tv; /* timestamp for rssi calculation */
293 int32_t rssi_sum; /* sum of rssi values */
294 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200295
296 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200297 } meas;
298
Daniel Willmann73191a42014-05-30 17:58:00 +0200299 /* Remember if the tbf was in wait_release state when we want to
300 * schedule a new dl assignment */
301 uint8_t was_releasing;
302
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200303 /* Can/should we upgrade this tbf to use multiple slots? */
304 uint8_t upgrade_to_multislot;
305
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200306 /* store the BTS this TBF belongs to */
307 BTS *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200308
Max59e4a4f2017-12-20 18:01:55 +0100309 uint8_t m_n3101; /* N3101 counter */
310
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100311 /*
312 * private fields. We can't make it private as it is breaking the
313 * llist macros.
314 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100315 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100316 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100317
sivasankari53950732016-12-08 17:15:17 +0530318 struct rate_ctr_group *m_ctrs;
319
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200320protected:
321 gprs_rlcmac_bts *bts_data() const;
Max25a3ca42017-12-13 18:47:52 +0100322 void enable_egprs();
Jacob Erlbecke8f5fe52015-12-14 13:23:15 +0100323 int set_tlli_from_ul(uint32_t new_tlli);
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200324 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100325
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200326 gprs_llc_queue *llc_queue();
327 const gprs_llc_queue *llc_queue() const;
328
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200329 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100330
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200331 class GprsMs *m_ms;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200332
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200333 /* Fields to take the TA/MS class values if no MS is associated */
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200334 uint8_t m_ta;
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200335 uint8_t m_ms_class;
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200336
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100337private:
Max50818062017-12-06 13:35:08 +0100338 enum gprs_rlcmac_tbf_state state;
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100339 LListHead<gprs_rlcmac_tbf> m_list;
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200340 LListHead<gprs_rlcmac_tbf> m_ms_list;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100341 bool m_egprs_enabled;
Maxb2de1f72017-12-20 18:05:29 +0100342 struct osmo_timer_list T[T_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100343 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200344};
345
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +0200346
Daniel Willmann0d12a2f2014-07-10 17:44:07 +0200347struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck86b6f052015-11-27 15:17:34 +0100348 int8_t use_trx, uint8_t ms_class, uint8_t egprs_ms_class,
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200349 uint32_t tlli, uint8_t ta, GprsMs *ms);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200350
Daniel Willmann48aa0b02014-07-16 18:54:10 +0200351struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck5879c642015-07-10 10:41:36 +0200352 GprsMs *ms, int8_t use_trx,
Jacob Erlbeck86b6f052015-11-27 15:17:34 +0100353 uint8_t ms_class, uint8_t egprs_ms_class, uint8_t single_slot);
Daniel Willmann48aa0b02014-07-16 18:54:10 +0200354
355struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck5879c642015-07-10 10:41:36 +0200356 GprsMs *ms, int8_t use_trx,
Jacob Erlbeck86b6f052015-11-27 15:17:34 +0100357 uint8_t ms_class, uint8_t egprs_ms_class, uint8_t single_slot);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200358
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200359void tbf_free(struct gprs_rlcmac_tbf *tbf);
360
aravind sirsikare9a138e2017-01-24 12:36:08 +0530361struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts,
362 GprsMs *ms, uint32_t tlli, uint8_t trx_no, uint8_t ts_no);
363
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200364int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
365
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200366inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
367{
368 return state == rhs;
369}
370
371inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
372{
373 return state != rhs;
374}
375
Daniel Willmanneb100242014-08-08 11:43:53 +0200376const char *tbf_name(gprs_rlcmac_tbf *tbf);
377
Daniel Willmann08e57c82014-08-15 18:11:57 +0200378inline const char *gprs_rlcmac_tbf::state_name() const
379{
380 return tbf_state_name[state];
381}
382
Max8dce1de2018-01-02 14:17:04 +0100383/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100384inline void gprs_rlcmac_tbf::set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line)
Max8dce1de2018-01-02 14:17:04 +0100385{
Max2399b1d2018-01-12 15:48:12 +0100386 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100387 if (check_ccch) {
388 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
389 state_flags |= (1 << state_flag);
390 } else
391 state_flags |= (1 << state_flag);
392}
393
Max2399b1d2018-01-12 15:48:12 +0100394inline void gprs_rlcmac_tbf::set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line)
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200395{
Max2399b1d2018-01-12 15:48:12 +0100396 LOGPSRC(DRLCMAC, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200397 tbf_name(this),
398 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200399 state = new_state;
400}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100401
Max8dce1de2018-01-02 14:17:04 +0100402inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
403{
404 if ((state_flags & (1 << state_flag))) {
405 state_flags &= ~(1 << state_flag);
406 return true;
407 }
408
409 return false;
410}
411
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100412inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
413{
414 return this->m_list;
415}
416
417inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
418{
419 return this->m_list;
420}
421
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200422inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200423{
424 return m_ms;
425}
426
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100427inline bool gprs_rlcmac_tbf::is_tlli_valid() const
428{
Jacob Erlbeck767193e2015-05-20 12:06:46 +0200429 return tlli() != 0;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100430}
431
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100432inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
433{
434 /* The TBF is established or has been assigned by a IMM.ASS for
435 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200436 return state > GPRS_RLCMAC_ASSIGN ||
437 (direction == GPRS_RLCMAC_DL_TBF &&
438 state == GPRS_RLCMAC_ASSIGN &&
439 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100440}
441
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100442inline uint8_t gprs_rlcmac_tbf::tfi() const
443{
444 return m_tfi;
445}
446
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100447inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100448{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100449 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100450}
451
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100452inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
453{
454 return m_egprs_enabled;
455}
456
457inline void gprs_rlcmac_tbf::enable_egprs()
458{
459 m_egprs_enabled = true;
460}
461
462inline void gprs_rlcmac_tbf::disable_egprs()
463{
464 m_egprs_enabled = false;
465}
466
Daniel Willmann078bb712014-07-10 17:44:06 +0200467struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200468 gprs_rlcmac_dl_tbf(BTS *bts);
Maxea98b7d2018-01-04 15:13:27 +0100469 gprs_rlc_dl_window *window();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200470 void cleanup();
Max25a3ca42017-12-13 18:47:52 +0100471 void enable_egprs();
Daniel Willmann30168882014-08-07 12:48:29 +0200472 /* dispatch Unitdata.DL messages */
473 static int handle(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck93990462015-05-15 15:50:43 +0200474 const uint32_t tlli, const uint32_t old_tlli,
475 const char *imsi, const uint8_t ms_class,
Jacob Erlbeck14e00f82015-11-27 18:10:39 +0100476 const uint8_t egprs_ms_class, const uint16_t delay_csec,
477 const uint8_t *data, const uint16_t len);
Daniel Willmann30168882014-08-07 12:48:29 +0200478
Daniel Willmann538ac5b2014-07-30 19:12:27 +0200479 int append_data(const uint8_t ms_class,
480 const uint16_t pdu_delay_csec,
481 const uint8_t *data, const uint16_t len);
482
Max7df82d42017-12-15 11:14:30 +0100483 int rcvd_dl_ack(bool final, uint8_t ssn, uint8_t *rbb);
484 int rcvd_dl_ack(bool final_ack, unsigned first_bsn, struct bitvec *rbb);
Daniel Willmannb8f26012014-07-30 19:12:28 +0200485 struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts);
Maxa10c3982017-07-07 18:25:41 +0200486 void trigger_ass(struct gprs_rlcmac_tbf *old_tbf);
Max8dce1de2018-01-02 14:17:04 +0100487
Maxaae1bfb2017-07-07 13:49:29 +0200488 bool handle_ack_nack();
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100489 void request_dl_ack();
Jacob Erlbeckeceb9102015-03-20 14:41:50 +0100490 bool need_control_ts() const;
491 bool have_data() const;
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100492 int frames_since_last_poll(unsigned fn) const;
Jacob Erlbeck3bed5d12015-03-19 11:22:38 +0100493 int frames_since_last_drain(unsigned fn) const;
494 bool keep_open(unsigned fn) const;
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200495 int release();
Jacob Erlbeckf04a5b32016-01-21 20:42:40 +0100496 int abort();
Maxa4f570f2017-12-15 11:21:57 +0100497 uint16_t window_size() const;
Max9d7357e2017-12-14 15:02:33 +0100498 void set_window_size();
Mrinal Mishraf86307e2016-11-10 18:16:30 +0530499 void update_coding_scheme_counter_dl(const GprsCodingScheme cs);
Aravind Sirsikar8e70bb52016-09-15 17:51:16 +0530500
Daniel Willmanncf706b02014-08-07 17:35:22 +0200501 /* TODO: add the gettimeofday as parameter */
502 struct msgb *llc_dequeue(bssgp_bvc_ctx *bctx);
503
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200504 /* Please note that all variables here will be reset when changing
505 * from WAIT RELEASE back to FLOW state (re-use of TBF).
506 * All states that need reset must be in this struct, so this is why
507 * variables are in both (dl and ul) structs and not outside union.
508 */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200509 int32_t m_tx_counter; /* count all transmitted blocks */
510 uint8_t m_wait_confirm; /* wait for CCCH IMM.ASS cnf */
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100511 bool m_dl_ack_requested;
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100512 int32_t m_last_dl_poll_fn;
Jacob Erlbeck3bed5d12015-03-19 11:22:38 +0100513 int32_t m_last_dl_drained_fn;
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200514
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200515 struct BandWidth {
Daniel Willmann418a4232014-08-08 11:21:04 +0200516 struct timeval dl_bw_tv; /* timestamp for dl bw calculation */
517 uint32_t dl_bw_octets; /* number of octets since bw_tv */
sivasankari53950732016-12-08 17:15:17 +0530518 uint32_t dl_throughput; /* throughput to be displayed in stats */
Daniel Willmann418a4232014-08-08 11:21:04 +0200519
520 struct timeval dl_loss_tv; /* timestamp for loss calculation */
521 uint16_t dl_loss_lost; /* sum of lost packets */
522 uint16_t dl_loss_received; /* sum of received packets */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200523
524 BandWidth();
Daniel Willmann418a4232014-08-08 11:21:04 +0200525 } m_bw;
526
sivasankari53950732016-12-08 17:15:17 +0530527 struct rate_ctr_group *m_dl_gprs_ctrs;
528 struct rate_ctr_group *m_dl_egprs_ctrs;
529
Daniel Willmannb8f26012014-07-30 19:12:28 +0200530protected:
Jacob Erlbeck2db0f082015-09-07 18:49:00 +0200531 struct ana_result {
532 unsigned received_packets;
533 unsigned lost_packets;
534 unsigned received_bytes;
535 unsigned lost_bytes;
536 };
537
Jacob Erlbeckd6752492016-02-02 18:12:46 +0100538 int take_next_bsn(uint32_t fn, int previous_bsn,
Jacob Erlbeck64e7b832016-02-04 15:16:47 +0100539 bool *may_combine);
Jacob Erlbeckd6752492016-02-02 18:12:46 +0100540 bool restart_bsn_cycle();
541 int create_new_bsn(const uint32_t fn, GprsCodingScheme cs);
Daniel Willmannb8f26012014-07-30 19:12:28 +0200542 struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
Jacob Erlbeckbe314d92016-02-02 15:32:10 +0100543 int index, int index2 = -1);
Daniel Willmann30168882014-08-07 12:48:29 +0200544 int update_window(const uint8_t ssn, const uint8_t *rbb);
Jacob Erlbeckeb08f862016-02-05 17:07:12 +0100545 int update_window(unsigned first_bsn, const struct bitvec *rbb);
Daniel Willmann30168882014-08-07 12:48:29 +0200546 int maybe_start_new_window();
547 bool dl_window_stalled() const;
Jacob Erlbeck409efa12015-06-12 14:06:09 +0200548 void reuse_tbf();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200549 void start_llc_timer();
Jacob Erlbeck2db0f082015-09-07 18:49:00 +0200550 int analyse_errors(char *show_rbb, uint8_t ssn, ana_result *res);
Jacob Erlbeck409efa12015-06-12 14:06:09 +0200551 void schedule_next_frame();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200552
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530553 enum egprs_rlc_dl_reseg_bsn_state egprs_dl_get_data
554 (int bsn, uint8_t **block_data);
555 unsigned int get_egprs_dl_spb_status(int bsn);
556 enum egprs_rlcmac_dl_spb get_egprs_dl_spb(int bsn);
557
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200558 struct osmo_timer_list m_llc_timer;
Maxea98b7d2018-01-04 15:13:27 +0100559
560 /* Please note that all variables below will be reset when changing
561 * from WAIT RELEASE back to FLOW state (re-use of TBF).
562 * All states that need reset must be in this struct, so this is why
563 * variables are in both (dl and ul) structs and not outside union.
564 */
565 gprs_rlc_dl_window m_window;
Daniel Willmann078bb712014-07-10 17:44:06 +0200566};
567
568struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200569 gprs_rlcmac_ul_tbf(BTS *bts);
Maxea98b7d2018-01-04 15:13:27 +0100570 gprs_rlc_ul_window *window();
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100571 struct msgb *create_ul_ack(uint32_t fn, uint8_t ts);
Maxfd13f6c2017-07-07 14:29:36 +0200572 bool ctrl_ack_to_toggle();
573 bool handle_ctrl_ack();
Max25a3ca42017-12-13 18:47:52 +0100574 void enable_egprs();
Daniel Willmann350f64d2014-08-07 14:54:11 +0200575 /* blocks were acked */
Jacob Erlbeckb3100e12015-12-14 13:36:13 +0100576 int rcv_data_block_acknowledged(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100577 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +0100578 uint8_t *data, struct pcu_l1_meas *meas);
Jacob Erlbeckb3100e12015-12-14 13:36:13 +0100579
Daniel Willmann350f64d2014-08-07 14:54:11 +0200580
Daniel Willmanne2732e22014-08-07 17:32:01 +0200581 /* TODO: extract LLC class? */
582 int assemble_forward_llc(const gprs_rlc_data *data);
583 int snd_ul_ud();
584
Aravind Sirsikar505a86d2016-07-26 18:26:21 +0530585 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_spb(
586 const struct gprs_rlc_data_info *rlc,
587 struct gprs_rlc_data *block,
588 uint8_t *data, const uint8_t block_idx);
589
590 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_first_seg(
591 const struct gprs_rlc_data_info *rlc,
592 struct gprs_rlc_data *block,
593 uint8_t *data, const uint8_t block_idx);
594
595 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_second_seg(
596 const struct gprs_rlc_data_info *rlc,
597 struct gprs_rlc_data *block,
598 uint8_t *data, const uint8_t block_idx);
599
Maxa4f570f2017-12-15 11:21:57 +0100600 uint16_t window_size() const;
Max9d7357e2017-12-14 15:02:33 +0100601 void set_window_size();
Mrinal Mishraf86307e2016-11-10 18:16:30 +0530602 void update_coding_scheme_counter_ul(const GprsCodingScheme cs);
603
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200604 /* Please note that all variables here will be reset when changing
605 * from WAIT RELEASE back to FLOW state (re-use of TBF).
606 * All states that need reset must be in this struct, so this is why
607 * variables are in both (dl and ul) structs and not outside union.
608 */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200609 int32_t m_rx_counter; /* count all received blocks */
610 uint8_t m_n3103; /* N3103 counter */
611 uint8_t m_usf[8]; /* list USFs per PDCH (timeslot) */
612 uint8_t m_contention_resolution_done; /* set after done */
613 uint8_t m_final_ack_sent; /* set if we sent final ack */
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200614
sivasankarida7250a2016-12-16 12:57:18 +0530615 struct rate_ctr_group *m_ul_gprs_ctrs;
616 struct rate_ctr_group *m_ul_egprs_ctrs;
617
Daniel Willmann350f64d2014-08-07 14:54:11 +0200618protected:
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100619 void maybe_schedule_uplink_acknack(const gprs_rlc_data_info *rlc);
Maxea98b7d2018-01-04 15:13:27 +0100620
621 /* Please note that all variables below will be reset when changing
622 * from WAIT RELEASE back to FLOW state (re-use of TBF).
623 * All states that need reset must be in this struct, so this is why
624 * variables are in both (dl and ul) structs and not outside union.
625 */
626 gprs_rlc_ul_window m_window;
Daniel Willmann078bb712014-07-10 17:44:06 +0200627};
628
Max701afa42017-12-01 17:13:22 +0100629#ifdef __cplusplus
630extern "C" {
631#endif
632void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta);
633void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta);
634#ifdef __cplusplus
635}
636#endif
637
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200638inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
639{
640 return (enum gprs_rlcmac_tbf_direction)
641 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
642}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100643
Maxa4f570f2017-12-15 11:21:57 +0100644inline uint16_t gprs_rlcmac_ul_tbf::window_size() const
645{
646 return m_window.ws();
647}
648
649inline uint16_t gprs_rlcmac_dl_tbf::window_size() const
650{
651 return m_window.ws();
652}
653
Max25a3ca42017-12-13 18:47:52 +0100654inline void gprs_rlcmac_ul_tbf::enable_egprs()
655{
656 m_window.set_sns(RLC_EGPRS_SNS);
657 gprs_rlcmac_tbf::enable_egprs();
658}
659
660inline void gprs_rlcmac_dl_tbf::enable_egprs()
661{
662 m_window.set_sns(RLC_EGPRS_SNS);
663 gprs_rlcmac_tbf::enable_egprs();
664}
665
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100666inline gprs_rlcmac_ul_tbf *as_ul_tbf(gprs_rlcmac_tbf *tbf)
667{
668 if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF)
669 return static_cast<gprs_rlcmac_ul_tbf *>(tbf);
670 else
671 return NULL;
672}
673
674inline gprs_rlcmac_dl_tbf *as_dl_tbf(gprs_rlcmac_tbf *tbf)
675{
676 if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF)
677 return static_cast<gprs_rlcmac_dl_tbf *>(tbf);
678 else
679 return NULL;
680}
681
Max9d7357e2017-12-14 15:02:33 +0100682uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots);
683
Daniel Willmannafa72f52014-01-15 17:06:19 +0100684#endif