blob: 99aba67a39ce02abd96261512d18193f38842108 [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>
37
38#include "coding_scheme.h"
Maxe66de5b2017-01-05 18:26:58 +010039}
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020040
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020041struct bssgp_bvc_ctx;
Jacob Erlbeckfecece02015-05-08 12:13:08 +020042class GprsMs;
Max1187a772018-01-26 13:31:42 +010043struct gprs_rlcmac_bts;
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020044
Vadim Yanitskiycef2f842019-10-09 21:52:50 +070045#endif
46
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020047/*
48 * TBF instance
49 */
50
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020051enum gprs_rlcmac_tbf_state {
52 GPRS_RLCMAC_NULL = 0, /* new created TBF */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +020053 GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020054 GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
55 GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
56 GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
57 GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
58};
59
Maxf60cf622017-07-10 14:40:09 +020060enum gprs_rlcmac_tbf_poll_type {
61 GPRS_RLCMAC_POLL_UL_ASS,
62 GPRS_RLCMAC_POLL_DL_ASS,
63 GPRS_RLCMAC_POLL_UL_ACK,
64 GPRS_RLCMAC_POLL_DL_ACK,
65};
66
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020067enum gprs_rlcmac_tbf_poll_state {
68 GPRS_RLCMAC_POLL_NONE = 0,
69 GPRS_RLCMAC_POLL_SCHED, /* a polling was scheduled */
70};
71
Maxcac6b662018-01-24 11:00:17 +010072extern const struct value_string gprs_rlcmac_tbf_poll_state_names[];
73
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020074enum gprs_rlcmac_tbf_dl_ass_state {
75 GPRS_RLCMAC_DL_ASS_NONE = 0,
76 GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
77 GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
78};
79
Maxe66de5b2017-01-05 18:26:58 +010080extern const struct value_string gprs_rlcmac_tbf_dl_ass_state_names[];
81
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020082enum gprs_rlcmac_tbf_ul_ass_state {
83 GPRS_RLCMAC_UL_ASS_NONE = 0,
84 GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
aravind sirsikared3413e2016-11-11 17:15:10 +053085 GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020086 GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
87};
88
Maxe66de5b2017-01-05 18:26:58 +010089extern const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[];
90
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020091enum gprs_rlcmac_tbf_ul_ack_state {
92 GPRS_RLCMAC_UL_ACK_NONE = 0,
93 GPRS_RLCMAC_UL_ACK_SEND_ACK, /* send acknowledge on next RTS */
94 GPRS_RLCMAC_UL_ACK_WAIT_ACK, /* wait for PACKET CONTROL ACK */
95};
96
Max088c7df2018-01-23 20:16:23 +010097extern const struct value_string gprs_rlcmac_tbf_ul_ack_state_names[];
98
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020099enum gprs_rlcmac_tbf_direction {
100 GPRS_RLCMAC_DL_TBF,
101 GPRS_RLCMAC_UL_TBF
102};
103
Max847ed9f2018-02-20 18:16:11 +0100104enum tbf_rlc_counters {
sivasankari53950732016-12-08 17:15:17 +0530105 TBF_CTR_RLC_NACKED,
106};
107
108enum tbf_gprs_counters {
109 TBF_CTR_GPRS_DL_CS1,
110 TBF_CTR_GPRS_DL_CS2,
111 TBF_CTR_GPRS_DL_CS3,
112 TBF_CTR_GPRS_DL_CS4,
113};
114
115enum tbf_egprs_counters {
116 TBF_CTR_EGPRS_DL_MCS1,
117 TBF_CTR_EGPRS_DL_MCS2,
118 TBF_CTR_EGPRS_DL_MCS3,
119 TBF_CTR_EGPRS_DL_MCS4,
120 TBF_CTR_EGPRS_DL_MCS5,
121 TBF_CTR_EGPRS_DL_MCS6,
122 TBF_CTR_EGPRS_DL_MCS7,
123 TBF_CTR_EGPRS_DL_MCS8,
124 TBF_CTR_EGPRS_DL_MCS9,
125};
126
Max0524e382018-01-19 18:22:25 +0100127#define LOGPTBF(tbf, level, fmt, args...) LOGP(DTBF, level, "%s " fmt, tbf_name(tbf), ## args)
Maxc21f0072017-12-15 17:36:45 +0100128
Maxee5be3a2017-12-20 17:31:13 +0100129enum tbf_timers {
Maxb2de1f72017-12-20 18:05:29 +0100130 /* internal assign/reject timer */
131 T0,
132
Maxee5be3a2017-12-20 17:31:13 +0100133 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
134 T3169,
135
136 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
137 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
138 T3191,
139
140 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
141 MS for this TBF. */
142 T3193,
143
144 /* Wait for reuse of TFI(s) when there is no response from the MS
145 (radio failure or cell change) for this TBF/MBMS radio bearer. */
146 T3195,
147 T_MAX
148};
149
Max847ed9f2018-02-20 18:16:11 +0100150enum tbf_counters { /* TBF counters from 3GPP TS 44.060 §13.4 */
151 /* counters are reset when: */
152 N3101, /* received a valid data block from mobile station in a block assigned for this USF */
153 N3103, /* transmitting the final PACKET UPLINK ACK/NACK message */
154 N3105, /* after sending a RRBP field in the downlink RLC data block, receives a valid RLC/MAC control message */
155 N_MAX
156};
157
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200158#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
159#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
160#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
161#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
162#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
163#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
164#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
165#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
166#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
167
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200168#define T_START(tbf, t, T, r, f) tbf->t_start(t, T, r, f, __FILE__, __LINE__)
Max467f6332017-12-20 18:13:29 +0100169
Max2399b1d2018-01-12 15:48:12 +0100170#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100171#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
172#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 +0100173#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Maxcac6b662018-01-24 11:00:17 +0100174#define TBF_POLL_SCHED_SET(t) do { t->poll_sched_set(__FILE__, __LINE__); } while(0)
175#define TBF_POLL_SCHED_UNSET(t) do { t->poll_sched_unset(__FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100176#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 +0100177#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
178#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100179
Vadim Yanitskiycef2f842019-10-09 21:52:50 +0700180#ifdef __cplusplus
181
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200182struct gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200183 gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200184
185 static void free_all(struct gprs_rlcmac_trx *trx);
Holger Hans Peter Freyther4f6a4e5d2013-10-16 17:58:46 +0200186 static void free_all(struct gprs_rlcmac_pdch *pdch);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200187
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200188 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
189 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100190 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
191 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100192 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Maxcac6b662018-01-24 11:00:17 +0100193 bool poll_scheduled() const;
Max2399b1d2018-01-12 15:48:12 +0100194 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100195 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
196 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 +0100197 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100198 void poll_sched_set(const char *file, int line);
199 void poll_sched_unset(const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100200 void check_pending_ass();
Max8dce1de2018-01-02 14:17:04 +0100201 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100202 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100203 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200204 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200205
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100206 const char *name() const;
207
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100208 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
209 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530210 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200211
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200212 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200213 void set_ms(GprsMs *ms);
214
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100215 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100216
Pau Espin Pedrolcd6c4662020-09-22 13:41:00 +0200217 std::string rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200218
Max847ed9f2018-02-20 18:16:11 +0100219 bool n_inc(enum tbf_counters n);
220 void n_reset(enum tbf_counters n);
221
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200222 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200223 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100224 void stop_timers(const char *reason);
225 bool timers_pending(enum tbf_timers t);
226 void t_stop(enum tbf_timers t, const char *reason);
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200227 void t_start(enum tbf_timers t, int T, const char *reason, bool force,
Max467f6332017-12-20 18:13:29 +0100228 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200229 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200230
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100231 int check_polling(uint32_t fn, uint8_t ts,
232 uint32_t *poll_fn, unsigned int *rrbp);
Maxf60cf622017-07-10 14:40:09 +0200233 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 +0200234 void poll_timeout();
235
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100236 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100237 uint32_t tlli() const;
238 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100239
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200240 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200241 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200242
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100243 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100244 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100245
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100246 const char *imsi() const;
247 void assign_imsi(const char *imsi);
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200248 uint8_t ta() const;
249 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200250 uint8_t ms_class() const;
251 void set_ms_class(uint8_t);
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200252 enum CodingScheme current_cs() const;
Max869c0c22018-01-03 12:00:36 +0100253 size_t llc_queue_size() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100254
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100255 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200256 uint8_t dl_slots() const;
257 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100258
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100259 bool is_control_ts(uint8_t ts) const;
260
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100261 /* EGPRS */
262 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100263 void disable_egprs();
264
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100265 /* attempt to make things a bit more fair */
266 void rotate_in_list();
267
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200268 LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}
269 const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}
270
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100271 LListHead<gprs_rlcmac_tbf>& list();
272 const LListHead<gprs_rlcmac_tbf>& list() const;
273
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200274 uint32_t state_flags;
275 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200276 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200277 uint8_t first_ts; /* first TS used by TBF */
278 uint8_t first_common_ts; /* first TS that the phone can send and
279 reveive simultaniously */
280 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200281 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100282
283 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200284
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200285 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100286 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200287
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100288 gprs_rlc m_rlc;
Max847ed9f2018-02-20 18:16:11 +0100289
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200290 struct osmo_gsm_timer_list gsm_timer;
291 unsigned int fT; /* fTxxxx number */
292 unsigned int num_fT_exp; /* number of consecutive fT expirations */
293
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200294 struct Meas {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200295 struct timespec rssi_tv; /* timestamp for rssi calculation */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200296 int32_t rssi_sum; /* sum of rssi values */
297 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200298
299 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200300 } meas;
301
Daniel Willmann73191a42014-05-30 17:58:00 +0200302 /* Remember if the tbf was in wait_release state when we want to
303 * schedule a new dl assignment */
304 uint8_t was_releasing;
305
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200306 /* Can/should we upgrade this tbf to use multiple slots? */
307 uint8_t upgrade_to_multislot;
308
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200309 /* store the BTS this TBF belongs to */
310 BTS *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200311
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100312 /*
313 * private fields. We can't make it private as it is breaking the
314 * llist macros.
315 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100316 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100317 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100318
sivasankari53950732016-12-08 17:15:17 +0530319 struct rate_ctr_group *m_ctrs;
320
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200321protected:
322 gprs_rlcmac_bts *bts_data() const;
Max25a3ca42017-12-13 18:47:52 +0100323 void enable_egprs();
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200324 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100325
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200326 gprs_llc_queue *llc_queue();
327 const gprs_llc_queue *llc_queue() const;
328
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200329 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100330
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200331 class GprsMs *m_ms;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200332
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200333 /* Fields to take the TA/MS class values if no MS is associated */
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200334 uint8_t m_ta;
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200335 uint8_t m_ms_class;
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200336
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100337private:
Max50818062017-12-06 13:35:08 +0100338 enum gprs_rlcmac_tbf_state state;
Max0e599802018-01-23 20:09:06 +0100339 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
340 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
Max088c7df2018-01-23 20:16:23 +0100341 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
Maxcac6b662018-01-24 11:00:17 +0100342 enum gprs_rlcmac_tbf_poll_state poll_state;
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100343 LListHead<gprs_rlcmac_tbf> m_list;
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200344 LListHead<gprs_rlcmac_tbf> m_ms_list;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100345 bool m_egprs_enabled;
Pau Espin Pedrolef1fe582019-09-05 14:40:24 +0200346 struct osmo_timer_list Tarr[T_MAX];
347 uint8_t Narr[N_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100348 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200349};
350
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +0200351
Pau Espin Pedrol17402a52020-05-08 17:44:33 +0200352struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts, GprsMs *ms,
Pau Espin Pedrol5dc6e462020-05-12 19:27:16 +0200353 int8_t use_trx, uint32_t tlli);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200354
Pau Espin Pedrol17402a52020-05-08 17:44:33 +0200355struct 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 +0200356
Pau Espin Pedrol322456e2020-05-08 18:15:59 +0200357struct 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 +0200358
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200359void tbf_free(struct gprs_rlcmac_tbf *tbf);
360
aravind sirsikare9a138e2017-01-24 12:36:08 +0530361struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts,
362 GprsMs *ms, uint32_t tlli, uint8_t trx_no, uint8_t ts_no);
363
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200364int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
365
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200366inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
367{
368 return state == rhs;
369}
370
Max0e599802018-01-23 20:09:06 +0100371inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
372{
373 return dl_ass_state == rhs;
374}
375
376inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
377{
378 return ul_ass_state == rhs;
379}
380
Max088c7df2018-01-23 20:16:23 +0100381inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
382{
383 return ul_ack_state == rhs;
384}
385
Maxcac6b662018-01-24 11:00:17 +0100386inline bool gprs_rlcmac_tbf::poll_scheduled() const
387{
388 return poll_state == GPRS_RLCMAC_POLL_SCHED;
389}
390
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200391inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
392{
393 return state != rhs;
394}
395
Daniel Willmanneb100242014-08-08 11:43:53 +0200396const char *tbf_name(gprs_rlcmac_tbf *tbf);
397
Daniel Willmann08e57c82014-08-15 18:11:57 +0200398inline const char *gprs_rlcmac_tbf::state_name() const
399{
400 return tbf_state_name[state];
401}
402
Max8dce1de2018-01-02 14:17:04 +0100403/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100404inline 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 +0100405{
Max2399b1d2018-01-12 15:48:12 +0100406 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100407 if (check_ccch) {
408 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100409 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100410 } else
411 state_flags |= (1 << state_flag);
412}
413
Max5d7f7572018-01-30 16:56:43 +0100414inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
415{
416 const char *ch = "UNKNOWN";
417 switch (t) {
418 case GPRS_RLCMAC_FLAG_CCCH:
419 if (unset) {
420 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
421 return;
422 } else {
423 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
424 LOGPSRC(DTBF, LOGL_ERROR, file, line,
425 "%s attempted to set ass. type CCCH which is already set.\n",
426 tbf_name(this));
427 }
428 ch = "CCCH";
429 break;
430 case GPRS_RLCMAC_FLAG_PACCH:
431 if (unset) {
432 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
433 return;
434 } else {
435 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
436 LOGPSRC(DTBF, LOGL_ERROR, file, line,
437 "%s attempted to set ass. type PACCH which is already set.\n",
438 tbf_name(this));
439 }
440 ch = "PACCH";
441 break;
442 default:
443 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
444 tbf_name(this), unset ? "un" : "", t);
445 return;
446 }
447
448 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
449 tbf_name(this), unset ? "un" : "", ch,
450 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
451 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
452
453 if (unset) {
454 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
455 state_flags &= ~(1 << t);
456 } else
457 state_flags |= (1 << t);
458}
459
Max2399b1d2018-01-12 15:48:12 +0100460inline 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 +0200461{
Max0524e382018-01-19 18:22:25 +0100462 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200463 tbf_name(this),
464 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200465 state = new_state;
466}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100467
Max0e599802018-01-23 20:09:06 +0100468inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
469{
470 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
471 tbf_name(this),
472 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
473 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
474 dl_ass_state = new_state;
475}
476
477inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
478{
479 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
480 tbf_name(this),
481 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
482 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
483 ul_ass_state = new_state;
484}
485
Max088c7df2018-01-23 20:16:23 +0100486inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
487{
488 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
489 tbf_name(this),
490 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
491 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
492 ul_ack_state = new_state;
493}
494
Maxcac6b662018-01-24 11:00:17 +0100495inline void gprs_rlcmac_tbf::poll_sched_set(const char *file, int line)
496{
497 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_SCHED\n",
498 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
499 poll_state = GPRS_RLCMAC_POLL_SCHED;
500}
501
502inline void gprs_rlcmac_tbf::poll_sched_unset(const char *file, int line)
503{
504 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_NONE\n",
505 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
506 poll_state = GPRS_RLCMAC_POLL_NONE;
507}
508
Max0e599802018-01-23 20:09:06 +0100509inline void gprs_rlcmac_tbf::check_pending_ass()
510{
511 if (ul_ass_state != GPRS_RLCMAC_UL_ASS_NONE)
512 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending uplink assignment in state %s. "
513 "This may not happen, because the assignment message never gets transmitted. "
514 "Please be sure not to free in this state. PLEASE FIX!\n",
515 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state));
516
517 if (dl_ass_state != GPRS_RLCMAC_DL_ASS_NONE)
518 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending downlink assignment in state %s. "
519 "This may not happen, because the assignment message never gets transmitted. "
520 "Please be sure not to free in this state. PLEASE FIX!\n",
521 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state));
522}
523
Max8dce1de2018-01-02 14:17:04 +0100524inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
525{
526 if ((state_flags & (1 << state_flag))) {
527 state_flags &= ~(1 << state_flag);
528 return true;
529 }
530
531 return false;
532}
533
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100534inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
535{
536 return this->m_list;
537}
538
539inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
540{
541 return this->m_list;
542}
543
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200544inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200545{
546 return m_ms;
547}
548
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100549inline bool gprs_rlcmac_tbf::is_tlli_valid() const
550{
Jacob Erlbeck767193e2015-05-20 12:06:46 +0200551 return tlli() != 0;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100552}
553
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100554inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
555{
556 /* The TBF is established or has been assigned by a IMM.ASS for
557 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200558 return state > GPRS_RLCMAC_ASSIGN ||
559 (direction == GPRS_RLCMAC_DL_TBF &&
560 state == GPRS_RLCMAC_ASSIGN &&
561 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100562}
563
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100564inline uint8_t gprs_rlcmac_tbf::tfi() const
565{
566 return m_tfi;
567}
568
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100569inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100570{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100571 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100572}
573
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100574inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
575{
576 return m_egprs_enabled;
577}
578
579inline void gprs_rlcmac_tbf::enable_egprs()
580{
581 m_egprs_enabled = true;
582}
583
584inline void gprs_rlcmac_tbf::disable_egprs()
585{
586 m_egprs_enabled = false;
587}
588
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200589inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
590{
591 return (enum gprs_rlcmac_tbf_direction)
592 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
593}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100594
Max9d7357e2017-12-14 15:02:33 +0100595uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots);
596
Daniel Willmannafa72f52014-01-15 17:06:19 +0100597#endif