blob: dc0b050f33d7532c219eba97534f241cb449f41f [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
Max847ed9f2018-02-20 18:16:11 +0100111enum tbf_rlc_counters {
sivasankari53950732016-12-08 17:15:17 +0530112 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
Max847ed9f2018-02-20 18:16:11 +0100178enum tbf_counters { /* TBF counters from 3GPP TS 44.060 §13.4 */
179 /* counters are reset when: */
180 N3101, /* received a valid data block from mobile station in a block assigned for this USF */
181 N3103, /* transmitting the final PACKET UPLINK ACK/NACK message */
182 N3105, /* after sending a RRBP field in the downlink RLC data block, receives a valid RLC/MAC control message */
183 N_MAX
184};
185
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200186#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
187#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
188#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
189#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
190#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
191#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
192#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
193#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
194#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
195
Max467f6332017-12-20 18:13:29 +0100196#define T_START(tbf, t, sec, usec, r, f) tbf->t_start(t, sec, usec, r, f, __FILE__, __LINE__)
197
Max2399b1d2018-01-12 15:48:12 +0100198#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100199#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
200#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 +0100201#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Maxcac6b662018-01-24 11:00:17 +0100202#define TBF_POLL_SCHED_SET(t) do { t->poll_sched_set(__FILE__, __LINE__); } while(0)
203#define TBF_POLL_SCHED_UNSET(t) do { t->poll_sched_unset(__FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100204#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 +0100205#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
206#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100207
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200208struct gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200209 gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200210
211 static void free_all(struct gprs_rlcmac_trx *trx);
Holger Hans Peter Freyther4f6a4e5d2013-10-16 17:58:46 +0200212 static void free_all(struct gprs_rlcmac_pdch *pdch);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200213
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200214 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
215 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100216 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
217 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100218 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Maxcac6b662018-01-24 11:00:17 +0100219 bool poll_scheduled() const;
Max2399b1d2018-01-12 15:48:12 +0100220 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100221 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
222 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 +0100223 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100224 void poll_sched_set(const char *file, int line);
225 void poll_sched_unset(const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100226 void check_pending_ass();
Max8dce1de2018-01-02 14:17:04 +0100227 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100228 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100229 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200230 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200231
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100232 const char *name() const;
233
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100234 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
235 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530236 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200237
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200238 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200239 void set_ms(GprsMs *ms);
240
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100241 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100242
Holger Hans Peter Freyther7380bab2013-10-16 18:09:19 +0200243 int rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200244
Max847ed9f2018-02-20 18:16:11 +0100245 bool n_inc(enum tbf_counters n);
246 void n_reset(enum tbf_counters n);
247
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200248 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200249 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100250 void stop_timers(const char *reason);
251 bool timers_pending(enum tbf_timers t);
252 void t_stop(enum tbf_timers t, const char *reason);
Max467f6332017-12-20 18:13:29 +0100253 void t_start(enum tbf_timers t, uint32_t sec, uint32_t microsec, const char *reason, bool force,
254 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200255 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200256
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100257 int check_polling(uint32_t fn, uint8_t ts,
258 uint32_t *poll_fn, unsigned int *rrbp);
Maxf60cf622017-07-10 14:40:09 +0200259 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 +0200260 void poll_timeout();
261
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100262 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100263 uint32_t tlli() const;
264 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100265
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200266 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200267 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200268
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100269 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100270 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100271
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100272 const char *imsi() const;
273 void assign_imsi(const char *imsi);
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200274 uint8_t ta() const;
275 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200276 uint8_t ms_class() const;
277 void set_ms_class(uint8_t);
Jacob Erlbeckcb728902016-01-05 15:33:03 +0100278 GprsCodingScheme current_cs() const;
Max869c0c22018-01-03 12:00:36 +0100279 size_t llc_queue_size() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100280
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100281 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200282 uint8_t dl_slots() const;
283 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100284
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100285 bool is_control_ts(uint8_t ts) const;
286
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100287 /* EGPRS */
288 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100289 void disable_egprs();
290
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100291 /* attempt to make things a bit more fair */
292 void rotate_in_list();
293
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200294 LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}
295 const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}
296
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100297 LListHead<gprs_rlcmac_tbf>& list();
298 const LListHead<gprs_rlcmac_tbf>& list() const;
299
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200300 uint32_t state_flags;
301 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200302 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200303 uint8_t first_ts; /* first TS used by TBF */
304 uint8_t first_common_ts; /* first TS that the phone can send and
305 reveive simultaniously */
306 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200307 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100308
309 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200310
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200311 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100312 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200313
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100314 gprs_rlc m_rlc;
Max847ed9f2018-02-20 18:16:11 +0100315
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200316 struct osmo_gsm_timer_list gsm_timer;
317 unsigned int fT; /* fTxxxx number */
318 unsigned int num_fT_exp; /* number of consecutive fT expirations */
319
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200320 struct Meas {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200321 struct timespec rssi_tv; /* timestamp for rssi calculation */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200322 int32_t rssi_sum; /* sum of rssi values */
323 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200324
325 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200326 } meas;
327
Daniel Willmann73191a42014-05-30 17:58:00 +0200328 /* Remember if the tbf was in wait_release state when we want to
329 * schedule a new dl assignment */
330 uint8_t was_releasing;
331
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200332 /* Can/should we upgrade this tbf to use multiple slots? */
333 uint8_t upgrade_to_multislot;
334
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200335 /* store the BTS this TBF belongs to */
336 BTS *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200337
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100338 /*
339 * private fields. We can't make it private as it is breaking the
340 * llist macros.
341 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100342 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100343 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100344
sivasankari53950732016-12-08 17:15:17 +0530345 struct rate_ctr_group *m_ctrs;
346
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200347protected:
348 gprs_rlcmac_bts *bts_data() const;
Max25a3ca42017-12-13 18:47:52 +0100349 void enable_egprs();
Jacob Erlbecke8f5fe52015-12-14 13:23:15 +0100350 int set_tlli_from_ul(uint32_t new_tlli);
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200351 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100352
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200353 gprs_llc_queue *llc_queue();
354 const gprs_llc_queue *llc_queue() const;
355
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200356 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100357
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200358 class GprsMs *m_ms;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200359
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200360 /* Fields to take the TA/MS class values if no MS is associated */
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200361 uint8_t m_ta;
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200362 uint8_t m_ms_class;
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200363
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100364private:
Max50818062017-12-06 13:35:08 +0100365 enum gprs_rlcmac_tbf_state state;
Max0e599802018-01-23 20:09:06 +0100366 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
367 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
Max088c7df2018-01-23 20:16:23 +0100368 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
Maxcac6b662018-01-24 11:00:17 +0100369 enum gprs_rlcmac_tbf_poll_state poll_state;
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100370 LListHead<gprs_rlcmac_tbf> m_list;
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200371 LListHead<gprs_rlcmac_tbf> m_ms_list;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100372 bool m_egprs_enabled;
Maxb2de1f72017-12-20 18:05:29 +0100373 struct osmo_timer_list T[T_MAX];
Max847ed9f2018-02-20 18:16:11 +0100374 uint8_t N[N_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100375 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200376};
377
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +0200378
Daniel Willmann0d12a2f2014-07-10 17:44:07 +0200379struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck86b6f052015-11-27 15:17:34 +0100380 int8_t use_trx, uint8_t ms_class, uint8_t egprs_ms_class,
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200381 uint32_t tlli, uint8_t ta, GprsMs *ms);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200382
Maxe9fe0e32017-09-28 15:56:05 +0200383struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, uint8_t ms_class,
384 uint8_t egprs_ms_class, bool single_slot);
Daniel Willmann48aa0b02014-07-16 18:54:10 +0200385
Maxe9fe0e32017-09-28 15:56:05 +0200386struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, uint8_t ms_class,
387 uint8_t egprs_ms_class, bool single_slot);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200388
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200389void tbf_free(struct gprs_rlcmac_tbf *tbf);
390
aravind sirsikare9a138e2017-01-24 12:36:08 +0530391struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts,
392 GprsMs *ms, uint32_t tlli, uint8_t trx_no, uint8_t ts_no);
393
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200394int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
395
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200396inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
397{
398 return state == rhs;
399}
400
Max0e599802018-01-23 20:09:06 +0100401inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
402{
403 return dl_ass_state == rhs;
404}
405
406inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
407{
408 return ul_ass_state == rhs;
409}
410
Max088c7df2018-01-23 20:16:23 +0100411inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
412{
413 return ul_ack_state == rhs;
414}
415
Maxcac6b662018-01-24 11:00:17 +0100416inline bool gprs_rlcmac_tbf::poll_scheduled() const
417{
418 return poll_state == GPRS_RLCMAC_POLL_SCHED;
419}
420
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200421inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
422{
423 return state != rhs;
424}
425
Daniel Willmanneb100242014-08-08 11:43:53 +0200426const char *tbf_name(gprs_rlcmac_tbf *tbf);
427
Daniel Willmann08e57c82014-08-15 18:11:57 +0200428inline const char *gprs_rlcmac_tbf::state_name() const
429{
430 return tbf_state_name[state];
431}
432
Max8dce1de2018-01-02 14:17:04 +0100433/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100434inline 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 +0100435{
Max2399b1d2018-01-12 15:48:12 +0100436 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100437 if (check_ccch) {
438 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100439 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100440 } else
441 state_flags |= (1 << state_flag);
442}
443
Max5d7f7572018-01-30 16:56:43 +0100444inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
445{
446 const char *ch = "UNKNOWN";
447 switch (t) {
448 case GPRS_RLCMAC_FLAG_CCCH:
449 if (unset) {
450 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
451 return;
452 } else {
453 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
454 LOGPSRC(DTBF, LOGL_ERROR, file, line,
455 "%s attempted to set ass. type CCCH which is already set.\n",
456 tbf_name(this));
457 }
458 ch = "CCCH";
459 break;
460 case GPRS_RLCMAC_FLAG_PACCH:
461 if (unset) {
462 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
463 return;
464 } else {
465 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
466 LOGPSRC(DTBF, LOGL_ERROR, file, line,
467 "%s attempted to set ass. type PACCH which is already set.\n",
468 tbf_name(this));
469 }
470 ch = "PACCH";
471 break;
472 default:
473 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
474 tbf_name(this), unset ? "un" : "", t);
475 return;
476 }
477
478 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
479 tbf_name(this), unset ? "un" : "", ch,
480 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
481 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
482
483 if (unset) {
484 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
485 state_flags &= ~(1 << t);
486 } else
487 state_flags |= (1 << t);
488}
489
Max2399b1d2018-01-12 15:48:12 +0100490inline 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 +0200491{
Max0524e382018-01-19 18:22:25 +0100492 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200493 tbf_name(this),
494 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200495 state = new_state;
496}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100497
Max0e599802018-01-23 20:09:06 +0100498inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
499{
500 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
501 tbf_name(this),
502 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
503 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
504 dl_ass_state = new_state;
505}
506
507inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
508{
509 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
510 tbf_name(this),
511 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
512 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
513 ul_ass_state = new_state;
514}
515
Max088c7df2018-01-23 20:16:23 +0100516inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
517{
518 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
519 tbf_name(this),
520 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
521 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
522 ul_ack_state = new_state;
523}
524
Maxcac6b662018-01-24 11:00:17 +0100525inline void gprs_rlcmac_tbf::poll_sched_set(const char *file, int line)
526{
527 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_SCHED\n",
528 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
529 poll_state = GPRS_RLCMAC_POLL_SCHED;
530}
531
532inline void gprs_rlcmac_tbf::poll_sched_unset(const char *file, int line)
533{
534 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_NONE\n",
535 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
536 poll_state = GPRS_RLCMAC_POLL_NONE;
537}
538
Max0e599802018-01-23 20:09:06 +0100539inline void gprs_rlcmac_tbf::check_pending_ass()
540{
541 if (ul_ass_state != GPRS_RLCMAC_UL_ASS_NONE)
542 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending uplink assignment in state %s. "
543 "This may not happen, because the assignment message never gets transmitted. "
544 "Please be sure not to free in this state. PLEASE FIX!\n",
545 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state));
546
547 if (dl_ass_state != GPRS_RLCMAC_DL_ASS_NONE)
548 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending downlink assignment in state %s. "
549 "This may not happen, because the assignment message never gets transmitted. "
550 "Please be sure not to free in this state. PLEASE FIX!\n",
551 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state));
552}
553
Max8dce1de2018-01-02 14:17:04 +0100554inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
555{
556 if ((state_flags & (1 << state_flag))) {
557 state_flags &= ~(1 << state_flag);
558 return true;
559 }
560
561 return false;
562}
563
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100564inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
565{
566 return this->m_list;
567}
568
569inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
570{
571 return this->m_list;
572}
573
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200574inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200575{
576 return m_ms;
577}
578
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100579inline bool gprs_rlcmac_tbf::is_tlli_valid() const
580{
Jacob Erlbeck767193e2015-05-20 12:06:46 +0200581 return tlli() != 0;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100582}
583
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100584inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
585{
586 /* The TBF is established or has been assigned by a IMM.ASS for
587 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200588 return state > GPRS_RLCMAC_ASSIGN ||
589 (direction == GPRS_RLCMAC_DL_TBF &&
590 state == GPRS_RLCMAC_ASSIGN &&
591 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100592}
593
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100594inline uint8_t gprs_rlcmac_tbf::tfi() const
595{
596 return m_tfi;
597}
598
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100599inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100600{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100601 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100602}
603
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100604inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
605{
606 return m_egprs_enabled;
607}
608
609inline void gprs_rlcmac_tbf::enable_egprs()
610{
611 m_egprs_enabled = true;
612}
613
614inline void gprs_rlcmac_tbf::disable_egprs()
615{
616 m_egprs_enabled = false;
617}
618
Daniel Willmann078bb712014-07-10 17:44:06 +0200619struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200620 gprs_rlcmac_dl_tbf(BTS *bts);
Maxea98b7d2018-01-04 15:13:27 +0100621 gprs_rlc_dl_window *window();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200622 void cleanup();
Max25a3ca42017-12-13 18:47:52 +0100623 void enable_egprs();
Daniel Willmann30168882014-08-07 12:48:29 +0200624 /* dispatch Unitdata.DL messages */
625 static int handle(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck93990462015-05-15 15:50:43 +0200626 const uint32_t tlli, const uint32_t old_tlli,
627 const char *imsi, const uint8_t ms_class,
Jacob Erlbeck14e00f82015-11-27 18:10:39 +0100628 const uint8_t egprs_ms_class, const uint16_t delay_csec,
629 const uint8_t *data, const uint16_t len);
Daniel Willmann30168882014-08-07 12:48:29 +0200630
Daniel Willmann538ac5b2014-07-30 19:12:27 +0200631 int append_data(const uint8_t ms_class,
632 const uint16_t pdu_delay_csec,
633 const uint8_t *data, const uint16_t len);
634
Max7df82d42017-12-15 11:14:30 +0100635 int rcvd_dl_ack(bool final, uint8_t ssn, uint8_t *rbb);
636 int rcvd_dl_ack(bool final_ack, unsigned first_bsn, struct bitvec *rbb);
Daniel Willmannb8f26012014-07-30 19:12:28 +0200637 struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts);
Maxa10c3982017-07-07 18:25:41 +0200638 void trigger_ass(struct gprs_rlcmac_tbf *old_tbf);
Max8dce1de2018-01-02 14:17:04 +0100639
Maxaae1bfb2017-07-07 13:49:29 +0200640 bool handle_ack_nack();
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100641 void request_dl_ack();
Jacob Erlbeckeceb9102015-03-20 14:41:50 +0100642 bool need_control_ts() const;
643 bool have_data() const;
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100644 int frames_since_last_poll(unsigned fn) const;
Jacob Erlbeck3bed5d12015-03-19 11:22:38 +0100645 int frames_since_last_drain(unsigned fn) const;
646 bool keep_open(unsigned fn) const;
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200647 int release();
Jacob Erlbeckf04a5b32016-01-21 20:42:40 +0100648 int abort();
Maxa4f570f2017-12-15 11:21:57 +0100649 uint16_t window_size() const;
Max9d7357e2017-12-14 15:02:33 +0100650 void set_window_size();
Mrinal Mishraf86307e2016-11-10 18:16:30 +0530651 void update_coding_scheme_counter_dl(const GprsCodingScheme cs);
Aravind Sirsikar8e70bb52016-09-15 17:51:16 +0530652
Daniel Willmanncf706b02014-08-07 17:35:22 +0200653 /* TODO: add the gettimeofday as parameter */
654 struct msgb *llc_dequeue(bssgp_bvc_ctx *bctx);
655
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200656 /* Please note that all variables here will be reset when changing
657 * from WAIT RELEASE back to FLOW state (re-use of TBF).
658 * All states that need reset must be in this struct, so this is why
659 * variables are in both (dl and ul) structs and not outside union.
660 */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200661 int32_t m_tx_counter; /* count all transmitted blocks */
662 uint8_t m_wait_confirm; /* wait for CCCH IMM.ASS cnf */
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100663 bool m_dl_ack_requested;
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100664 int32_t m_last_dl_poll_fn;
Jacob Erlbeck3bed5d12015-03-19 11:22:38 +0100665 int32_t m_last_dl_drained_fn;
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200666
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200667 struct BandWidth {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200668 struct timespec dl_bw_tv; /* timestamp for dl bw calculation */
Daniel Willmann418a4232014-08-08 11:21:04 +0200669 uint32_t dl_bw_octets; /* number of octets since bw_tv */
sivasankari53950732016-12-08 17:15:17 +0530670 uint32_t dl_throughput; /* throughput to be displayed in stats */
Daniel Willmann418a4232014-08-08 11:21:04 +0200671
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200672 struct timespec dl_loss_tv; /* timestamp for loss calculation */
Daniel Willmann418a4232014-08-08 11:21:04 +0200673 uint16_t dl_loss_lost; /* sum of lost packets */
674 uint16_t dl_loss_received; /* sum of received packets */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200675
676 BandWidth();
Daniel Willmann418a4232014-08-08 11:21:04 +0200677 } m_bw;
678
sivasankari53950732016-12-08 17:15:17 +0530679 struct rate_ctr_group *m_dl_gprs_ctrs;
680 struct rate_ctr_group *m_dl_egprs_ctrs;
681
Daniel Willmannb8f26012014-07-30 19:12:28 +0200682protected:
Jacob Erlbeck2db0f082015-09-07 18:49:00 +0200683 struct ana_result {
684 unsigned received_packets;
685 unsigned lost_packets;
686 unsigned received_bytes;
687 unsigned lost_bytes;
688 };
689
Jacob Erlbeckd6752492016-02-02 18:12:46 +0100690 int take_next_bsn(uint32_t fn, int previous_bsn,
Jacob Erlbeck64e7b832016-02-04 15:16:47 +0100691 bool *may_combine);
Jacob Erlbeckd6752492016-02-02 18:12:46 +0100692 bool restart_bsn_cycle();
693 int create_new_bsn(const uint32_t fn, GprsCodingScheme cs);
Daniel Willmannb8f26012014-07-30 19:12:28 +0200694 struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
Jacob Erlbeckbe314d92016-02-02 15:32:10 +0100695 int index, int index2 = -1);
Daniel Willmann30168882014-08-07 12:48:29 +0200696 int update_window(const uint8_t ssn, const uint8_t *rbb);
Jacob Erlbeckeb08f862016-02-05 17:07:12 +0100697 int update_window(unsigned first_bsn, const struct bitvec *rbb);
Daniel Willmann30168882014-08-07 12:48:29 +0200698 int maybe_start_new_window();
699 bool dl_window_stalled() const;
Jacob Erlbeck409efa12015-06-12 14:06:09 +0200700 void reuse_tbf();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200701 void start_llc_timer();
Jacob Erlbeck2db0f082015-09-07 18:49:00 +0200702 int analyse_errors(char *show_rbb, uint8_t ssn, ana_result *res);
Jacob Erlbeck409efa12015-06-12 14:06:09 +0200703 void schedule_next_frame();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200704
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530705 enum egprs_rlc_dl_reseg_bsn_state egprs_dl_get_data
706 (int bsn, uint8_t **block_data);
707 unsigned int get_egprs_dl_spb_status(int bsn);
708 enum egprs_rlcmac_dl_spb get_egprs_dl_spb(int bsn);
709
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200710 struct osmo_timer_list m_llc_timer;
Maxea98b7d2018-01-04 15:13:27 +0100711
712 /* Please note that all variables below will be reset when changing
713 * from WAIT RELEASE back to FLOW state (re-use of TBF).
714 * All states that need reset must be in this struct, so this is why
715 * variables are in both (dl and ul) structs and not outside union.
716 */
717 gprs_rlc_dl_window m_window;
Daniel Willmann078bb712014-07-10 17:44:06 +0200718};
719
720struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200721 gprs_rlcmac_ul_tbf(BTS *bts);
Maxea98b7d2018-01-04 15:13:27 +0100722 gprs_rlc_ul_window *window();
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100723 struct msgb *create_ul_ack(uint32_t fn, uint8_t ts);
Maxfd13f6c2017-07-07 14:29:36 +0200724 bool ctrl_ack_to_toggle();
725 bool handle_ctrl_ack();
Max25a3ca42017-12-13 18:47:52 +0100726 void enable_egprs();
Daniel Willmann350f64d2014-08-07 14:54:11 +0200727 /* blocks were acked */
Jacob Erlbeckb3100e12015-12-14 13:36:13 +0100728 int rcv_data_block_acknowledged(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100729 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +0100730 uint8_t *data, struct pcu_l1_meas *meas);
Jacob Erlbeckb3100e12015-12-14 13:36:13 +0100731
Daniel Willmann350f64d2014-08-07 14:54:11 +0200732
Daniel Willmanne2732e22014-08-07 17:32:01 +0200733 /* TODO: extract LLC class? */
734 int assemble_forward_llc(const gprs_rlc_data *data);
735 int snd_ul_ud();
736
Aravind Sirsikar505a86d2016-07-26 18:26:21 +0530737 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_spb(
738 const struct gprs_rlc_data_info *rlc,
739 struct gprs_rlc_data *block,
740 uint8_t *data, const uint8_t block_idx);
741
742 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_first_seg(
743 const struct gprs_rlc_data_info *rlc,
744 struct gprs_rlc_data *block,
745 uint8_t *data, const uint8_t block_idx);
746
747 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_second_seg(
748 const struct gprs_rlc_data_info *rlc,
749 struct gprs_rlc_data *block,
750 uint8_t *data, const uint8_t block_idx);
751
Maxa4f570f2017-12-15 11:21:57 +0100752 uint16_t window_size() const;
Max9d7357e2017-12-14 15:02:33 +0100753 void set_window_size();
Mrinal Mishraf86307e2016-11-10 18:16:30 +0530754 void update_coding_scheme_counter_ul(const GprsCodingScheme cs);
755
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200756 /* Please note that all variables here will be reset when changing
757 * from WAIT RELEASE back to FLOW state (re-use of TBF).
758 * All states that need reset must be in this struct, so this is why
759 * variables are in both (dl and ul) structs and not outside union.
760 */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200761 int32_t m_rx_counter; /* count all received blocks */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200762 uint8_t m_usf[8]; /* list USFs per PDCH (timeslot) */
763 uint8_t m_contention_resolution_done; /* set after done */
764 uint8_t m_final_ack_sent; /* set if we sent final ack */
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200765
sivasankarida7250a2016-12-16 12:57:18 +0530766 struct rate_ctr_group *m_ul_gprs_ctrs;
767 struct rate_ctr_group *m_ul_egprs_ctrs;
768
Daniel Willmann350f64d2014-08-07 14:54:11 +0200769protected:
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100770 void maybe_schedule_uplink_acknack(const gprs_rlc_data_info *rlc);
Maxea98b7d2018-01-04 15:13:27 +0100771
772 /* Please note that all variables below will be reset when changing
773 * from WAIT RELEASE back to FLOW state (re-use of TBF).
774 * All states that need reset must be in this struct, so this is why
775 * variables are in both (dl and ul) structs and not outside union.
776 */
777 gprs_rlc_ul_window m_window;
Daniel Willmann078bb712014-07-10 17:44:06 +0200778};
779
Max701afa42017-12-01 17:13:22 +0100780#ifdef __cplusplus
781extern "C" {
782#endif
783void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta);
784void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta);
785#ifdef __cplusplus
786}
787#endif
788
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200789inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
790{
791 return (enum gprs_rlcmac_tbf_direction)
792 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
793}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100794
Maxa4f570f2017-12-15 11:21:57 +0100795inline uint16_t gprs_rlcmac_ul_tbf::window_size() const
796{
797 return m_window.ws();
798}
799
800inline uint16_t gprs_rlcmac_dl_tbf::window_size() const
801{
802 return m_window.ws();
803}
804
Max25a3ca42017-12-13 18:47:52 +0100805inline void gprs_rlcmac_ul_tbf::enable_egprs()
806{
807 m_window.set_sns(RLC_EGPRS_SNS);
808 gprs_rlcmac_tbf::enable_egprs();
809}
810
811inline void gprs_rlcmac_dl_tbf::enable_egprs()
812{
813 m_window.set_sns(RLC_EGPRS_SNS);
814 gprs_rlcmac_tbf::enable_egprs();
815}
816
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100817inline gprs_rlcmac_ul_tbf *as_ul_tbf(gprs_rlcmac_tbf *tbf)
818{
819 if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF)
820 return static_cast<gprs_rlcmac_ul_tbf *>(tbf);
821 else
822 return NULL;
823}
824
825inline gprs_rlcmac_dl_tbf *as_dl_tbf(gprs_rlcmac_tbf *tbf)
826{
827 if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF)
828 return static_cast<gprs_rlcmac_dl_tbf *>(tbf);
829 else
830 return NULL;
831}
832
Max9d7357e2017-12-14 15:02:33 +0100833uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots);
834
Daniel Willmannafa72f52014-01-15 17:06:19 +0100835#endif