blob: 239b8fdcbf419484c37757a608b62be88c5d3609 [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 Freytherbe570812013-11-07 08:01:49 +010023#include "llc.h"
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010024#include "rlc.h"
Jacob Erlbeck6835cea2015-08-21 15:24:02 +020025#include "cxx_linuxlist.h"
Daniel Willmanneb100242014-08-08 11:43:53 +020026#include <gprs_debug.h>
Max1187a772018-01-26 13:31:42 +010027#include <gprs_coding_scheme.h>
28#include <gsm_timer.h>
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>
Max1187a772018-01-26 13:31:42 +010032 #include <osmocom/core/linuxlist.h>
33 #include <osmocom/core/logging.h>
34 #include <osmocom/core/timer.h>
Maxe66de5b2017-01-05 18:26:58 +010035}
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020036
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020037struct bssgp_bvc_ctx;
Jacob Erlbeckfecece02015-05-08 12:13:08 +020038class GprsMs;
Max1187a772018-01-26 13:31:42 +010039struct gprs_rlcmac_bts;
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020040
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020041/*
42 * TBF instance
43 */
44
Maxb2de1f72017-12-20 18:05:29 +010045#define T_ASS_AGCH_USEC 200000 /* waiting after IMM.ASS confirm */
46#define T_ASS_PACCH_SEC 2 /* timeout for pacch assigment */
47#define T_REJ_PACCH_USEC 2000 /* timeout for tbf reject for PRR*/
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020048
49enum gprs_rlcmac_tbf_state {
50 GPRS_RLCMAC_NULL = 0, /* new created TBF */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +020051 GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020052 GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
53 GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
54 GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
55 GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
56};
57
Maxf60cf622017-07-10 14:40:09 +020058enum gprs_rlcmac_tbf_poll_type {
59 GPRS_RLCMAC_POLL_UL_ASS,
60 GPRS_RLCMAC_POLL_DL_ASS,
61 GPRS_RLCMAC_POLL_UL_ACK,
62 GPRS_RLCMAC_POLL_DL_ACK,
63};
64
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020065enum gprs_rlcmac_tbf_poll_state {
66 GPRS_RLCMAC_POLL_NONE = 0,
67 GPRS_RLCMAC_POLL_SCHED, /* a polling was scheduled */
68};
69
Maxcac6b662018-01-24 11:00:17 +010070extern const struct value_string gprs_rlcmac_tbf_poll_state_names[];
71
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020072enum gprs_rlcmac_tbf_dl_ass_state {
73 GPRS_RLCMAC_DL_ASS_NONE = 0,
74 GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
75 GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
76};
77
Maxe66de5b2017-01-05 18:26:58 +010078extern const struct value_string gprs_rlcmac_tbf_dl_ass_state_names[];
79
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020080enum gprs_rlcmac_tbf_ul_ass_state {
81 GPRS_RLCMAC_UL_ASS_NONE = 0,
82 GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
aravind sirsikared3413e2016-11-11 17:15:10 +053083 GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020084 GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
85};
86
Maxe66de5b2017-01-05 18:26:58 +010087extern const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[];
88
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020089enum gprs_rlcmac_tbf_ul_ack_state {
90 GPRS_RLCMAC_UL_ACK_NONE = 0,
91 GPRS_RLCMAC_UL_ACK_SEND_ACK, /* send acknowledge on next RTS */
92 GPRS_RLCMAC_UL_ACK_WAIT_ACK, /* wait for PACKET CONTROL ACK */
93};
94
Max088c7df2018-01-23 20:16:23 +010095extern const struct value_string gprs_rlcmac_tbf_ul_ack_state_names[];
96
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020097enum gprs_rlcmac_tbf_direction {
98 GPRS_RLCMAC_DL_TBF,
99 GPRS_RLCMAC_UL_TBF
100};
101
Maxd0532b52017-12-13 18:27:32 +0100102enum tbf_dl_prio {
103 DL_PRIO_NONE,
104 DL_PRIO_SENT_DATA, /* the data has been sent and not (yet) nacked */
105 DL_PRIO_LOW_AGE, /* the age has reached the first threshold */
106 DL_PRIO_NEW_DATA, /* the data has not been sent yet or nacked */
107 DL_PRIO_HIGH_AGE, /* the age has reached the second threshold */
108 DL_PRIO_CONTROL, /* a control block needs to be sent */
109};
110
sivasankari53950732016-12-08 17:15:17 +0530111enum tbf_counters {
112 TBF_CTR_RLC_NACKED,
113};
114
115enum tbf_gprs_counters {
116 TBF_CTR_GPRS_DL_CS1,
117 TBF_CTR_GPRS_DL_CS2,
118 TBF_CTR_GPRS_DL_CS3,
119 TBF_CTR_GPRS_DL_CS4,
120};
121
122enum tbf_egprs_counters {
123 TBF_CTR_EGPRS_DL_MCS1,
124 TBF_CTR_EGPRS_DL_MCS2,
125 TBF_CTR_EGPRS_DL_MCS3,
126 TBF_CTR_EGPRS_DL_MCS4,
127 TBF_CTR_EGPRS_DL_MCS5,
128 TBF_CTR_EGPRS_DL_MCS6,
129 TBF_CTR_EGPRS_DL_MCS7,
130 TBF_CTR_EGPRS_DL_MCS8,
131 TBF_CTR_EGPRS_DL_MCS9,
132};
133
sivasankarida7250a2016-12-16 12:57:18 +0530134enum tbf_gprs_ul_counters {
135 TBF_CTR_GPRS_UL_CS1,
136 TBF_CTR_GPRS_UL_CS2,
137 TBF_CTR_GPRS_UL_CS3,
138 TBF_CTR_GPRS_UL_CS4,
139};
140
141enum tbf_egprs_ul_counters {
142 TBF_CTR_EGPRS_UL_MCS1,
143 TBF_CTR_EGPRS_UL_MCS2,
144 TBF_CTR_EGPRS_UL_MCS3,
145 TBF_CTR_EGPRS_UL_MCS4,
146 TBF_CTR_EGPRS_UL_MCS5,
147 TBF_CTR_EGPRS_UL_MCS6,
148 TBF_CTR_EGPRS_UL_MCS7,
149 TBF_CTR_EGPRS_UL_MCS8,
150 TBF_CTR_EGPRS_UL_MCS9,
151};
152
Max0524e382018-01-19 18:22:25 +0100153#define LOGPTBF(tbf, level, fmt, args...) LOGP(DTBF, level, "%s " fmt, tbf_name(tbf), ## args)
154#define LOGPTBFUL(tbf, level, fmt, args...) LOGP(DTBFUL, level, "%s " fmt, tbf_name(tbf), ## args)
155#define LOGPTBFDL(tbf, level, fmt, args...) LOGP(DTBFDL, level, "%s " fmt, tbf_name(tbf), ## args)
Maxc21f0072017-12-15 17:36:45 +0100156
Maxee5be3a2017-12-20 17:31:13 +0100157enum tbf_timers {
Maxb2de1f72017-12-20 18:05:29 +0100158 /* internal assign/reject timer */
159 T0,
160
Maxee5be3a2017-12-20 17:31:13 +0100161 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
162 T3169,
163
164 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
165 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
166 T3191,
167
168 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
169 MS for this TBF. */
170 T3193,
171
172 /* Wait for reuse of TFI(s) when there is no response from the MS
173 (radio failure or cell change) for this TBF/MBMS radio bearer. */
174 T3195,
175 T_MAX
176};
177
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200178#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
179#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
180#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
181#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
182#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
183#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
184#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
185#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
186#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
187
Max467f6332017-12-20 18:13:29 +0100188#define T_START(tbf, t, sec, usec, r, f) tbf->t_start(t, sec, usec, r, f, __FILE__, __LINE__)
189
Max2399b1d2018-01-12 15:48:12 +0100190#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100191#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
192#define TBF_SET_ASS_STATE_UL(t, st) do { t->set_ass_state_ul(st, __FILE__, __LINE__); } while(0)
Max088c7df2018-01-23 20:16:23 +0100193#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Maxcac6b662018-01-24 11:00:17 +0100194#define TBF_POLL_SCHED_SET(t) do { t->poll_sched_set(__FILE__, __LINE__); } while(0)
195#define TBF_POLL_SCHED_UNSET(t) do { t->poll_sched_unset(__FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100196#define TBF_SET_ASS_ON(t, fl, chk) do { t->set_assigned_on(fl, chk, __FILE__, __LINE__); } while(0)
Max5d7f7572018-01-30 16:56:43 +0100197#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
198#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100199
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200200struct gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200201 gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200202
203 static void free_all(struct gprs_rlcmac_trx *trx);
Holger Hans Peter Freyther4f6a4e5d2013-10-16 17:58:46 +0200204 static void free_all(struct gprs_rlcmac_pdch *pdch);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200205
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200206 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
207 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100208 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
209 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100210 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Maxcac6b662018-01-24 11:00:17 +0100211 bool poll_scheduled() const;
Max2399b1d2018-01-12 15:48:12 +0100212 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100213 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
214 void set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line);
Max088c7df2018-01-23 20:16:23 +0100215 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100216 void poll_sched_set(const char *file, int line);
217 void poll_sched_unset(const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100218 void check_pending_ass();
Max8dce1de2018-01-02 14:17:04 +0100219 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100220 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100221 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200222 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200223
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100224 const char *name() const;
225
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100226 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
227 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530228 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200229
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200230 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200231 void set_ms(GprsMs *ms);
232
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100233 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100234
Holger Hans Peter Freyther7380bab2013-10-16 18:09:19 +0200235 int rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200236
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200237 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200238 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100239 void stop_timers(const char *reason);
240 bool timers_pending(enum tbf_timers t);
241 void t_stop(enum tbf_timers t, const char *reason);
Max467f6332017-12-20 18:13:29 +0100242 void t_start(enum tbf_timers t, uint32_t sec, uint32_t microsec, const char *reason, bool force,
243 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200244 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200245
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100246 int check_polling(uint32_t fn, uint8_t ts,
247 uint32_t *poll_fn, unsigned int *rrbp);
Maxf60cf622017-07-10 14:40:09 +0200248 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 +0200249 void poll_timeout();
250
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100251 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100252 uint32_t tlli() const;
253 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100254
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200255 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200256 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200257
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100258 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100259 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100260
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100261 const char *imsi() const;
262 void assign_imsi(const char *imsi);
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200263 uint8_t ta() const;
264 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200265 uint8_t ms_class() const;
266 void set_ms_class(uint8_t);
Jacob Erlbeckcb728902016-01-05 15:33:03 +0100267 GprsCodingScheme current_cs() const;
Max869c0c22018-01-03 12:00:36 +0100268 size_t llc_queue_size() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100269
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100270 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200271 uint8_t dl_slots() const;
272 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100273
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100274 bool is_control_ts(uint8_t ts) const;
275
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100276 /* EGPRS */
277 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100278 void disable_egprs();
279
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100280 /* attempt to make things a bit more fair */
281 void rotate_in_list();
282
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200283 LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}
284 const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}
285
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100286 LListHead<gprs_rlcmac_tbf>& list();
287 const LListHead<gprs_rlcmac_tbf>& list() const;
288
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200289 uint32_t state_flags;
290 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200291 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200292 uint8_t first_ts; /* first TS used by TBF */
293 uint8_t first_common_ts; /* first TS that the phone can send and
294 reveive simultaniously */
295 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200296 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100297
298 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200299
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200300 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100301 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200302
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100303 gprs_rlc m_rlc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200304
305 uint8_t n3105; /* N3105 counter */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200306
307 struct osmo_gsm_timer_list gsm_timer;
308 unsigned int fT; /* fTxxxx number */
309 unsigned int num_fT_exp; /* number of consecutive fT expirations */
310
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200311 struct Meas {
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200312 struct timeval rssi_tv; /* timestamp for rssi calculation */
313 int32_t rssi_sum; /* sum of rssi values */
314 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200315
316 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200317 } meas;
318
Daniel Willmann73191a42014-05-30 17:58:00 +0200319 /* Remember if the tbf was in wait_release state when we want to
320 * schedule a new dl assignment */
321 uint8_t was_releasing;
322
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200323 /* Can/should we upgrade this tbf to use multiple slots? */
324 uint8_t upgrade_to_multislot;
325
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200326 /* store the BTS this TBF belongs to */
327 BTS *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200328
Max59e4a4f2017-12-20 18:01:55 +0100329 uint8_t m_n3101; /* N3101 counter */
330
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100331 /*
332 * private fields. We can't make it private as it is breaking the
333 * llist macros.
334 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100335 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100336 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100337
sivasankari53950732016-12-08 17:15:17 +0530338 struct rate_ctr_group *m_ctrs;
339
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200340protected:
341 gprs_rlcmac_bts *bts_data() const;
Max25a3ca42017-12-13 18:47:52 +0100342 void enable_egprs();
Jacob Erlbecke8f5fe52015-12-14 13:23:15 +0100343 int set_tlli_from_ul(uint32_t new_tlli);
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200344 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100345
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200346 gprs_llc_queue *llc_queue();
347 const gprs_llc_queue *llc_queue() const;
348
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200349 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100350
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200351 class GprsMs *m_ms;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200352
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200353 /* Fields to take the TA/MS class values if no MS is associated */
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200354 uint8_t m_ta;
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200355 uint8_t m_ms_class;
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200356
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100357private:
Max50818062017-12-06 13:35:08 +0100358 enum gprs_rlcmac_tbf_state state;
Max0e599802018-01-23 20:09:06 +0100359 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
360 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
Max088c7df2018-01-23 20:16:23 +0100361 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
Maxcac6b662018-01-24 11:00:17 +0100362 enum gprs_rlcmac_tbf_poll_state poll_state;
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100363 LListHead<gprs_rlcmac_tbf> m_list;
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200364 LListHead<gprs_rlcmac_tbf> m_ms_list;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100365 bool m_egprs_enabled;
Maxb2de1f72017-12-20 18:05:29 +0100366 struct osmo_timer_list T[T_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100367 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200368};
369
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +0200370
Daniel Willmann0d12a2f2014-07-10 17:44:07 +0200371struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck86b6f052015-11-27 15:17:34 +0100372 int8_t use_trx, uint8_t ms_class, uint8_t egprs_ms_class,
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200373 uint32_t tlli, uint8_t ta, GprsMs *ms);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200374
Maxe9fe0e32017-09-28 15:56:05 +0200375struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, uint8_t ms_class,
376 uint8_t egprs_ms_class, bool single_slot);
Daniel Willmann48aa0b02014-07-16 18:54:10 +0200377
Maxe9fe0e32017-09-28 15:56:05 +0200378struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, uint8_t ms_class,
379 uint8_t egprs_ms_class, bool single_slot);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200380
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200381void tbf_free(struct gprs_rlcmac_tbf *tbf);
382
aravind sirsikare9a138e2017-01-24 12:36:08 +0530383struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts,
384 GprsMs *ms, uint32_t tlli, uint8_t trx_no, uint8_t ts_no);
385
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200386int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
387
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200388inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
389{
390 return state == rhs;
391}
392
Max0e599802018-01-23 20:09:06 +0100393inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
394{
395 return dl_ass_state == rhs;
396}
397
398inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
399{
400 return ul_ass_state == rhs;
401}
402
Max088c7df2018-01-23 20:16:23 +0100403inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
404{
405 return ul_ack_state == rhs;
406}
407
Maxcac6b662018-01-24 11:00:17 +0100408inline bool gprs_rlcmac_tbf::poll_scheduled() const
409{
410 return poll_state == GPRS_RLCMAC_POLL_SCHED;
411}
412
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200413inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
414{
415 return state != rhs;
416}
417
Daniel Willmanneb100242014-08-08 11:43:53 +0200418const char *tbf_name(gprs_rlcmac_tbf *tbf);
419
Daniel Willmann08e57c82014-08-15 18:11:57 +0200420inline const char *gprs_rlcmac_tbf::state_name() const
421{
422 return tbf_state_name[state];
423}
424
Max8dce1de2018-01-02 14:17:04 +0100425/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100426inline 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 +0100427{
Max2399b1d2018-01-12 15:48:12 +0100428 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100429 if (check_ccch) {
430 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100431 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100432 } else
433 state_flags |= (1 << state_flag);
434}
435
Max5d7f7572018-01-30 16:56:43 +0100436inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
437{
438 const char *ch = "UNKNOWN";
439 switch (t) {
440 case GPRS_RLCMAC_FLAG_CCCH:
441 if (unset) {
442 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
443 return;
444 } else {
445 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
446 LOGPSRC(DTBF, LOGL_ERROR, file, line,
447 "%s attempted to set ass. type CCCH which is already set.\n",
448 tbf_name(this));
449 }
450 ch = "CCCH";
451 break;
452 case GPRS_RLCMAC_FLAG_PACCH:
453 if (unset) {
454 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
455 return;
456 } else {
457 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
458 LOGPSRC(DTBF, LOGL_ERROR, file, line,
459 "%s attempted to set ass. type PACCH which is already set.\n",
460 tbf_name(this));
461 }
462 ch = "PACCH";
463 break;
464 default:
465 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
466 tbf_name(this), unset ? "un" : "", t);
467 return;
468 }
469
470 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
471 tbf_name(this), unset ? "un" : "", ch,
472 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
473 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
474
475 if (unset) {
476 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
477 state_flags &= ~(1 << t);
478 } else
479 state_flags |= (1 << t);
480}
481
Max2399b1d2018-01-12 15:48:12 +0100482inline 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 +0200483{
Max0524e382018-01-19 18:22:25 +0100484 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200485 tbf_name(this),
486 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200487 state = new_state;
488}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100489
Max0e599802018-01-23 20:09:06 +0100490inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
491{
492 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
493 tbf_name(this),
494 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
495 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
496 dl_ass_state = new_state;
497}
498
499inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
500{
501 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
502 tbf_name(this),
503 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
504 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
505 ul_ass_state = new_state;
506}
507
Max088c7df2018-01-23 20:16:23 +0100508inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
509{
510 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
511 tbf_name(this),
512 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
513 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
514 ul_ack_state = new_state;
515}
516
Maxcac6b662018-01-24 11:00:17 +0100517inline void gprs_rlcmac_tbf::poll_sched_set(const char *file, int line)
518{
519 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_SCHED\n",
520 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
521 poll_state = GPRS_RLCMAC_POLL_SCHED;
522}
523
524inline void gprs_rlcmac_tbf::poll_sched_unset(const char *file, int line)
525{
526 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_NONE\n",
527 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
528 poll_state = GPRS_RLCMAC_POLL_NONE;
529}
530
Max0e599802018-01-23 20:09:06 +0100531inline void gprs_rlcmac_tbf::check_pending_ass()
532{
533 if (ul_ass_state != GPRS_RLCMAC_UL_ASS_NONE)
534 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending uplink assignment in state %s. "
535 "This may not happen, because the assignment message never gets transmitted. "
536 "Please be sure not to free in this state. PLEASE FIX!\n",
537 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state));
538
539 if (dl_ass_state != GPRS_RLCMAC_DL_ASS_NONE)
540 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending downlink assignment in state %s. "
541 "This may not happen, because the assignment message never gets transmitted. "
542 "Please be sure not to free in this state. PLEASE FIX!\n",
543 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state));
544}
545
Max8dce1de2018-01-02 14:17:04 +0100546inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
547{
548 if ((state_flags & (1 << state_flag))) {
549 state_flags &= ~(1 << state_flag);
550 return true;
551 }
552
553 return false;
554}
555
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100556inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
557{
558 return this->m_list;
559}
560
561inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
562{
563 return this->m_list;
564}
565
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200566inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200567{
568 return m_ms;
569}
570
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100571inline bool gprs_rlcmac_tbf::is_tlli_valid() const
572{
Jacob Erlbeck767193e2015-05-20 12:06:46 +0200573 return tlli() != 0;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100574}
575
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100576inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
577{
578 /* The TBF is established or has been assigned by a IMM.ASS for
579 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200580 return state > GPRS_RLCMAC_ASSIGN ||
581 (direction == GPRS_RLCMAC_DL_TBF &&
582 state == GPRS_RLCMAC_ASSIGN &&
583 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100584}
585
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100586inline uint8_t gprs_rlcmac_tbf::tfi() const
587{
588 return m_tfi;
589}
590
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100591inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100592{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100593 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100594}
595
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100596inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
597{
598 return m_egprs_enabled;
599}
600
601inline void gprs_rlcmac_tbf::enable_egprs()
602{
603 m_egprs_enabled = true;
604}
605
606inline void gprs_rlcmac_tbf::disable_egprs()
607{
608 m_egprs_enabled = false;
609}
610
Daniel Willmann078bb712014-07-10 17:44:06 +0200611struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200612 gprs_rlcmac_dl_tbf(BTS *bts);
Maxea98b7d2018-01-04 15:13:27 +0100613 gprs_rlc_dl_window *window();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200614 void cleanup();
Max25a3ca42017-12-13 18:47:52 +0100615 void enable_egprs();
Daniel Willmann30168882014-08-07 12:48:29 +0200616 /* dispatch Unitdata.DL messages */
617 static int handle(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck93990462015-05-15 15:50:43 +0200618 const uint32_t tlli, const uint32_t old_tlli,
619 const char *imsi, const uint8_t ms_class,
Jacob Erlbeck14e00f82015-11-27 18:10:39 +0100620 const uint8_t egprs_ms_class, const uint16_t delay_csec,
621 const uint8_t *data, const uint16_t len);
Daniel Willmann30168882014-08-07 12:48:29 +0200622
Daniel Willmann538ac5b2014-07-30 19:12:27 +0200623 int append_data(const uint8_t ms_class,
624 const uint16_t pdu_delay_csec,
625 const uint8_t *data, const uint16_t len);
626
Max7df82d42017-12-15 11:14:30 +0100627 int rcvd_dl_ack(bool final, uint8_t ssn, uint8_t *rbb);
628 int rcvd_dl_ack(bool final_ack, unsigned first_bsn, struct bitvec *rbb);
Daniel Willmannb8f26012014-07-30 19:12:28 +0200629 struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts);
Maxa10c3982017-07-07 18:25:41 +0200630 void trigger_ass(struct gprs_rlcmac_tbf *old_tbf);
Max8dce1de2018-01-02 14:17:04 +0100631
Maxaae1bfb2017-07-07 13:49:29 +0200632 bool handle_ack_nack();
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100633 void request_dl_ack();
Jacob Erlbeckeceb9102015-03-20 14:41:50 +0100634 bool need_control_ts() const;
635 bool have_data() const;
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100636 int frames_since_last_poll(unsigned fn) const;
Jacob Erlbeck3bed5d12015-03-19 11:22:38 +0100637 int frames_since_last_drain(unsigned fn) const;
638 bool keep_open(unsigned fn) const;
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200639 int release();
Jacob Erlbeckf04a5b32016-01-21 20:42:40 +0100640 int abort();
Maxa4f570f2017-12-15 11:21:57 +0100641 uint16_t window_size() const;
Max9d7357e2017-12-14 15:02:33 +0100642 void set_window_size();
Mrinal Mishraf86307e2016-11-10 18:16:30 +0530643 void update_coding_scheme_counter_dl(const GprsCodingScheme cs);
Aravind Sirsikar8e70bb52016-09-15 17:51:16 +0530644
Daniel Willmanncf706b02014-08-07 17:35:22 +0200645 /* TODO: add the gettimeofday as parameter */
646 struct msgb *llc_dequeue(bssgp_bvc_ctx *bctx);
647
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200648 /* Please note that all variables here will be reset when changing
649 * from WAIT RELEASE back to FLOW state (re-use of TBF).
650 * All states that need reset must be in this struct, so this is why
651 * variables are in both (dl and ul) structs and not outside union.
652 */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200653 int32_t m_tx_counter; /* count all transmitted blocks */
654 uint8_t m_wait_confirm; /* wait for CCCH IMM.ASS cnf */
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100655 bool m_dl_ack_requested;
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100656 int32_t m_last_dl_poll_fn;
Jacob Erlbeck3bed5d12015-03-19 11:22:38 +0100657 int32_t m_last_dl_drained_fn;
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200658
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200659 struct BandWidth {
Daniel Willmann418a4232014-08-08 11:21:04 +0200660 struct timeval dl_bw_tv; /* timestamp for dl bw calculation */
661 uint32_t dl_bw_octets; /* number of octets since bw_tv */
sivasankari53950732016-12-08 17:15:17 +0530662 uint32_t dl_throughput; /* throughput to be displayed in stats */
Daniel Willmann418a4232014-08-08 11:21:04 +0200663
664 struct timeval dl_loss_tv; /* timestamp for loss calculation */
665 uint16_t dl_loss_lost; /* sum of lost packets */
666 uint16_t dl_loss_received; /* sum of received packets */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200667
668 BandWidth();
Daniel Willmann418a4232014-08-08 11:21:04 +0200669 } m_bw;
670
sivasankari53950732016-12-08 17:15:17 +0530671 struct rate_ctr_group *m_dl_gprs_ctrs;
672 struct rate_ctr_group *m_dl_egprs_ctrs;
673
Daniel Willmannb8f26012014-07-30 19:12:28 +0200674protected:
Jacob Erlbeck2db0f082015-09-07 18:49:00 +0200675 struct ana_result {
676 unsigned received_packets;
677 unsigned lost_packets;
678 unsigned received_bytes;
679 unsigned lost_bytes;
680 };
681
Jacob Erlbeckd6752492016-02-02 18:12:46 +0100682 int take_next_bsn(uint32_t fn, int previous_bsn,
Jacob Erlbeck64e7b832016-02-04 15:16:47 +0100683 bool *may_combine);
Jacob Erlbeckd6752492016-02-02 18:12:46 +0100684 bool restart_bsn_cycle();
685 int create_new_bsn(const uint32_t fn, GprsCodingScheme cs);
Daniel Willmannb8f26012014-07-30 19:12:28 +0200686 struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
Jacob Erlbeckbe314d92016-02-02 15:32:10 +0100687 int index, int index2 = -1);
Daniel Willmann30168882014-08-07 12:48:29 +0200688 int update_window(const uint8_t ssn, const uint8_t *rbb);
Jacob Erlbeckeb08f862016-02-05 17:07:12 +0100689 int update_window(unsigned first_bsn, const struct bitvec *rbb);
Daniel Willmann30168882014-08-07 12:48:29 +0200690 int maybe_start_new_window();
691 bool dl_window_stalled() const;
Jacob Erlbeck409efa12015-06-12 14:06:09 +0200692 void reuse_tbf();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200693 void start_llc_timer();
Jacob Erlbeck2db0f082015-09-07 18:49:00 +0200694 int analyse_errors(char *show_rbb, uint8_t ssn, ana_result *res);
Jacob Erlbeck409efa12015-06-12 14:06:09 +0200695 void schedule_next_frame();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200696
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530697 enum egprs_rlc_dl_reseg_bsn_state egprs_dl_get_data
698 (int bsn, uint8_t **block_data);
699 unsigned int get_egprs_dl_spb_status(int bsn);
700 enum egprs_rlcmac_dl_spb get_egprs_dl_spb(int bsn);
701
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200702 struct osmo_timer_list m_llc_timer;
Maxea98b7d2018-01-04 15:13:27 +0100703
704 /* Please note that all variables below will be reset when changing
705 * from WAIT RELEASE back to FLOW state (re-use of TBF).
706 * All states that need reset must be in this struct, so this is why
707 * variables are in both (dl and ul) structs and not outside union.
708 */
709 gprs_rlc_dl_window m_window;
Daniel Willmann078bb712014-07-10 17:44:06 +0200710};
711
712struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200713 gprs_rlcmac_ul_tbf(BTS *bts);
Maxea98b7d2018-01-04 15:13:27 +0100714 gprs_rlc_ul_window *window();
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100715 struct msgb *create_ul_ack(uint32_t fn, uint8_t ts);
Maxfd13f6c2017-07-07 14:29:36 +0200716 bool ctrl_ack_to_toggle();
717 bool handle_ctrl_ack();
Max25a3ca42017-12-13 18:47:52 +0100718 void enable_egprs();
Daniel Willmann350f64d2014-08-07 14:54:11 +0200719 /* blocks were acked */
Jacob Erlbeckb3100e12015-12-14 13:36:13 +0100720 int rcv_data_block_acknowledged(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100721 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +0100722 uint8_t *data, struct pcu_l1_meas *meas);
Jacob Erlbeckb3100e12015-12-14 13:36:13 +0100723
Daniel Willmann350f64d2014-08-07 14:54:11 +0200724
Daniel Willmanne2732e22014-08-07 17:32:01 +0200725 /* TODO: extract LLC class? */
726 int assemble_forward_llc(const gprs_rlc_data *data);
727 int snd_ul_ud();
728
Aravind Sirsikar505a86d2016-07-26 18:26:21 +0530729 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_spb(
730 const struct gprs_rlc_data_info *rlc,
731 struct gprs_rlc_data *block,
732 uint8_t *data, const uint8_t block_idx);
733
734 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_first_seg(
735 const struct gprs_rlc_data_info *rlc,
736 struct gprs_rlc_data *block,
737 uint8_t *data, const uint8_t block_idx);
738
739 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_second_seg(
740 const struct gprs_rlc_data_info *rlc,
741 struct gprs_rlc_data *block,
742 uint8_t *data, const uint8_t block_idx);
743
Maxa4f570f2017-12-15 11:21:57 +0100744 uint16_t window_size() const;
Max9d7357e2017-12-14 15:02:33 +0100745 void set_window_size();
Mrinal Mishraf86307e2016-11-10 18:16:30 +0530746 void update_coding_scheme_counter_ul(const GprsCodingScheme cs);
747
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200748 /* Please note that all variables here will be reset when changing
749 * from WAIT RELEASE back to FLOW state (re-use of TBF).
750 * All states that need reset must be in this struct, so this is why
751 * variables are in both (dl and ul) structs and not outside union.
752 */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200753 int32_t m_rx_counter; /* count all received blocks */
754 uint8_t m_n3103; /* N3103 counter */
755 uint8_t m_usf[8]; /* list USFs per PDCH (timeslot) */
756 uint8_t m_contention_resolution_done; /* set after done */
757 uint8_t m_final_ack_sent; /* set if we sent final ack */
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200758
sivasankarida7250a2016-12-16 12:57:18 +0530759 struct rate_ctr_group *m_ul_gprs_ctrs;
760 struct rate_ctr_group *m_ul_egprs_ctrs;
761
Daniel Willmann350f64d2014-08-07 14:54:11 +0200762protected:
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100763 void maybe_schedule_uplink_acknack(const gprs_rlc_data_info *rlc);
Maxea98b7d2018-01-04 15:13:27 +0100764
765 /* Please note that all variables below will be reset when changing
766 * from WAIT RELEASE back to FLOW state (re-use of TBF).
767 * All states that need reset must be in this struct, so this is why
768 * variables are in both (dl and ul) structs and not outside union.
769 */
770 gprs_rlc_ul_window m_window;
Daniel Willmann078bb712014-07-10 17:44:06 +0200771};
772
Max701afa42017-12-01 17:13:22 +0100773#ifdef __cplusplus
774extern "C" {
775#endif
776void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta);
777void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta);
778#ifdef __cplusplus
779}
780#endif
781
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200782inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
783{
784 return (enum gprs_rlcmac_tbf_direction)
785 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
786}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100787
Maxa4f570f2017-12-15 11:21:57 +0100788inline uint16_t gprs_rlcmac_ul_tbf::window_size() const
789{
790 return m_window.ws();
791}
792
793inline uint16_t gprs_rlcmac_dl_tbf::window_size() const
794{
795 return m_window.ws();
796}
797
Max25a3ca42017-12-13 18:47:52 +0100798inline void gprs_rlcmac_ul_tbf::enable_egprs()
799{
800 m_window.set_sns(RLC_EGPRS_SNS);
801 gprs_rlcmac_tbf::enable_egprs();
802}
803
804inline void gprs_rlcmac_dl_tbf::enable_egprs()
805{
806 m_window.set_sns(RLC_EGPRS_SNS);
807 gprs_rlcmac_tbf::enable_egprs();
808}
809
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100810inline gprs_rlcmac_ul_tbf *as_ul_tbf(gprs_rlcmac_tbf *tbf)
811{
812 if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF)
813 return static_cast<gprs_rlcmac_ul_tbf *>(tbf);
814 else
815 return NULL;
816}
817
818inline gprs_rlcmac_dl_tbf *as_dl_tbf(gprs_rlcmac_tbf *tbf)
819{
820 if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF)
821 return static_cast<gprs_rlcmac_dl_tbf *>(tbf);
822 else
823 return NULL;
824}
825
Max9d7357e2017-12-14 15:02:33 +0100826uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots);
827
Daniel Willmannafa72f52014-01-15 17:06:19 +0100828#endif