blob: 2ed63f975eadce117b60da190be5b98d40b3e1e5 [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
Maxcac6b662018-01-24 11:00:17 +010067extern const struct value_string gprs_rlcmac_tbf_poll_state_names[];
68
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020069enum gprs_rlcmac_tbf_dl_ass_state {
70 GPRS_RLCMAC_DL_ASS_NONE = 0,
71 GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
72 GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
73};
74
Maxe66de5b2017-01-05 18:26:58 +010075extern const struct value_string gprs_rlcmac_tbf_dl_ass_state_names[];
76
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020077enum gprs_rlcmac_tbf_ul_ass_state {
78 GPRS_RLCMAC_UL_ASS_NONE = 0,
79 GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
aravind sirsikared3413e2016-11-11 17:15:10 +053080 GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020081 GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
82};
83
Maxe66de5b2017-01-05 18:26:58 +010084extern const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[];
85
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020086enum gprs_rlcmac_tbf_ul_ack_state {
87 GPRS_RLCMAC_UL_ACK_NONE = 0,
88 GPRS_RLCMAC_UL_ACK_SEND_ACK, /* send acknowledge on next RTS */
89 GPRS_RLCMAC_UL_ACK_WAIT_ACK, /* wait for PACKET CONTROL ACK */
90};
91
Max088c7df2018-01-23 20:16:23 +010092extern const struct value_string gprs_rlcmac_tbf_ul_ack_state_names[];
93
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020094enum gprs_rlcmac_tbf_direction {
95 GPRS_RLCMAC_DL_TBF,
96 GPRS_RLCMAC_UL_TBF
97};
98
Maxd0532b52017-12-13 18:27:32 +010099enum tbf_dl_prio {
100 DL_PRIO_NONE,
101 DL_PRIO_SENT_DATA, /* the data has been sent and not (yet) nacked */
102 DL_PRIO_LOW_AGE, /* the age has reached the first threshold */
103 DL_PRIO_NEW_DATA, /* the data has not been sent yet or nacked */
104 DL_PRIO_HIGH_AGE, /* the age has reached the second threshold */
105 DL_PRIO_CONTROL, /* a control block needs to be sent */
106};
107
sivasankari53950732016-12-08 17:15:17 +0530108enum tbf_counters {
109 TBF_CTR_RLC_NACKED,
110};
111
112enum tbf_gprs_counters {
113 TBF_CTR_GPRS_DL_CS1,
114 TBF_CTR_GPRS_DL_CS2,
115 TBF_CTR_GPRS_DL_CS3,
116 TBF_CTR_GPRS_DL_CS4,
117};
118
119enum tbf_egprs_counters {
120 TBF_CTR_EGPRS_DL_MCS1,
121 TBF_CTR_EGPRS_DL_MCS2,
122 TBF_CTR_EGPRS_DL_MCS3,
123 TBF_CTR_EGPRS_DL_MCS4,
124 TBF_CTR_EGPRS_DL_MCS5,
125 TBF_CTR_EGPRS_DL_MCS6,
126 TBF_CTR_EGPRS_DL_MCS7,
127 TBF_CTR_EGPRS_DL_MCS8,
128 TBF_CTR_EGPRS_DL_MCS9,
129};
130
sivasankarida7250a2016-12-16 12:57:18 +0530131enum tbf_gprs_ul_counters {
132 TBF_CTR_GPRS_UL_CS1,
133 TBF_CTR_GPRS_UL_CS2,
134 TBF_CTR_GPRS_UL_CS3,
135 TBF_CTR_GPRS_UL_CS4,
136};
137
138enum tbf_egprs_ul_counters {
139 TBF_CTR_EGPRS_UL_MCS1,
140 TBF_CTR_EGPRS_UL_MCS2,
141 TBF_CTR_EGPRS_UL_MCS3,
142 TBF_CTR_EGPRS_UL_MCS4,
143 TBF_CTR_EGPRS_UL_MCS5,
144 TBF_CTR_EGPRS_UL_MCS6,
145 TBF_CTR_EGPRS_UL_MCS7,
146 TBF_CTR_EGPRS_UL_MCS8,
147 TBF_CTR_EGPRS_UL_MCS9,
148};
149
Max0524e382018-01-19 18:22:25 +0100150#define LOGPTBF(tbf, level, fmt, args...) LOGP(DTBF, level, "%s " fmt, tbf_name(tbf), ## args)
151#define LOGPTBFUL(tbf, level, fmt, args...) LOGP(DTBFUL, level, "%s " fmt, tbf_name(tbf), ## args)
152#define LOGPTBFDL(tbf, level, fmt, args...) LOGP(DTBFDL, level, "%s " fmt, tbf_name(tbf), ## args)
Maxc21f0072017-12-15 17:36:45 +0100153
Maxee5be3a2017-12-20 17:31:13 +0100154enum tbf_timers {
Maxb2de1f72017-12-20 18:05:29 +0100155 /* internal assign/reject timer */
156 T0,
157
Maxee5be3a2017-12-20 17:31:13 +0100158 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
159 T3169,
160
161 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
162 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
163 T3191,
164
165 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
166 MS for this TBF. */
167 T3193,
168
169 /* Wait for reuse of TFI(s) when there is no response from the MS
170 (radio failure or cell change) for this TBF/MBMS radio bearer. */
171 T3195,
172 T_MAX
173};
174
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200175#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
176#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
177#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
178#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
179#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
180#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
181#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
182#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
183#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
184
Max467f6332017-12-20 18:13:29 +0100185#define T_START(tbf, t, sec, usec, r, f) tbf->t_start(t, sec, usec, r, f, __FILE__, __LINE__)
186
Max2399b1d2018-01-12 15:48:12 +0100187#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100188#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
189#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 +0100190#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Maxcac6b662018-01-24 11:00:17 +0100191#define TBF_POLL_SCHED_SET(t) do { t->poll_sched_set(__FILE__, __LINE__); } while(0)
192#define TBF_POLL_SCHED_UNSET(t) do { t->poll_sched_unset(__FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100193#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 +0100194#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
195#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100196
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200197struct gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200198 gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200199
200 static void free_all(struct gprs_rlcmac_trx *trx);
Holger Hans Peter Freyther4f6a4e5d2013-10-16 17:58:46 +0200201 static void free_all(struct gprs_rlcmac_pdch *pdch);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200202
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200203 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
204 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100205 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
206 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100207 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Maxcac6b662018-01-24 11:00:17 +0100208 bool poll_scheduled() const;
Max2399b1d2018-01-12 15:48:12 +0100209 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100210 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
211 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 +0100212 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100213 void poll_sched_set(const char *file, int line);
214 void poll_sched_unset(const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100215 void check_pending_ass();
Max8dce1de2018-01-02 14:17:04 +0100216 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100217 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100218 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200219 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200220
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100221 const char *name() const;
222
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100223 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
224 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530225 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200226
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200227 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200228 void set_ms(GprsMs *ms);
229
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100230 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100231
Holger Hans Peter Freyther7380bab2013-10-16 18:09:19 +0200232 int rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200233
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200234 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200235 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100236 void stop_timers(const char *reason);
237 bool timers_pending(enum tbf_timers t);
238 void t_stop(enum tbf_timers t, const char *reason);
Max467f6332017-12-20 18:13:29 +0100239 void t_start(enum tbf_timers t, uint32_t sec, uint32_t microsec, const char *reason, bool force,
240 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200241 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200242
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100243 int check_polling(uint32_t fn, uint8_t ts,
244 uint32_t *poll_fn, unsigned int *rrbp);
Maxf60cf622017-07-10 14:40:09 +0200245 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 +0200246 void poll_timeout();
247
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100248 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100249 uint32_t tlli() const;
250 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100251
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200252 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200253 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200254
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100255 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100256 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100257
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100258 const char *imsi() const;
259 void assign_imsi(const char *imsi);
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200260 uint8_t ta() const;
261 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200262 uint8_t ms_class() const;
263 void set_ms_class(uint8_t);
Jacob Erlbeckcb728902016-01-05 15:33:03 +0100264 GprsCodingScheme current_cs() const;
Max869c0c22018-01-03 12:00:36 +0100265 size_t llc_queue_size() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100266
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100267 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200268 uint8_t dl_slots() const;
269 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100270
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100271 bool is_control_ts(uint8_t ts) const;
272
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100273 /* EGPRS */
274 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100275 void disable_egprs();
276
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100277 /* attempt to make things a bit more fair */
278 void rotate_in_list();
279
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200280 LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}
281 const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}
282
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100283 LListHead<gprs_rlcmac_tbf>& list();
284 const LListHead<gprs_rlcmac_tbf>& list() const;
285
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200286 uint32_t state_flags;
287 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200288 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200289 uint8_t first_ts; /* first TS used by TBF */
290 uint8_t first_common_ts; /* first TS that the phone can send and
291 reveive simultaniously */
292 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200293 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100294
295 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200296
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200297 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100298 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200299
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100300 gprs_rlc m_rlc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200301
302 uint8_t n3105; /* N3105 counter */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200303
304 struct osmo_gsm_timer_list gsm_timer;
305 unsigned int fT; /* fTxxxx number */
306 unsigned int num_fT_exp; /* number of consecutive fT expirations */
307
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200308 struct Meas {
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200309 struct timeval rssi_tv; /* timestamp for rssi calculation */
310 int32_t rssi_sum; /* sum of rssi values */
311 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200312
313 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200314 } meas;
315
Daniel Willmann73191a42014-05-30 17:58:00 +0200316 /* Remember if the tbf was in wait_release state when we want to
317 * schedule a new dl assignment */
318 uint8_t was_releasing;
319
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200320 /* Can/should we upgrade this tbf to use multiple slots? */
321 uint8_t upgrade_to_multislot;
322
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200323 /* store the BTS this TBF belongs to */
324 BTS *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200325
Max59e4a4f2017-12-20 18:01:55 +0100326 uint8_t m_n3101; /* N3101 counter */
327
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100328 /*
329 * private fields. We can't make it private as it is breaking the
330 * llist macros.
331 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100332 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100333 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100334
sivasankari53950732016-12-08 17:15:17 +0530335 struct rate_ctr_group *m_ctrs;
336
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200337protected:
338 gprs_rlcmac_bts *bts_data() const;
Max25a3ca42017-12-13 18:47:52 +0100339 void enable_egprs();
Jacob Erlbecke8f5fe52015-12-14 13:23:15 +0100340 int set_tlli_from_ul(uint32_t new_tlli);
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200341 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100342
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200343 gprs_llc_queue *llc_queue();
344 const gprs_llc_queue *llc_queue() const;
345
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200346 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100347
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200348 class GprsMs *m_ms;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200349
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200350 /* Fields to take the TA/MS class values if no MS is associated */
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200351 uint8_t m_ta;
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200352 uint8_t m_ms_class;
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200353
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100354private:
Max50818062017-12-06 13:35:08 +0100355 enum gprs_rlcmac_tbf_state state;
Max0e599802018-01-23 20:09:06 +0100356 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
357 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
Max088c7df2018-01-23 20:16:23 +0100358 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
Maxcac6b662018-01-24 11:00:17 +0100359 enum gprs_rlcmac_tbf_poll_state poll_state;
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100360 LListHead<gprs_rlcmac_tbf> m_list;
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200361 LListHead<gprs_rlcmac_tbf> m_ms_list;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100362 bool m_egprs_enabled;
Maxb2de1f72017-12-20 18:05:29 +0100363 struct osmo_timer_list T[T_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100364 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200365};
366
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +0200367
Daniel Willmann0d12a2f2014-07-10 17:44:07 +0200368struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck86b6f052015-11-27 15:17:34 +0100369 int8_t use_trx, uint8_t ms_class, uint8_t egprs_ms_class,
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200370 uint32_t tlli, uint8_t ta, GprsMs *ms);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200371
Maxe9fe0e32017-09-28 15:56:05 +0200372struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, uint8_t ms_class,
373 uint8_t egprs_ms_class, bool single_slot);
Daniel Willmann48aa0b02014-07-16 18:54:10 +0200374
Maxe9fe0e32017-09-28 15:56:05 +0200375struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_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);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200377
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200378void tbf_free(struct gprs_rlcmac_tbf *tbf);
379
aravind sirsikare9a138e2017-01-24 12:36:08 +0530380struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts,
381 GprsMs *ms, uint32_t tlli, uint8_t trx_no, uint8_t ts_no);
382
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200383int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
384
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200385inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
386{
387 return state == rhs;
388}
389
Max0e599802018-01-23 20:09:06 +0100390inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
391{
392 return dl_ass_state == rhs;
393}
394
395inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
396{
397 return ul_ass_state == rhs;
398}
399
Max088c7df2018-01-23 20:16:23 +0100400inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
401{
402 return ul_ack_state == rhs;
403}
404
Maxcac6b662018-01-24 11:00:17 +0100405inline bool gprs_rlcmac_tbf::poll_scheduled() const
406{
407 return poll_state == GPRS_RLCMAC_POLL_SCHED;
408}
409
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200410inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
411{
412 return state != rhs;
413}
414
Daniel Willmanneb100242014-08-08 11:43:53 +0200415const char *tbf_name(gprs_rlcmac_tbf *tbf);
416
Daniel Willmann08e57c82014-08-15 18:11:57 +0200417inline const char *gprs_rlcmac_tbf::state_name() const
418{
419 return tbf_state_name[state];
420}
421
Max8dce1de2018-01-02 14:17:04 +0100422/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100423inline 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 +0100424{
Max2399b1d2018-01-12 15:48:12 +0100425 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100426 if (check_ccch) {
427 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100428 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100429 } else
430 state_flags |= (1 << state_flag);
431}
432
Max5d7f7572018-01-30 16:56:43 +0100433inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
434{
435 const char *ch = "UNKNOWN";
436 switch (t) {
437 case GPRS_RLCMAC_FLAG_CCCH:
438 if (unset) {
439 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
440 return;
441 } else {
442 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
443 LOGPSRC(DTBF, LOGL_ERROR, file, line,
444 "%s attempted to set ass. type CCCH which is already set.\n",
445 tbf_name(this));
446 }
447 ch = "CCCH";
448 break;
449 case GPRS_RLCMAC_FLAG_PACCH:
450 if (unset) {
451 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
452 return;
453 } else {
454 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
455 LOGPSRC(DTBF, LOGL_ERROR, file, line,
456 "%s attempted to set ass. type PACCH which is already set.\n",
457 tbf_name(this));
458 }
459 ch = "PACCH";
460 break;
461 default:
462 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
463 tbf_name(this), unset ? "un" : "", t);
464 return;
465 }
466
467 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
468 tbf_name(this), unset ? "un" : "", ch,
469 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
470 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
471
472 if (unset) {
473 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
474 state_flags &= ~(1 << t);
475 } else
476 state_flags |= (1 << t);
477}
478
Max2399b1d2018-01-12 15:48:12 +0100479inline 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 +0200480{
Max0524e382018-01-19 18:22:25 +0100481 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200482 tbf_name(this),
483 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200484 state = new_state;
485}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100486
Max0e599802018-01-23 20:09:06 +0100487inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
488{
489 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
490 tbf_name(this),
491 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
492 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
493 dl_ass_state = new_state;
494}
495
496inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
497{
498 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
499 tbf_name(this),
500 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
501 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
502 ul_ass_state = new_state;
503}
504
Max088c7df2018-01-23 20:16:23 +0100505inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
506{
507 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
508 tbf_name(this),
509 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
510 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
511 ul_ack_state = new_state;
512}
513
Maxcac6b662018-01-24 11:00:17 +0100514inline void gprs_rlcmac_tbf::poll_sched_set(const char *file, int line)
515{
516 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_SCHED\n",
517 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
518 poll_state = GPRS_RLCMAC_POLL_SCHED;
519}
520
521inline void gprs_rlcmac_tbf::poll_sched_unset(const char *file, int line)
522{
523 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_NONE\n",
524 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
525 poll_state = GPRS_RLCMAC_POLL_NONE;
526}
527
Max0e599802018-01-23 20:09:06 +0100528inline void gprs_rlcmac_tbf::check_pending_ass()
529{
530 if (ul_ass_state != GPRS_RLCMAC_UL_ASS_NONE)
531 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending uplink assignment in state %s. "
532 "This may not happen, because the assignment message never gets transmitted. "
533 "Please be sure not to free in this state. PLEASE FIX!\n",
534 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state));
535
536 if (dl_ass_state != GPRS_RLCMAC_DL_ASS_NONE)
537 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending downlink assignment in state %s. "
538 "This may not happen, because the assignment message never gets transmitted. "
539 "Please be sure not to free in this state. PLEASE FIX!\n",
540 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state));
541}
542
Max8dce1de2018-01-02 14:17:04 +0100543inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
544{
545 if ((state_flags & (1 << state_flag))) {
546 state_flags &= ~(1 << state_flag);
547 return true;
548 }
549
550 return false;
551}
552
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100553inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
554{
555 return this->m_list;
556}
557
558inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
559{
560 return this->m_list;
561}
562
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200563inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200564{
565 return m_ms;
566}
567
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100568inline bool gprs_rlcmac_tbf::is_tlli_valid() const
569{
Jacob Erlbeck767193e2015-05-20 12:06:46 +0200570 return tlli() != 0;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100571}
572
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100573inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
574{
575 /* The TBF is established or has been assigned by a IMM.ASS for
576 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200577 return state > GPRS_RLCMAC_ASSIGN ||
578 (direction == GPRS_RLCMAC_DL_TBF &&
579 state == GPRS_RLCMAC_ASSIGN &&
580 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100581}
582
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100583inline uint8_t gprs_rlcmac_tbf::tfi() const
584{
585 return m_tfi;
586}
587
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100588inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100589{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100590 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100591}
592
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100593inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
594{
595 return m_egprs_enabled;
596}
597
598inline void gprs_rlcmac_tbf::enable_egprs()
599{
600 m_egprs_enabled = true;
601}
602
603inline void gprs_rlcmac_tbf::disable_egprs()
604{
605 m_egprs_enabled = false;
606}
607
Daniel Willmann078bb712014-07-10 17:44:06 +0200608struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200609 gprs_rlcmac_dl_tbf(BTS *bts);
Maxea98b7d2018-01-04 15:13:27 +0100610 gprs_rlc_dl_window *window();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200611 void cleanup();
Max25a3ca42017-12-13 18:47:52 +0100612 void enable_egprs();
Daniel Willmann30168882014-08-07 12:48:29 +0200613 /* dispatch Unitdata.DL messages */
614 static int handle(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck93990462015-05-15 15:50:43 +0200615 const uint32_t tlli, const uint32_t old_tlli,
616 const char *imsi, const uint8_t ms_class,
Jacob Erlbeck14e00f82015-11-27 18:10:39 +0100617 const uint8_t egprs_ms_class, const uint16_t delay_csec,
618 const uint8_t *data, const uint16_t len);
Daniel Willmann30168882014-08-07 12:48:29 +0200619
Daniel Willmann538ac5b2014-07-30 19:12:27 +0200620 int append_data(const uint8_t ms_class,
621 const uint16_t pdu_delay_csec,
622 const uint8_t *data, const uint16_t len);
623
Max7df82d42017-12-15 11:14:30 +0100624 int rcvd_dl_ack(bool final, uint8_t ssn, uint8_t *rbb);
625 int rcvd_dl_ack(bool final_ack, unsigned first_bsn, struct bitvec *rbb);
Daniel Willmannb8f26012014-07-30 19:12:28 +0200626 struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts);
Maxa10c3982017-07-07 18:25:41 +0200627 void trigger_ass(struct gprs_rlcmac_tbf *old_tbf);
Max8dce1de2018-01-02 14:17:04 +0100628
Maxaae1bfb2017-07-07 13:49:29 +0200629 bool handle_ack_nack();
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100630 void request_dl_ack();
Jacob Erlbeckeceb9102015-03-20 14:41:50 +0100631 bool need_control_ts() const;
632 bool have_data() const;
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100633 int frames_since_last_poll(unsigned fn) const;
Jacob Erlbeck3bed5d12015-03-19 11:22:38 +0100634 int frames_since_last_drain(unsigned fn) const;
635 bool keep_open(unsigned fn) const;
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200636 int release();
Jacob Erlbeckf04a5b32016-01-21 20:42:40 +0100637 int abort();
Maxa4f570f2017-12-15 11:21:57 +0100638 uint16_t window_size() const;
Max9d7357e2017-12-14 15:02:33 +0100639 void set_window_size();
Mrinal Mishraf86307e2016-11-10 18:16:30 +0530640 void update_coding_scheme_counter_dl(const GprsCodingScheme cs);
Aravind Sirsikar8e70bb52016-09-15 17:51:16 +0530641
Daniel Willmanncf706b02014-08-07 17:35:22 +0200642 /* TODO: add the gettimeofday as parameter */
643 struct msgb *llc_dequeue(bssgp_bvc_ctx *bctx);
644
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200645 /* Please note that all variables here will be reset when changing
646 * from WAIT RELEASE back to FLOW state (re-use of TBF).
647 * All states that need reset must be in this struct, so this is why
648 * variables are in both (dl and ul) structs and not outside union.
649 */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200650 int32_t m_tx_counter; /* count all transmitted blocks */
651 uint8_t m_wait_confirm; /* wait for CCCH IMM.ASS cnf */
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100652 bool m_dl_ack_requested;
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100653 int32_t m_last_dl_poll_fn;
Jacob Erlbeck3bed5d12015-03-19 11:22:38 +0100654 int32_t m_last_dl_drained_fn;
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200655
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200656 struct BandWidth {
Daniel Willmann418a4232014-08-08 11:21:04 +0200657 struct timeval dl_bw_tv; /* timestamp for dl bw calculation */
658 uint32_t dl_bw_octets; /* number of octets since bw_tv */
sivasankari53950732016-12-08 17:15:17 +0530659 uint32_t dl_throughput; /* throughput to be displayed in stats */
Daniel Willmann418a4232014-08-08 11:21:04 +0200660
661 struct timeval dl_loss_tv; /* timestamp for loss calculation */
662 uint16_t dl_loss_lost; /* sum of lost packets */
663 uint16_t dl_loss_received; /* sum of received packets */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200664
665 BandWidth();
Daniel Willmann418a4232014-08-08 11:21:04 +0200666 } m_bw;
667
sivasankari53950732016-12-08 17:15:17 +0530668 struct rate_ctr_group *m_dl_gprs_ctrs;
669 struct rate_ctr_group *m_dl_egprs_ctrs;
670
Daniel Willmannb8f26012014-07-30 19:12:28 +0200671protected:
Jacob Erlbeck2db0f082015-09-07 18:49:00 +0200672 struct ana_result {
673 unsigned received_packets;
674 unsigned lost_packets;
675 unsigned received_bytes;
676 unsigned lost_bytes;
677 };
678
Jacob Erlbeckd6752492016-02-02 18:12:46 +0100679 int take_next_bsn(uint32_t fn, int previous_bsn,
Jacob Erlbeck64e7b832016-02-04 15:16:47 +0100680 bool *may_combine);
Jacob Erlbeckd6752492016-02-02 18:12:46 +0100681 bool restart_bsn_cycle();
682 int create_new_bsn(const uint32_t fn, GprsCodingScheme cs);
Daniel Willmannb8f26012014-07-30 19:12:28 +0200683 struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
Jacob Erlbeckbe314d92016-02-02 15:32:10 +0100684 int index, int index2 = -1);
Daniel Willmann30168882014-08-07 12:48:29 +0200685 int update_window(const uint8_t ssn, const uint8_t *rbb);
Jacob Erlbeckeb08f862016-02-05 17:07:12 +0100686 int update_window(unsigned first_bsn, const struct bitvec *rbb);
Daniel Willmann30168882014-08-07 12:48:29 +0200687 int maybe_start_new_window();
688 bool dl_window_stalled() const;
Jacob Erlbeck409efa12015-06-12 14:06:09 +0200689 void reuse_tbf();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200690 void start_llc_timer();
Jacob Erlbeck2db0f082015-09-07 18:49:00 +0200691 int analyse_errors(char *show_rbb, uint8_t ssn, ana_result *res);
Jacob Erlbeck409efa12015-06-12 14:06:09 +0200692 void schedule_next_frame();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200693
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530694 enum egprs_rlc_dl_reseg_bsn_state egprs_dl_get_data
695 (int bsn, uint8_t **block_data);
696 unsigned int get_egprs_dl_spb_status(int bsn);
697 enum egprs_rlcmac_dl_spb get_egprs_dl_spb(int bsn);
698
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200699 struct osmo_timer_list m_llc_timer;
Maxea98b7d2018-01-04 15:13:27 +0100700
701 /* Please note that all variables below will be reset when changing
702 * from WAIT RELEASE back to FLOW state (re-use of TBF).
703 * All states that need reset must be in this struct, so this is why
704 * variables are in both (dl and ul) structs and not outside union.
705 */
706 gprs_rlc_dl_window m_window;
Daniel Willmann078bb712014-07-10 17:44:06 +0200707};
708
709struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200710 gprs_rlcmac_ul_tbf(BTS *bts);
Maxea98b7d2018-01-04 15:13:27 +0100711 gprs_rlc_ul_window *window();
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100712 struct msgb *create_ul_ack(uint32_t fn, uint8_t ts);
Maxfd13f6c2017-07-07 14:29:36 +0200713 bool ctrl_ack_to_toggle();
714 bool handle_ctrl_ack();
Max25a3ca42017-12-13 18:47:52 +0100715 void enable_egprs();
Daniel Willmann350f64d2014-08-07 14:54:11 +0200716 /* blocks were acked */
Jacob Erlbeckb3100e12015-12-14 13:36:13 +0100717 int rcv_data_block_acknowledged(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100718 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +0100719 uint8_t *data, struct pcu_l1_meas *meas);
Jacob Erlbeckb3100e12015-12-14 13:36:13 +0100720
Daniel Willmann350f64d2014-08-07 14:54:11 +0200721
Daniel Willmanne2732e22014-08-07 17:32:01 +0200722 /* TODO: extract LLC class? */
723 int assemble_forward_llc(const gprs_rlc_data *data);
724 int snd_ul_ud();
725
Aravind Sirsikar505a86d2016-07-26 18:26:21 +0530726 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_spb(
727 const struct gprs_rlc_data_info *rlc,
728 struct gprs_rlc_data *block,
729 uint8_t *data, const uint8_t block_idx);
730
731 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_first_seg(
732 const struct gprs_rlc_data_info *rlc,
733 struct gprs_rlc_data *block,
734 uint8_t *data, const uint8_t block_idx);
735
736 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_second_seg(
737 const struct gprs_rlc_data_info *rlc,
738 struct gprs_rlc_data *block,
739 uint8_t *data, const uint8_t block_idx);
740
Maxa4f570f2017-12-15 11:21:57 +0100741 uint16_t window_size() const;
Max9d7357e2017-12-14 15:02:33 +0100742 void set_window_size();
Mrinal Mishraf86307e2016-11-10 18:16:30 +0530743 void update_coding_scheme_counter_ul(const GprsCodingScheme cs);
744
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200745 /* Please note that all variables here will be reset when changing
746 * from WAIT RELEASE back to FLOW state (re-use of TBF).
747 * All states that need reset must be in this struct, so this is why
748 * variables are in both (dl and ul) structs and not outside union.
749 */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200750 int32_t m_rx_counter; /* count all received blocks */
751 uint8_t m_n3103; /* N3103 counter */
752 uint8_t m_usf[8]; /* list USFs per PDCH (timeslot) */
753 uint8_t m_contention_resolution_done; /* set after done */
754 uint8_t m_final_ack_sent; /* set if we sent final ack */
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200755
sivasankarida7250a2016-12-16 12:57:18 +0530756 struct rate_ctr_group *m_ul_gprs_ctrs;
757 struct rate_ctr_group *m_ul_egprs_ctrs;
758
Daniel Willmann350f64d2014-08-07 14:54:11 +0200759protected:
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100760 void maybe_schedule_uplink_acknack(const gprs_rlc_data_info *rlc);
Maxea98b7d2018-01-04 15:13:27 +0100761
762 /* Please note that all variables below will be reset when changing
763 * from WAIT RELEASE back to FLOW state (re-use of TBF).
764 * All states that need reset must be in this struct, so this is why
765 * variables are in both (dl and ul) structs and not outside union.
766 */
767 gprs_rlc_ul_window m_window;
Daniel Willmann078bb712014-07-10 17:44:06 +0200768};
769
Max701afa42017-12-01 17:13:22 +0100770#ifdef __cplusplus
771extern "C" {
772#endif
773void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta);
774void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta);
775#ifdef __cplusplus
776}
777#endif
778
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200779inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
780{
781 return (enum gprs_rlcmac_tbf_direction)
782 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
783}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100784
Maxa4f570f2017-12-15 11:21:57 +0100785inline uint16_t gprs_rlcmac_ul_tbf::window_size() const
786{
787 return m_window.ws();
788}
789
790inline uint16_t gprs_rlcmac_dl_tbf::window_size() const
791{
792 return m_window.ws();
793}
794
Max25a3ca42017-12-13 18:47:52 +0100795inline void gprs_rlcmac_ul_tbf::enable_egprs()
796{
797 m_window.set_sns(RLC_EGPRS_SNS);
798 gprs_rlcmac_tbf::enable_egprs();
799}
800
801inline void gprs_rlcmac_dl_tbf::enable_egprs()
802{
803 m_window.set_sns(RLC_EGPRS_SNS);
804 gprs_rlcmac_tbf::enable_egprs();
805}
806
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100807inline gprs_rlcmac_ul_tbf *as_ul_tbf(gprs_rlcmac_tbf *tbf)
808{
809 if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF)
810 return static_cast<gprs_rlcmac_ul_tbf *>(tbf);
811 else
812 return NULL;
813}
814
815inline gprs_rlcmac_dl_tbf *as_dl_tbf(gprs_rlcmac_tbf *tbf)
816{
817 if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF)
818 return static_cast<gprs_rlcmac_dl_tbf *>(tbf);
819 else
820 return NULL;
821}
822
Max9d7357e2017-12-14 15:02:33 +0100823uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots);
824
Daniel Willmannafa72f52014-01-15 17:06:19 +0100825#endif