blob: d767547d94a18c4ba175be502e49e9a8a3d35400 [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
Pau Espin Pedrolcd6c4662020-09-22 13:41:00 +020023#include <string>
24
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +010025#include "llc.h"
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010026#include "rlc.h"
Jacob Erlbeck6835cea2015-08-21 15:24:02 +020027#include "cxx_linuxlist.h"
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010028#include "pcu_utils.h"
Daniel Willmanneb100242014-08-08 11:43:53 +020029#include <gprs_debug.h>
Max1187a772018-01-26 13:31:42 +010030#include <gsm_timer.h>
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020031#include <stdint.h>
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +020032
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010033struct bssgp_bvc_ctx;
34struct gprs_rlcmac_bts;
35
36#endif
37
38struct GprsMs;
39
40#ifdef __cplusplus
Maxe66de5b2017-01-05 18:26:58 +010041extern "C" {
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010042#endif
Maxe66de5b2017-01-05 18:26:58 +010043#include <osmocom/core/utils.h>
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +020044#include <osmocom/core/linuxlist.h>
45#include <osmocom/core/logging.h>
46#include <osmocom/core/timer.h>
Vadim Yanitskiycb988942020-11-08 13:27:35 +070047#include <osmocom/gsm/gsm48.h>
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +020048
49#include "coding_scheme.h"
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010050#ifdef __cplusplus
Maxe66de5b2017-01-05 18:26:58 +010051}
Vadim Yanitskiycef2f842019-10-09 21:52:50 +070052#endif
53
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020054/*
55 * TBF instance
56 */
57
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020058enum gprs_rlcmac_tbf_state {
59 GPRS_RLCMAC_NULL = 0, /* new created TBF */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +020060 GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020061 GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
62 GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
63 GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
64 GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
65};
66
Maxf60cf622017-07-10 14:40:09 +020067enum gprs_rlcmac_tbf_poll_type {
68 GPRS_RLCMAC_POLL_UL_ASS,
69 GPRS_RLCMAC_POLL_DL_ASS,
70 GPRS_RLCMAC_POLL_UL_ACK,
71 GPRS_RLCMAC_POLL_DL_ACK,
72};
73
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020074enum gprs_rlcmac_tbf_poll_state {
75 GPRS_RLCMAC_POLL_NONE = 0,
76 GPRS_RLCMAC_POLL_SCHED, /* a polling was scheduled */
77};
78
Maxcac6b662018-01-24 11:00:17 +010079extern const struct value_string gprs_rlcmac_tbf_poll_state_names[];
80
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020081enum gprs_rlcmac_tbf_dl_ass_state {
82 GPRS_RLCMAC_DL_ASS_NONE = 0,
83 GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
84 GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
85};
86
Maxe66de5b2017-01-05 18:26:58 +010087extern const struct value_string gprs_rlcmac_tbf_dl_ass_state_names[];
88
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020089enum gprs_rlcmac_tbf_ul_ass_state {
90 GPRS_RLCMAC_UL_ASS_NONE = 0,
91 GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
aravind sirsikared3413e2016-11-11 17:15:10 +053092 GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020093 GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
94};
95
Maxe66de5b2017-01-05 18:26:58 +010096extern const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[];
97
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020098enum gprs_rlcmac_tbf_ul_ack_state {
99 GPRS_RLCMAC_UL_ACK_NONE = 0,
100 GPRS_RLCMAC_UL_ACK_SEND_ACK, /* send acknowledge on next RTS */
101 GPRS_RLCMAC_UL_ACK_WAIT_ACK, /* wait for PACKET CONTROL ACK */
102};
103
Max088c7df2018-01-23 20:16:23 +0100104extern const struct value_string gprs_rlcmac_tbf_ul_ack_state_names[];
105
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200106enum gprs_rlcmac_tbf_direction {
107 GPRS_RLCMAC_DL_TBF,
108 GPRS_RLCMAC_UL_TBF
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
Pau Espin Pedrol442198c2020-10-23 22:30:04 +0200134extern const struct rate_ctr_group_desc tbf_ctrg_desc;
135extern unsigned int next_tbf_ctr_group_id;
136
Max0524e382018-01-19 18:22:25 +0100137#define LOGPTBF(tbf, level, fmt, args...) LOGP(DTBF, level, "%s " fmt, tbf_name(tbf), ## args)
Maxc21f0072017-12-15 17:36:45 +0100138
Maxee5be3a2017-12-20 17:31:13 +0100139enum tbf_timers {
Maxb2de1f72017-12-20 18:05:29 +0100140 /* internal assign/reject timer */
141 T0,
142
Maxee5be3a2017-12-20 17:31:13 +0100143 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
144 T3169,
145
146 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
147 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
148 T3191,
149
150 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
151 MS for this TBF. */
152 T3193,
153
154 /* Wait for reuse of TFI(s) when there is no response from the MS
155 (radio failure or cell change) for this TBF/MBMS radio bearer. */
156 T3195,
157 T_MAX
158};
159
Max847ed9f2018-02-20 18:16:11 +0100160enum tbf_counters { /* TBF counters from 3GPP TS 44.060 §13.4 */
161 /* counters are reset when: */
162 N3101, /* received a valid data block from mobile station in a block assigned for this USF */
163 N3103, /* transmitting the final PACKET UPLINK ACK/NACK message */
164 N3105, /* after sending a RRBP field in the downlink RLC data block, receives a valid RLC/MAC control message */
165 N_MAX
166};
167
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200168#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
169#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
170#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
171#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
172#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
173#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
174#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
175#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
176#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
177
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200178#define T_START(tbf, t, T, r, f) tbf->t_start(t, T, r, f, __FILE__, __LINE__)
Max467f6332017-12-20 18:13:29 +0100179
Max2399b1d2018-01-12 15:48:12 +0100180#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100181#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
182#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 +0100183#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Maxcac6b662018-01-24 11:00:17 +0100184#define TBF_POLL_SCHED_SET(t) do { t->poll_sched_set(__FILE__, __LINE__); } while(0)
185#define TBF_POLL_SCHED_UNSET(t) do { t->poll_sched_unset(__FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100186#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 +0100187#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
188#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100189
Vadim Yanitskiycef2f842019-10-09 21:52:50 +0700190#ifdef __cplusplus
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100191extern "C" {
192#endif
193struct gprs_rlcmac_tbf;
194const char *tbf_name(struct gprs_rlcmac_tbf *tbf);
195enum gprs_rlcmac_tbf_state tbf_state(const struct gprs_rlcmac_tbf *tbf);
196enum gprs_rlcmac_tbf_direction tbf_direction(const struct gprs_rlcmac_tbf *tbf);
197void tbf_set_ms(struct gprs_rlcmac_tbf *tbf, struct GprsMs *ms);
198struct llist_head *tbf_ms_list(struct gprs_rlcmac_tbf *tbf);
199struct GprsMs *tbf_ms(struct gprs_rlcmac_tbf *tbf);
200bool tbf_timers_pending(struct gprs_rlcmac_tbf *tbf, enum tbf_timers t);
201void tbf_free(struct gprs_rlcmac_tbf *tbf);
202struct gprs_llc *tbf_llc(struct gprs_rlcmac_tbf *tbf);
203uint8_t tbf_first_common_ts(const struct gprs_rlcmac_tbf *tbf);
204uint8_t tbf_dl_slots(const struct gprs_rlcmac_tbf *tbf);
205uint8_t tbf_ul_slots(const struct gprs_rlcmac_tbf *tbf);
206bool tbf_is_tfi_assigned(const struct gprs_rlcmac_tbf *tbf);
207int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
208#ifdef __cplusplus
209}
210#endif
211
212#ifdef __cplusplus
Vadim Yanitskiycef2f842019-10-09 21:52:50 +0700213
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200214struct gprs_rlcmac_tbf {
Pau Espin Pedrole9f77d32020-10-23 18:41:40 +0200215 gprs_rlcmac_tbf(BTS *bts_, GprsMs *ms, gprs_rlcmac_tbf_direction dir);
Eric11881672021-01-11 18:49:12 +0100216 virtual ~gprs_rlcmac_tbf() {}
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200217
218 static void free_all(struct gprs_rlcmac_trx *trx);
Holger Hans Peter Freyther4f6a4e5d2013-10-16 17:58:46 +0200219 static void free_all(struct gprs_rlcmac_pdch *pdch);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200220
Pau Espin Pedrolb3f23972020-10-23 21:00:23 +0200221 virtual gprs_rlc_window *window() = 0;
222
Pau Espin Pedrole9f77d32020-10-23 18:41:40 +0200223 int setup(int8_t use_trx, bool single_slot);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200224 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
225 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100226 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
227 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100228 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Maxcac6b662018-01-24 11:00:17 +0100229 bool poll_scheduled() const;
Max2399b1d2018-01-12 15:48:12 +0100230 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100231 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
232 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 +0100233 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100234 void poll_sched_set(const char *file, int line);
235 void poll_sched_unset(const char *file, int line);
Max8dce1de2018-01-02 14:17:04 +0100236 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100237 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100238 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200239 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200240
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100241 const char *name() const;
242
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100243 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
244 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530245 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200246
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200247 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200248 void set_ms(GprsMs *ms);
249
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100250 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100251
Pau Espin Pedrolcd6c4662020-09-22 13:41:00 +0200252 std::string rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200253
Max847ed9f2018-02-20 18:16:11 +0100254 bool n_inc(enum tbf_counters n);
255 void n_reset(enum tbf_counters n);
256
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200257 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200258 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100259 void stop_timers(const char *reason);
260 bool timers_pending(enum tbf_timers t);
261 void t_stop(enum tbf_timers t, const char *reason);
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200262 void t_start(enum tbf_timers t, int T, const char *reason, bool force,
Max467f6332017-12-20 18:13:29 +0100263 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200264 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200265
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100266 int check_polling(uint32_t fn, uint8_t ts,
267 uint32_t *poll_fn, unsigned int *rrbp);
Maxf60cf622017-07-10 14:40:09 +0200268 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 +0200269 void poll_timeout();
270
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100271 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100272 uint32_t tlli() const;
273 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100274
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200275 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200276 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200277
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100278 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100279 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100280
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100281 const char *imsi() const;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200282 uint8_t ta() const;
283 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200284 uint8_t ms_class() const;
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200285 enum CodingScheme current_cs() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100286
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100287 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200288 uint8_t dl_slots() const;
289 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100290
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100291 bool is_control_ts(uint8_t ts) const;
292
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100293 /* EGPRS */
294 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100295
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100296 /* attempt to make things a bit more fair */
297 void rotate_in_list();
298
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100299 LListHead<gprs_rlcmac_tbf>& list();
300 const LListHead<gprs_rlcmac_tbf>& list() const;
301
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200302 uint32_t state_flags;
303 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200304 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200305 uint8_t first_ts; /* first TS used by TBF */
Pau Espin Pedrol01aef5e2020-09-22 19:08:57 +0200306 uint8_t first_common_ts; /* first TS where the phone can send and
307 receive simultaniously */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200308 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200309 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100310
311 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200312
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200313 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100314 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200315
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100316 gprs_rlc m_rlc;
Max847ed9f2018-02-20 18:16:11 +0100317
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200318 struct osmo_gsm_timer_list gsm_timer;
319 unsigned int fT; /* fTxxxx number */
320 unsigned int num_fT_exp; /* number of consecutive fT expirations */
321
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200322 struct Meas {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200323 struct timespec rssi_tv; /* timestamp for rssi calculation */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200324 int32_t rssi_sum; /* sum of rssi values */
325 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200326
327 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200328 } meas;
329
Daniel Willmann73191a42014-05-30 17:58:00 +0200330 /* Remember if the tbf was in wait_release state when we want to
331 * schedule a new dl assignment */
332 uint8_t was_releasing;
333
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200334 /* Can/should we upgrade this tbf to use multiple slots? */
335 uint8_t upgrade_to_multislot;
336
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200337 /* store the BTS this TBF belongs to */
338 BTS *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200339
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100340 /*
341 * private fields. We can't make it private as it is breaking the
342 * llist macros.
343 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100344 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100345 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100346
sivasankari53950732016-12-08 17:15:17 +0530347 struct rate_ctr_group *m_ctrs;
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100348 enum gprs_rlcmac_tbf_state state;
349 struct llist_item m_ms_list;
sivasankari53950732016-12-08 17:15:17 +0530350
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200351protected:
352 gprs_rlcmac_bts *bts_data() const;
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200353 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100354
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200355 gprs_llc_queue *llc_queue();
356 const gprs_llc_queue *llc_queue() const;
357
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200358 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100359
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100360 struct GprsMs *m_ms;
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100361private:
Pau Espin Pedrole9f77d32020-10-23 18:41:40 +0200362 void enable_egprs();
Max0e599802018-01-23 20:09:06 +0100363 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
364 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
Max088c7df2018-01-23 20:16:23 +0100365 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
Maxcac6b662018-01-24 11:00:17 +0100366 enum gprs_rlcmac_tbf_poll_state poll_state;
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100367 LListHead<gprs_rlcmac_tbf> m_list;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100368 bool m_egprs_enabled;
Pau Espin Pedrolef1fe582019-09-05 14:40:24 +0200369 struct osmo_timer_list Tarr[T_MAX];
370 uint8_t Narr[N_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100371 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200372};
373
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200374inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
375{
376 return state == rhs;
377}
378
Max0e599802018-01-23 20:09:06 +0100379inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
380{
381 return dl_ass_state == rhs;
382}
383
384inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
385{
386 return ul_ass_state == rhs;
387}
388
Max088c7df2018-01-23 20:16:23 +0100389inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
390{
391 return ul_ack_state == rhs;
392}
393
Maxcac6b662018-01-24 11:00:17 +0100394inline bool gprs_rlcmac_tbf::poll_scheduled() const
395{
396 return poll_state == GPRS_RLCMAC_POLL_SCHED;
397}
398
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200399inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
400{
401 return state != rhs;
402}
403
Daniel Willmann08e57c82014-08-15 18:11:57 +0200404inline const char *gprs_rlcmac_tbf::state_name() const
405{
406 return tbf_state_name[state];
407}
408
Max8dce1de2018-01-02 14:17:04 +0100409/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100410inline 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 +0100411{
Max2399b1d2018-01-12 15:48:12 +0100412 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100413 if (check_ccch) {
414 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100415 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100416 } else
417 state_flags |= (1 << state_flag);
418}
419
Max5d7f7572018-01-30 16:56:43 +0100420inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
421{
422 const char *ch = "UNKNOWN";
423 switch (t) {
424 case GPRS_RLCMAC_FLAG_CCCH:
425 if (unset) {
426 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
427 return;
428 } else {
429 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
430 LOGPSRC(DTBF, LOGL_ERROR, file, line,
431 "%s attempted to set ass. type CCCH which is already set.\n",
432 tbf_name(this));
433 }
434 ch = "CCCH";
435 break;
436 case GPRS_RLCMAC_FLAG_PACCH:
437 if (unset) {
438 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
439 return;
440 } else {
441 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
442 LOGPSRC(DTBF, LOGL_ERROR, file, line,
443 "%s attempted to set ass. type PACCH which is already set.\n",
444 tbf_name(this));
445 }
446 ch = "PACCH";
447 break;
448 default:
449 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
450 tbf_name(this), unset ? "un" : "", t);
451 return;
452 }
453
454 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
455 tbf_name(this), unset ? "un" : "", ch,
456 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
457 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
458
459 if (unset) {
460 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
461 state_flags &= ~(1 << t);
462 } else
463 state_flags |= (1 << t);
464}
465
Max2399b1d2018-01-12 15:48:12 +0100466inline 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 +0200467{
Max0524e382018-01-19 18:22:25 +0100468 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200469 tbf_name(this),
470 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200471 state = new_state;
472}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100473
Max0e599802018-01-23 20:09:06 +0100474inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
475{
476 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
477 tbf_name(this),
478 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
479 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
480 dl_ass_state = new_state;
481}
482
483inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
484{
485 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
486 tbf_name(this),
487 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
488 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
489 ul_ass_state = new_state;
490}
491
Max088c7df2018-01-23 20:16:23 +0100492inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
493{
494 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
495 tbf_name(this),
496 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
497 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
498 ul_ack_state = new_state;
499}
500
Maxcac6b662018-01-24 11:00:17 +0100501inline void gprs_rlcmac_tbf::poll_sched_set(const char *file, int line)
502{
503 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_SCHED\n",
504 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
505 poll_state = GPRS_RLCMAC_POLL_SCHED;
506}
507
508inline void gprs_rlcmac_tbf::poll_sched_unset(const char *file, int line)
509{
510 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_NONE\n",
511 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
512 poll_state = GPRS_RLCMAC_POLL_NONE;
513}
514
Max8dce1de2018-01-02 14:17:04 +0100515inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
516{
517 if ((state_flags & (1 << state_flag))) {
518 state_flags &= ~(1 << state_flag);
519 return true;
520 }
521
522 return false;
523}
524
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100525inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
526{
527 return this->m_list;
528}
529
530inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
531{
532 return this->m_list;
533}
534
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200535inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200536{
537 return m_ms;
538}
539
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100540inline bool gprs_rlcmac_tbf::is_tlli_valid() const
541{
Vadim Yanitskiycb988942020-11-08 13:27:35 +0700542 return tlli() != GSM_RESERVED_TMSI;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100543}
544
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100545inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
546{
547 /* The TBF is established or has been assigned by a IMM.ASS for
548 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200549 return state > GPRS_RLCMAC_ASSIGN ||
550 (direction == GPRS_RLCMAC_DL_TBF &&
551 state == GPRS_RLCMAC_ASSIGN &&
552 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100553}
554
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100555inline uint8_t gprs_rlcmac_tbf::tfi() const
556{
557 return m_tfi;
558}
559
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100560inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100561{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100562 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100563}
564
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100565inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
566{
567 return m_egprs_enabled;
568}
569
570inline void gprs_rlcmac_tbf::enable_egprs()
571{
572 m_egprs_enabled = true;
Pau Espin Pedrol7bde60f2020-10-23 21:21:09 +0200573 window()->set_sns(RLC_EGPRS_SNS);
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100574}
575
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200576inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
577{
578 return (enum gprs_rlcmac_tbf_direction)
579 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
580}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100581
Max9d7357e2017-12-14 15:02:33 +0100582uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots);
583
Daniel Willmannafa72f52014-01-15 17:06:19 +0100584#endif