blob: c97477bcccd5d317279ff024df3a90d87fd8037e [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"
Daniel Willmanneb100242014-08-08 11:43:53 +020028#include <gprs_debug.h>
Max1187a772018-01-26 13:31:42 +010029#include <gsm_timer.h>
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020030#include <stdint.h>
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +020031
Maxe66de5b2017-01-05 18:26:58 +010032extern "C" {
33#include <osmocom/core/utils.h>
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +020034#include <osmocom/core/linuxlist.h>
35#include <osmocom/core/logging.h>
36#include <osmocom/core/timer.h>
Vadim Yanitskiycb988942020-11-08 13:27:35 +070037#include <osmocom/gsm/gsm48.h>
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +020038
39#include "coding_scheme.h"
Maxe66de5b2017-01-05 18:26:58 +010040}
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020041
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020042struct bssgp_bvc_ctx;
Jacob Erlbeckfecece02015-05-08 12:13:08 +020043class GprsMs;
Max1187a772018-01-26 13:31:42 +010044struct gprs_rlcmac_bts;
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020045
Vadim Yanitskiycef2f842019-10-09 21:52:50 +070046#endif
47
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020048/*
49 * TBF instance
50 */
51
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020052enum gprs_rlcmac_tbf_state {
53 GPRS_RLCMAC_NULL = 0, /* new created TBF */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +020054 GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020055 GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
56 GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
57 GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
58 GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
59};
60
Maxf60cf622017-07-10 14:40:09 +020061enum gprs_rlcmac_tbf_poll_type {
62 GPRS_RLCMAC_POLL_UL_ASS,
63 GPRS_RLCMAC_POLL_DL_ASS,
64 GPRS_RLCMAC_POLL_UL_ACK,
65 GPRS_RLCMAC_POLL_DL_ACK,
66};
67
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020068enum gprs_rlcmac_tbf_poll_state {
69 GPRS_RLCMAC_POLL_NONE = 0,
70 GPRS_RLCMAC_POLL_SCHED, /* a polling was scheduled */
71};
72
Maxcac6b662018-01-24 11:00:17 +010073extern const struct value_string gprs_rlcmac_tbf_poll_state_names[];
74
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020075enum gprs_rlcmac_tbf_dl_ass_state {
76 GPRS_RLCMAC_DL_ASS_NONE = 0,
77 GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
78 GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
79};
80
Maxe66de5b2017-01-05 18:26:58 +010081extern const struct value_string gprs_rlcmac_tbf_dl_ass_state_names[];
82
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020083enum gprs_rlcmac_tbf_ul_ass_state {
84 GPRS_RLCMAC_UL_ASS_NONE = 0,
85 GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
aravind sirsikared3413e2016-11-11 17:15:10 +053086 GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020087 GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
88};
89
Maxe66de5b2017-01-05 18:26:58 +010090extern const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[];
91
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020092enum gprs_rlcmac_tbf_ul_ack_state {
93 GPRS_RLCMAC_UL_ACK_NONE = 0,
94 GPRS_RLCMAC_UL_ACK_SEND_ACK, /* send acknowledge on next RTS */
95 GPRS_RLCMAC_UL_ACK_WAIT_ACK, /* wait for PACKET CONTROL ACK */
96};
97
Max088c7df2018-01-23 20:16:23 +010098extern const struct value_string gprs_rlcmac_tbf_ul_ack_state_names[];
99
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200100enum gprs_rlcmac_tbf_direction {
101 GPRS_RLCMAC_DL_TBF,
102 GPRS_RLCMAC_UL_TBF
103};
104
Max847ed9f2018-02-20 18:16:11 +0100105enum tbf_rlc_counters {
sivasankari53950732016-12-08 17:15:17 +0530106 TBF_CTR_RLC_NACKED,
107};
108
109enum tbf_gprs_counters {
110 TBF_CTR_GPRS_DL_CS1,
111 TBF_CTR_GPRS_DL_CS2,
112 TBF_CTR_GPRS_DL_CS3,
113 TBF_CTR_GPRS_DL_CS4,
114};
115
116enum tbf_egprs_counters {
117 TBF_CTR_EGPRS_DL_MCS1,
118 TBF_CTR_EGPRS_DL_MCS2,
119 TBF_CTR_EGPRS_DL_MCS3,
120 TBF_CTR_EGPRS_DL_MCS4,
121 TBF_CTR_EGPRS_DL_MCS5,
122 TBF_CTR_EGPRS_DL_MCS6,
123 TBF_CTR_EGPRS_DL_MCS7,
124 TBF_CTR_EGPRS_DL_MCS8,
125 TBF_CTR_EGPRS_DL_MCS9,
126};
127
Pau Espin Pedrol442198c2020-10-23 22:30:04 +0200128extern const struct rate_ctr_group_desc tbf_ctrg_desc;
129extern unsigned int next_tbf_ctr_group_id;
130
Max0524e382018-01-19 18:22:25 +0100131#define LOGPTBF(tbf, level, fmt, args...) LOGP(DTBF, level, "%s " fmt, tbf_name(tbf), ## args)
Maxc21f0072017-12-15 17:36:45 +0100132
Maxee5be3a2017-12-20 17:31:13 +0100133enum tbf_timers {
Maxb2de1f72017-12-20 18:05:29 +0100134 /* internal assign/reject timer */
135 T0,
136
Maxee5be3a2017-12-20 17:31:13 +0100137 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
138 T3169,
139
140 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
141 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
142 T3191,
143
144 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
145 MS for this TBF. */
146 T3193,
147
148 /* Wait for reuse of TFI(s) when there is no response from the MS
149 (radio failure or cell change) for this TBF/MBMS radio bearer. */
150 T3195,
151 T_MAX
152};
153
Max847ed9f2018-02-20 18:16:11 +0100154enum tbf_counters { /* TBF counters from 3GPP TS 44.060 §13.4 */
155 /* counters are reset when: */
156 N3101, /* received a valid data block from mobile station in a block assigned for this USF */
157 N3103, /* transmitting the final PACKET UPLINK ACK/NACK message */
158 N3105, /* after sending a RRBP field in the downlink RLC data block, receives a valid RLC/MAC control message */
159 N_MAX
160};
161
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200162#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
163#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
164#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
165#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
166#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
167#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
168#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
169#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
170#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
171
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200172#define T_START(tbf, t, T, r, f) tbf->t_start(t, T, r, f, __FILE__, __LINE__)
Max467f6332017-12-20 18:13:29 +0100173
Max2399b1d2018-01-12 15:48:12 +0100174#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100175#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
176#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 +0100177#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Maxcac6b662018-01-24 11:00:17 +0100178#define TBF_POLL_SCHED_SET(t) do { t->poll_sched_set(__FILE__, __LINE__); } while(0)
179#define TBF_POLL_SCHED_UNSET(t) do { t->poll_sched_unset(__FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100180#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 +0100181#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
182#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100183
Vadim Yanitskiycef2f842019-10-09 21:52:50 +0700184#ifdef __cplusplus
185
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200186struct gprs_rlcmac_tbf {
Pau Espin Pedrole9f77d32020-10-23 18:41:40 +0200187 gprs_rlcmac_tbf(BTS *bts_, GprsMs *ms, gprs_rlcmac_tbf_direction dir);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200188
189 static void free_all(struct gprs_rlcmac_trx *trx);
Holger Hans Peter Freyther4f6a4e5d2013-10-16 17:58:46 +0200190 static void free_all(struct gprs_rlcmac_pdch *pdch);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200191
Pau Espin Pedrolb3f23972020-10-23 21:00:23 +0200192 virtual gprs_rlc_window *window() = 0;
193
Pau Espin Pedrole9f77d32020-10-23 18:41:40 +0200194 int setup(int8_t use_trx, bool single_slot);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200195 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
196 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100197 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
198 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100199 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Maxcac6b662018-01-24 11:00:17 +0100200 bool poll_scheduled() const;
Max2399b1d2018-01-12 15:48:12 +0100201 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100202 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
203 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 +0100204 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100205 void poll_sched_set(const char *file, int line);
206 void poll_sched_unset(const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100207 void check_pending_ass();
Max8dce1de2018-01-02 14:17:04 +0100208 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100209 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100210 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200211 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200212
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100213 const char *name() const;
214
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100215 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
216 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530217 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200218
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200219 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200220 void set_ms(GprsMs *ms);
221
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100222 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100223
Pau Espin Pedrolcd6c4662020-09-22 13:41:00 +0200224 std::string rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200225
Max847ed9f2018-02-20 18:16:11 +0100226 bool n_inc(enum tbf_counters n);
227 void n_reset(enum tbf_counters n);
228
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200229 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200230 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100231 void stop_timers(const char *reason);
232 bool timers_pending(enum tbf_timers t);
233 void t_stop(enum tbf_timers t, const char *reason);
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200234 void t_start(enum tbf_timers t, int T, const char *reason, bool force,
Max467f6332017-12-20 18:13:29 +0100235 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200236 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200237
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100238 int check_polling(uint32_t fn, uint8_t ts,
239 uint32_t *poll_fn, unsigned int *rrbp);
Maxf60cf622017-07-10 14:40:09 +0200240 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 +0200241 void poll_timeout();
242
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100243 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100244 uint32_t tlli() const;
245 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100246
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200247 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200248 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200249
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100250 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100251 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100252
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100253 const char *imsi() const;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200254 uint8_t ta() const;
255 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200256 uint8_t ms_class() const;
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200257 enum CodingScheme current_cs() const;
Max869c0c22018-01-03 12:00:36 +0100258 size_t llc_queue_size() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100259
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100260 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200261 uint8_t dl_slots() const;
262 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100263
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100264 bool is_control_ts(uint8_t ts) const;
265
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100266 /* EGPRS */
267 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100268
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100269 /* attempt to make things a bit more fair */
270 void rotate_in_list();
271
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200272 LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}
273 const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}
274
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100275 LListHead<gprs_rlcmac_tbf>& list();
276 const LListHead<gprs_rlcmac_tbf>& list() const;
277
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200278 uint32_t state_flags;
279 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200280 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200281 uint8_t first_ts; /* first TS used by TBF */
Pau Espin Pedrol01aef5e2020-09-22 19:08:57 +0200282 uint8_t first_common_ts; /* first TS where the phone can send and
283 receive simultaniously */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200284 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200285 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100286
287 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200288
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200289 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100290 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200291
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100292 gprs_rlc m_rlc;
Max847ed9f2018-02-20 18:16:11 +0100293
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200294 struct osmo_gsm_timer_list gsm_timer;
295 unsigned int fT; /* fTxxxx number */
296 unsigned int num_fT_exp; /* number of consecutive fT expirations */
297
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200298 struct Meas {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200299 struct timespec rssi_tv; /* timestamp for rssi calculation */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200300 int32_t rssi_sum; /* sum of rssi values */
301 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200302
303 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200304 } meas;
305
Daniel Willmann73191a42014-05-30 17:58:00 +0200306 /* Remember if the tbf was in wait_release state when we want to
307 * schedule a new dl assignment */
308 uint8_t was_releasing;
309
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200310 /* Can/should we upgrade this tbf to use multiple slots? */
311 uint8_t upgrade_to_multislot;
312
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200313 /* store the BTS this TBF belongs to */
314 BTS *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200315
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100316 /*
317 * private fields. We can't make it private as it is breaking the
318 * llist macros.
319 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100320 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100321 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100322
sivasankari53950732016-12-08 17:15:17 +0530323 struct rate_ctr_group *m_ctrs;
324
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200325protected:
326 gprs_rlcmac_bts *bts_data() const;
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200327 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100328
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200329 gprs_llc_queue *llc_queue();
330 const gprs_llc_queue *llc_queue() const;
331
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200332 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100333
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200334 class GprsMs *m_ms;
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100335private:
Pau Espin Pedrole9f77d32020-10-23 18:41:40 +0200336 void enable_egprs();
Max50818062017-12-06 13:35:08 +0100337 enum gprs_rlcmac_tbf_state state;
Max0e599802018-01-23 20:09:06 +0100338 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
339 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
Max088c7df2018-01-23 20:16:23 +0100340 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
Maxcac6b662018-01-24 11:00:17 +0100341 enum gprs_rlcmac_tbf_poll_state poll_state;
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100342 LListHead<gprs_rlcmac_tbf> m_list;
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200343 LListHead<gprs_rlcmac_tbf> m_ms_list;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100344 bool m_egprs_enabled;
Pau Espin Pedrolef1fe582019-09-05 14:40:24 +0200345 struct osmo_timer_list Tarr[T_MAX];
346 uint8_t Narr[N_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100347 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200348};
349
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200350void tbf_free(struct gprs_rlcmac_tbf *tbf);
351
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200352int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
353
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200354inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
355{
356 return state == rhs;
357}
358
Max0e599802018-01-23 20:09:06 +0100359inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
360{
361 return dl_ass_state == rhs;
362}
363
364inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
365{
366 return ul_ass_state == rhs;
367}
368
Max088c7df2018-01-23 20:16:23 +0100369inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
370{
371 return ul_ack_state == rhs;
372}
373
Maxcac6b662018-01-24 11:00:17 +0100374inline bool gprs_rlcmac_tbf::poll_scheduled() const
375{
376 return poll_state == GPRS_RLCMAC_POLL_SCHED;
377}
378
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200379inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
380{
381 return state != rhs;
382}
383
Daniel Willmanneb100242014-08-08 11:43:53 +0200384const char *tbf_name(gprs_rlcmac_tbf *tbf);
385
Daniel Willmann08e57c82014-08-15 18:11:57 +0200386inline const char *gprs_rlcmac_tbf::state_name() const
387{
388 return tbf_state_name[state];
389}
390
Max8dce1de2018-01-02 14:17:04 +0100391/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100392inline 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 +0100393{
Max2399b1d2018-01-12 15:48:12 +0100394 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100395 if (check_ccch) {
396 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100397 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100398 } else
399 state_flags |= (1 << state_flag);
400}
401
Max5d7f7572018-01-30 16:56:43 +0100402inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
403{
404 const char *ch = "UNKNOWN";
405 switch (t) {
406 case GPRS_RLCMAC_FLAG_CCCH:
407 if (unset) {
408 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
409 return;
410 } else {
411 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
412 LOGPSRC(DTBF, LOGL_ERROR, file, line,
413 "%s attempted to set ass. type CCCH which is already set.\n",
414 tbf_name(this));
415 }
416 ch = "CCCH";
417 break;
418 case GPRS_RLCMAC_FLAG_PACCH:
419 if (unset) {
420 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
421 return;
422 } else {
423 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
424 LOGPSRC(DTBF, LOGL_ERROR, file, line,
425 "%s attempted to set ass. type PACCH which is already set.\n",
426 tbf_name(this));
427 }
428 ch = "PACCH";
429 break;
430 default:
431 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
432 tbf_name(this), unset ? "un" : "", t);
433 return;
434 }
435
436 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
437 tbf_name(this), unset ? "un" : "", ch,
438 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
439 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
440
441 if (unset) {
442 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
443 state_flags &= ~(1 << t);
444 } else
445 state_flags |= (1 << t);
446}
447
Max2399b1d2018-01-12 15:48:12 +0100448inline 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 +0200449{
Max0524e382018-01-19 18:22:25 +0100450 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200451 tbf_name(this),
452 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200453 state = new_state;
454}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100455
Max0e599802018-01-23 20:09:06 +0100456inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
457{
458 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
459 tbf_name(this),
460 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
461 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
462 dl_ass_state = new_state;
463}
464
465inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
466{
467 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
468 tbf_name(this),
469 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
470 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
471 ul_ass_state = new_state;
472}
473
Max088c7df2018-01-23 20:16:23 +0100474inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
475{
476 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
477 tbf_name(this),
478 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
479 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
480 ul_ack_state = new_state;
481}
482
Maxcac6b662018-01-24 11:00:17 +0100483inline void gprs_rlcmac_tbf::poll_sched_set(const char *file, int line)
484{
485 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_SCHED\n",
486 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
487 poll_state = GPRS_RLCMAC_POLL_SCHED;
488}
489
490inline void gprs_rlcmac_tbf::poll_sched_unset(const char *file, int line)
491{
492 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_NONE\n",
493 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
494 poll_state = GPRS_RLCMAC_POLL_NONE;
495}
496
Max0e599802018-01-23 20:09:06 +0100497inline void gprs_rlcmac_tbf::check_pending_ass()
498{
499 if (ul_ass_state != GPRS_RLCMAC_UL_ASS_NONE)
500 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending uplink assignment in state %s. "
501 "This may not happen, because the assignment message never gets transmitted. "
502 "Please be sure not to free in this state. PLEASE FIX!\n",
503 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state));
504
505 if (dl_ass_state != GPRS_RLCMAC_DL_ASS_NONE)
506 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending downlink assignment in state %s. "
507 "This may not happen, because the assignment message never gets transmitted. "
508 "Please be sure not to free in this state. PLEASE FIX!\n",
509 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state));
510}
511
Max8dce1de2018-01-02 14:17:04 +0100512inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
513{
514 if ((state_flags & (1 << state_flag))) {
515 state_flags &= ~(1 << state_flag);
516 return true;
517 }
518
519 return false;
520}
521
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100522inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
523{
524 return this->m_list;
525}
526
527inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
528{
529 return this->m_list;
530}
531
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200532inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200533{
534 return m_ms;
535}
536
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100537inline bool gprs_rlcmac_tbf::is_tlli_valid() const
538{
Vadim Yanitskiycb988942020-11-08 13:27:35 +0700539 return tlli() != GSM_RESERVED_TMSI;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100540}
541
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100542inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
543{
544 /* The TBF is established or has been assigned by a IMM.ASS for
545 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200546 return state > GPRS_RLCMAC_ASSIGN ||
547 (direction == GPRS_RLCMAC_DL_TBF &&
548 state == GPRS_RLCMAC_ASSIGN &&
549 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100550}
551
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100552inline uint8_t gprs_rlcmac_tbf::tfi() const
553{
554 return m_tfi;
555}
556
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100557inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100558{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100559 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100560}
561
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100562inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
563{
564 return m_egprs_enabled;
565}
566
567inline void gprs_rlcmac_tbf::enable_egprs()
568{
569 m_egprs_enabled = true;
Pau Espin Pedrol7bde60f2020-10-23 21:21:09 +0200570 window()->set_sns(RLC_EGPRS_SNS);
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100571}
572
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200573inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
574{
575 return (enum gprs_rlcmac_tbf_direction)
576 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
577}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100578
Max9d7357e2017-12-14 15:02:33 +0100579uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots);
580
Daniel Willmannafa72f52014-01-15 17:06:19 +0100581#endif