blob: 2b4cf6df57c1b445009f5df21b65e9909284eff7 [file] [log] [blame]
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +02001/*
2 * Copyright (C) 2013 by Holger Hans Peter Freyther
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#pragma once
20
Daniel Willmannafa72f52014-01-15 17:06:19 +010021#ifdef __cplusplus
22
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +010023#include "llc.h"
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010024#include "rlc.h"
Jacob Erlbeck6835cea2015-08-21 15:24:02 +020025#include "cxx_linuxlist.h"
Daniel Willmanneb100242014-08-08 11:43:53 +020026#include <gprs_debug.h>
Max1187a772018-01-26 13:31:42 +010027#include <gprs_coding_scheme.h>
28#include <gsm_timer.h>
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020029#include <stdint.h>
Maxe66de5b2017-01-05 18:26:58 +010030extern "C" {
31#include <osmocom/core/utils.h>
Max1187a772018-01-26 13:31:42 +010032 #include <osmocom/core/linuxlist.h>
33 #include <osmocom/core/logging.h>
34 #include <osmocom/core/timer.h>
Maxe66de5b2017-01-05 18:26:58 +010035}
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020036
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020037struct bssgp_bvc_ctx;
Jacob Erlbeckfecece02015-05-08 12:13:08 +020038class GprsMs;
Max1187a772018-01-26 13:31:42 +010039struct gprs_rlcmac_bts;
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020040
Vadim Yanitskiycef2f842019-10-09 21:52:50 +070041#endif
42
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020043/*
44 * TBF instance
45 */
46
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020047enum gprs_rlcmac_tbf_state {
48 GPRS_RLCMAC_NULL = 0, /* new created TBF */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +020049 GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020050 GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
51 GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
52 GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
53 GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
54};
55
Maxf60cf622017-07-10 14:40:09 +020056enum gprs_rlcmac_tbf_poll_type {
57 GPRS_RLCMAC_POLL_UL_ASS,
58 GPRS_RLCMAC_POLL_DL_ASS,
59 GPRS_RLCMAC_POLL_UL_ACK,
60 GPRS_RLCMAC_POLL_DL_ACK,
61};
62
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020063enum gprs_rlcmac_tbf_poll_state {
64 GPRS_RLCMAC_POLL_NONE = 0,
65 GPRS_RLCMAC_POLL_SCHED, /* a polling was scheduled */
66};
67
Maxcac6b662018-01-24 11:00:17 +010068extern const struct value_string gprs_rlcmac_tbf_poll_state_names[];
69
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020070enum gprs_rlcmac_tbf_dl_ass_state {
71 GPRS_RLCMAC_DL_ASS_NONE = 0,
72 GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
73 GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
74};
75
Maxe66de5b2017-01-05 18:26:58 +010076extern const struct value_string gprs_rlcmac_tbf_dl_ass_state_names[];
77
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020078enum gprs_rlcmac_tbf_ul_ass_state {
79 GPRS_RLCMAC_UL_ASS_NONE = 0,
80 GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
aravind sirsikared3413e2016-11-11 17:15:10 +053081 GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020082 GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
83};
84
Maxe66de5b2017-01-05 18:26:58 +010085extern const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[];
86
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020087enum gprs_rlcmac_tbf_ul_ack_state {
88 GPRS_RLCMAC_UL_ACK_NONE = 0,
89 GPRS_RLCMAC_UL_ACK_SEND_ACK, /* send acknowledge on next RTS */
90 GPRS_RLCMAC_UL_ACK_WAIT_ACK, /* wait for PACKET CONTROL ACK */
91};
92
Max088c7df2018-01-23 20:16:23 +010093extern const struct value_string gprs_rlcmac_tbf_ul_ack_state_names[];
94
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020095enum gprs_rlcmac_tbf_direction {
96 GPRS_RLCMAC_DL_TBF,
97 GPRS_RLCMAC_UL_TBF
98};
99
Max847ed9f2018-02-20 18:16:11 +0100100enum tbf_rlc_counters {
sivasankari53950732016-12-08 17:15:17 +0530101 TBF_CTR_RLC_NACKED,
102};
103
104enum tbf_gprs_counters {
105 TBF_CTR_GPRS_DL_CS1,
106 TBF_CTR_GPRS_DL_CS2,
107 TBF_CTR_GPRS_DL_CS3,
108 TBF_CTR_GPRS_DL_CS4,
109};
110
111enum tbf_egprs_counters {
112 TBF_CTR_EGPRS_DL_MCS1,
113 TBF_CTR_EGPRS_DL_MCS2,
114 TBF_CTR_EGPRS_DL_MCS3,
115 TBF_CTR_EGPRS_DL_MCS4,
116 TBF_CTR_EGPRS_DL_MCS5,
117 TBF_CTR_EGPRS_DL_MCS6,
118 TBF_CTR_EGPRS_DL_MCS7,
119 TBF_CTR_EGPRS_DL_MCS8,
120 TBF_CTR_EGPRS_DL_MCS9,
121};
122
Max0524e382018-01-19 18:22:25 +0100123#define LOGPTBF(tbf, level, fmt, args...) LOGP(DTBF, level, "%s " fmt, tbf_name(tbf), ## args)
Maxc21f0072017-12-15 17:36:45 +0100124
Maxee5be3a2017-12-20 17:31:13 +0100125enum tbf_timers {
Maxb2de1f72017-12-20 18:05:29 +0100126 /* internal assign/reject timer */
127 T0,
128
Maxee5be3a2017-12-20 17:31:13 +0100129 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
130 T3169,
131
132 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
133 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
134 T3191,
135
136 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
137 MS for this TBF. */
138 T3193,
139
140 /* Wait for reuse of TFI(s) when there is no response from the MS
141 (radio failure or cell change) for this TBF/MBMS radio bearer. */
142 T3195,
143 T_MAX
144};
145
Max847ed9f2018-02-20 18:16:11 +0100146enum tbf_counters { /* TBF counters from 3GPP TS 44.060 ยง13.4 */
147 /* counters are reset when: */
148 N3101, /* received a valid data block from mobile station in a block assigned for this USF */
149 N3103, /* transmitting the final PACKET UPLINK ACK/NACK message */
150 N3105, /* after sending a RRBP field in the downlink RLC data block, receives a valid RLC/MAC control message */
151 N_MAX
152};
153
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200154#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
155#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
156#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
157#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
158#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
159#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
160#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
161#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
162#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
163
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200164#define T_START(tbf, t, T, r, f) tbf->t_start(t, T, r, f, __FILE__, __LINE__)
Max467f6332017-12-20 18:13:29 +0100165
Max2399b1d2018-01-12 15:48:12 +0100166#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100167#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
168#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 +0100169#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Maxcac6b662018-01-24 11:00:17 +0100170#define TBF_POLL_SCHED_SET(t) do { t->poll_sched_set(__FILE__, __LINE__); } while(0)
171#define TBF_POLL_SCHED_UNSET(t) do { t->poll_sched_unset(__FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100172#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 +0100173#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
174#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100175
Vadim Yanitskiycef2f842019-10-09 21:52:50 +0700176#ifdef __cplusplus
177
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200178struct gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200179 gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200180
181 static void free_all(struct gprs_rlcmac_trx *trx);
Holger Hans Peter Freyther4f6a4e5d2013-10-16 17:58:46 +0200182 static void free_all(struct gprs_rlcmac_pdch *pdch);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200183
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200184 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
185 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100186 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
187 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100188 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Maxcac6b662018-01-24 11:00:17 +0100189 bool poll_scheduled() const;
Max2399b1d2018-01-12 15:48:12 +0100190 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100191 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
192 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 +0100193 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100194 void poll_sched_set(const char *file, int line);
195 void poll_sched_unset(const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100196 void check_pending_ass();
Max8dce1de2018-01-02 14:17:04 +0100197 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100198 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100199 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200200 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200201
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100202 const char *name() const;
203
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100204 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
205 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530206 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200207
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200208 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200209 void set_ms(GprsMs *ms);
210
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100211 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100212
Holger Hans Peter Freyther7380bab2013-10-16 18:09:19 +0200213 int rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200214
Max847ed9f2018-02-20 18:16:11 +0100215 bool n_inc(enum tbf_counters n);
216 void n_reset(enum tbf_counters n);
217
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200218 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200219 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100220 void stop_timers(const char *reason);
221 bool timers_pending(enum tbf_timers t);
222 void t_stop(enum tbf_timers t, const char *reason);
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200223 void t_start(enum tbf_timers t, int T, const char *reason, bool force,
Max467f6332017-12-20 18:13:29 +0100224 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200225 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200226
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100227 int check_polling(uint32_t fn, uint8_t ts,
228 uint32_t *poll_fn, unsigned int *rrbp);
Maxf60cf622017-07-10 14:40:09 +0200229 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 +0200230 void poll_timeout();
231
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100232 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100233 uint32_t tlli() const;
234 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100235
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200236 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200237 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200238
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100239 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100240 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100241
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100242 const char *imsi() const;
243 void assign_imsi(const char *imsi);
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200244 uint8_t ta() const;
245 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200246 uint8_t ms_class() const;
247 void set_ms_class(uint8_t);
Jacob Erlbeckcb728902016-01-05 15:33:03 +0100248 GprsCodingScheme current_cs() const;
Max869c0c22018-01-03 12:00:36 +0100249 size_t llc_queue_size() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100250
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100251 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200252 uint8_t dl_slots() const;
253 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100254
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100255 bool is_control_ts(uint8_t ts) const;
256
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100257 /* EGPRS */
258 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100259 void disable_egprs();
260
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100261 /* attempt to make things a bit more fair */
262 void rotate_in_list();
263
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200264 LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}
265 const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}
266
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100267 LListHead<gprs_rlcmac_tbf>& list();
268 const LListHead<gprs_rlcmac_tbf>& list() const;
269
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200270 uint32_t state_flags;
271 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200272 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200273 uint8_t first_ts; /* first TS used by TBF */
274 uint8_t first_common_ts; /* first TS that the phone can send and
275 reveive simultaniously */
276 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200277 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100278
279 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200280
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200281 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100282 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200283
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100284 gprs_rlc m_rlc;
Max847ed9f2018-02-20 18:16:11 +0100285
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200286 struct osmo_gsm_timer_list gsm_timer;
287 unsigned int fT; /* fTxxxx number */
288 unsigned int num_fT_exp; /* number of consecutive fT expirations */
289
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200290 struct Meas {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200291 struct timespec rssi_tv; /* timestamp for rssi calculation */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200292 int32_t rssi_sum; /* sum of rssi values */
293 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200294
295 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200296 } meas;
297
Daniel Willmann73191a42014-05-30 17:58:00 +0200298 /* Remember if the tbf was in wait_release state when we want to
299 * schedule a new dl assignment */
300 uint8_t was_releasing;
301
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200302 /* Can/should we upgrade this tbf to use multiple slots? */
303 uint8_t upgrade_to_multislot;
304
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200305 /* store the BTS this TBF belongs to */
306 BTS *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200307
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100308 /*
309 * private fields. We can't make it private as it is breaking the
310 * llist macros.
311 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100312 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100313 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100314
sivasankari53950732016-12-08 17:15:17 +0530315 struct rate_ctr_group *m_ctrs;
316
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200317protected:
318 gprs_rlcmac_bts *bts_data() const;
Max25a3ca42017-12-13 18:47:52 +0100319 void enable_egprs();
Jacob Erlbecke8f5fe52015-12-14 13:23:15 +0100320 int set_tlli_from_ul(uint32_t new_tlli);
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200321 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100322
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200323 gprs_llc_queue *llc_queue();
324 const gprs_llc_queue *llc_queue() const;
325
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200326 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100327
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200328 class GprsMs *m_ms;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200329
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200330 /* Fields to take the TA/MS class values if no MS is associated */
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200331 uint8_t m_ta;
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200332 uint8_t m_ms_class;
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200333
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100334private:
Max50818062017-12-06 13:35:08 +0100335 enum gprs_rlcmac_tbf_state state;
Max0e599802018-01-23 20:09:06 +0100336 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
337 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
Max088c7df2018-01-23 20:16:23 +0100338 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
Maxcac6b662018-01-24 11:00:17 +0100339 enum gprs_rlcmac_tbf_poll_state poll_state;
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100340 LListHead<gprs_rlcmac_tbf> m_list;
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200341 LListHead<gprs_rlcmac_tbf> m_ms_list;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100342 bool m_egprs_enabled;
Pau Espin Pedrolef1fe582019-09-05 14:40:24 +0200343 struct osmo_timer_list Tarr[T_MAX];
344 uint8_t Narr[N_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100345 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200346};
347
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +0200348
Pau Espin Pedrol17402a52020-05-08 17:44:33 +0200349struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts, GprsMs *ms,
Pau Espin Pedrol5dc6e462020-05-12 19:27:16 +0200350 int8_t use_trx, uint32_t tlli);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200351
Pau Espin Pedrol17402a52020-05-08 17:44:33 +0200352struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, bool single_slot);
Daniel Willmann48aa0b02014-07-16 18:54:10 +0200353
Pau Espin Pedrol322456e2020-05-08 18:15:59 +0200354struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, bool single_slot);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200355
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200356void tbf_free(struct gprs_rlcmac_tbf *tbf);
357
aravind sirsikare9a138e2017-01-24 12:36:08 +0530358struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts,
359 GprsMs *ms, uint32_t tlli, uint8_t trx_no, uint8_t ts_no);
360
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200361int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
362
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200363inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
364{
365 return state == rhs;
366}
367
Max0e599802018-01-23 20:09:06 +0100368inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
369{
370 return dl_ass_state == rhs;
371}
372
373inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
374{
375 return ul_ass_state == rhs;
376}
377
Max088c7df2018-01-23 20:16:23 +0100378inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
379{
380 return ul_ack_state == rhs;
381}
382
Maxcac6b662018-01-24 11:00:17 +0100383inline bool gprs_rlcmac_tbf::poll_scheduled() const
384{
385 return poll_state == GPRS_RLCMAC_POLL_SCHED;
386}
387
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200388inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
389{
390 return state != rhs;
391}
392
Daniel Willmanneb100242014-08-08 11:43:53 +0200393const char *tbf_name(gprs_rlcmac_tbf *tbf);
394
Daniel Willmann08e57c82014-08-15 18:11:57 +0200395inline const char *gprs_rlcmac_tbf::state_name() const
396{
397 return tbf_state_name[state];
398}
399
Max8dce1de2018-01-02 14:17:04 +0100400/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100401inline 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 +0100402{
Max2399b1d2018-01-12 15:48:12 +0100403 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100404 if (check_ccch) {
405 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100406 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100407 } else
408 state_flags |= (1 << state_flag);
409}
410
Max5d7f7572018-01-30 16:56:43 +0100411inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
412{
413 const char *ch = "UNKNOWN";
414 switch (t) {
415 case GPRS_RLCMAC_FLAG_CCCH:
416 if (unset) {
417 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
418 return;
419 } else {
420 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
421 LOGPSRC(DTBF, LOGL_ERROR, file, line,
422 "%s attempted to set ass. type CCCH which is already set.\n",
423 tbf_name(this));
424 }
425 ch = "CCCH";
426 break;
427 case GPRS_RLCMAC_FLAG_PACCH:
428 if (unset) {
429 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
430 return;
431 } else {
432 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
433 LOGPSRC(DTBF, LOGL_ERROR, file, line,
434 "%s attempted to set ass. type PACCH which is already set.\n",
435 tbf_name(this));
436 }
437 ch = "PACCH";
438 break;
439 default:
440 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
441 tbf_name(this), unset ? "un" : "", t);
442 return;
443 }
444
445 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
446 tbf_name(this), unset ? "un" : "", ch,
447 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
448 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
449
450 if (unset) {
451 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
452 state_flags &= ~(1 << t);
453 } else
454 state_flags |= (1 << t);
455}
456
Max2399b1d2018-01-12 15:48:12 +0100457inline 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 +0200458{
Max0524e382018-01-19 18:22:25 +0100459 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200460 tbf_name(this),
461 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200462 state = new_state;
463}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100464
Max0e599802018-01-23 20:09:06 +0100465inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
466{
467 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
468 tbf_name(this),
469 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
470 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
471 dl_ass_state = new_state;
472}
473
474inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
475{
476 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
477 tbf_name(this),
478 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
479 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
480 ul_ass_state = new_state;
481}
482
Max088c7df2018-01-23 20:16:23 +0100483inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
484{
485 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
486 tbf_name(this),
487 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
488 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
489 ul_ack_state = new_state;
490}
491
Maxcac6b662018-01-24 11:00:17 +0100492inline void gprs_rlcmac_tbf::poll_sched_set(const char *file, int line)
493{
494 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_SCHED\n",
495 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
496 poll_state = GPRS_RLCMAC_POLL_SCHED;
497}
498
499inline void gprs_rlcmac_tbf::poll_sched_unset(const char *file, int line)
500{
501 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_NONE\n",
502 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
503 poll_state = GPRS_RLCMAC_POLL_NONE;
504}
505
Max0e599802018-01-23 20:09:06 +0100506inline void gprs_rlcmac_tbf::check_pending_ass()
507{
508 if (ul_ass_state != GPRS_RLCMAC_UL_ASS_NONE)
509 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending uplink assignment in state %s. "
510 "This may not happen, because the assignment message never gets transmitted. "
511 "Please be sure not to free in this state. PLEASE FIX!\n",
512 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state));
513
514 if (dl_ass_state != GPRS_RLCMAC_DL_ASS_NONE)
515 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending downlink assignment in state %s. "
516 "This may not happen, because the assignment message never gets transmitted. "
517 "Please be sure not to free in this state. PLEASE FIX!\n",
518 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state));
519}
520
Max8dce1de2018-01-02 14:17:04 +0100521inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
522{
523 if ((state_flags & (1 << state_flag))) {
524 state_flags &= ~(1 << state_flag);
525 return true;
526 }
527
528 return false;
529}
530
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100531inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
532{
533 return this->m_list;
534}
535
536inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
537{
538 return this->m_list;
539}
540
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200541inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200542{
543 return m_ms;
544}
545
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100546inline bool gprs_rlcmac_tbf::is_tlli_valid() const
547{
Jacob Erlbeck767193e2015-05-20 12:06:46 +0200548 return tlli() != 0;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100549}
550
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100551inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
552{
553 /* The TBF is established or has been assigned by a IMM.ASS for
554 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200555 return state > GPRS_RLCMAC_ASSIGN ||
556 (direction == GPRS_RLCMAC_DL_TBF &&
557 state == GPRS_RLCMAC_ASSIGN &&
558 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100559}
560
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100561inline uint8_t gprs_rlcmac_tbf::tfi() const
562{
563 return m_tfi;
564}
565
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100566inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100567{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100568 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100569}
570
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100571inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
572{
573 return m_egprs_enabled;
574}
575
576inline void gprs_rlcmac_tbf::enable_egprs()
577{
578 m_egprs_enabled = true;
579}
580
581inline void gprs_rlcmac_tbf::disable_egprs()
582{
583 m_egprs_enabled = false;
584}
585
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200586inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
587{
588 return (enum gprs_rlcmac_tbf_direction)
589 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
590}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100591
Max9d7357e2017-12-14 15:02:33 +0100592uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots);
593
Daniel Willmannafa72f52014-01-15 17:06:19 +0100594#endif