blob: be3336a93ba49970ee7fd25a74324db1f1527443 [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 <gsm_timer.h>
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020028#include <stdint.h>
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +020029
Maxe66de5b2017-01-05 18:26:58 +010030extern "C" {
31#include <osmocom/core/utils.h>
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +020032#include <osmocom/core/linuxlist.h>
33#include <osmocom/core/logging.h>
34#include <osmocom/core/timer.h>
35
36#include "coding_scheme.h"
Maxe66de5b2017-01-05 18:26:58 +010037}
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020038
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020039struct bssgp_bvc_ctx;
Jacob Erlbeckfecece02015-05-08 12:13:08 +020040class GprsMs;
Max1187a772018-01-26 13:31:42 +010041struct gprs_rlcmac_bts;
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020042
Vadim Yanitskiycef2f842019-10-09 21:52:50 +070043#endif
44
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020045/*
46 * TBF instance
47 */
48
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020049enum gprs_rlcmac_tbf_state {
50 GPRS_RLCMAC_NULL = 0, /* new created TBF */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +020051 GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020052 GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
53 GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
54 GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
55 GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
56};
57
Maxf60cf622017-07-10 14:40:09 +020058enum gprs_rlcmac_tbf_poll_type {
59 GPRS_RLCMAC_POLL_UL_ASS,
60 GPRS_RLCMAC_POLL_DL_ASS,
61 GPRS_RLCMAC_POLL_UL_ACK,
62 GPRS_RLCMAC_POLL_DL_ACK,
63};
64
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020065enum gprs_rlcmac_tbf_poll_state {
66 GPRS_RLCMAC_POLL_NONE = 0,
67 GPRS_RLCMAC_POLL_SCHED, /* a polling was scheduled */
68};
69
Maxcac6b662018-01-24 11:00:17 +010070extern const struct value_string gprs_rlcmac_tbf_poll_state_names[];
71
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020072enum gprs_rlcmac_tbf_dl_ass_state {
73 GPRS_RLCMAC_DL_ASS_NONE = 0,
74 GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
75 GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
76};
77
Maxe66de5b2017-01-05 18:26:58 +010078extern const struct value_string gprs_rlcmac_tbf_dl_ass_state_names[];
79
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020080enum gprs_rlcmac_tbf_ul_ass_state {
81 GPRS_RLCMAC_UL_ASS_NONE = 0,
82 GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
aravind sirsikared3413e2016-11-11 17:15:10 +053083 GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020084 GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
85};
86
Maxe66de5b2017-01-05 18:26:58 +010087extern const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[];
88
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020089enum gprs_rlcmac_tbf_ul_ack_state {
90 GPRS_RLCMAC_UL_ACK_NONE = 0,
91 GPRS_RLCMAC_UL_ACK_SEND_ACK, /* send acknowledge on next RTS */
92 GPRS_RLCMAC_UL_ACK_WAIT_ACK, /* wait for PACKET CONTROL ACK */
93};
94
Max088c7df2018-01-23 20:16:23 +010095extern const struct value_string gprs_rlcmac_tbf_ul_ack_state_names[];
96
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020097enum gprs_rlcmac_tbf_direction {
98 GPRS_RLCMAC_DL_TBF,
99 GPRS_RLCMAC_UL_TBF
100};
101
Max847ed9f2018-02-20 18:16:11 +0100102enum tbf_rlc_counters {
sivasankari53950732016-12-08 17:15:17 +0530103 TBF_CTR_RLC_NACKED,
104};
105
106enum tbf_gprs_counters {
107 TBF_CTR_GPRS_DL_CS1,
108 TBF_CTR_GPRS_DL_CS2,
109 TBF_CTR_GPRS_DL_CS3,
110 TBF_CTR_GPRS_DL_CS4,
111};
112
113enum tbf_egprs_counters {
114 TBF_CTR_EGPRS_DL_MCS1,
115 TBF_CTR_EGPRS_DL_MCS2,
116 TBF_CTR_EGPRS_DL_MCS3,
117 TBF_CTR_EGPRS_DL_MCS4,
118 TBF_CTR_EGPRS_DL_MCS5,
119 TBF_CTR_EGPRS_DL_MCS6,
120 TBF_CTR_EGPRS_DL_MCS7,
121 TBF_CTR_EGPRS_DL_MCS8,
122 TBF_CTR_EGPRS_DL_MCS9,
123};
124
Max0524e382018-01-19 18:22:25 +0100125#define LOGPTBF(tbf, level, fmt, args...) LOGP(DTBF, level, "%s " fmt, tbf_name(tbf), ## args)
Maxc21f0072017-12-15 17:36:45 +0100126
Maxee5be3a2017-12-20 17:31:13 +0100127enum tbf_timers {
Maxb2de1f72017-12-20 18:05:29 +0100128 /* internal assign/reject timer */
129 T0,
130
Maxee5be3a2017-12-20 17:31:13 +0100131 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
132 T3169,
133
134 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
135 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
136 T3191,
137
138 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
139 MS for this TBF. */
140 T3193,
141
142 /* Wait for reuse of TFI(s) when there is no response from the MS
143 (radio failure or cell change) for this TBF/MBMS radio bearer. */
144 T3195,
145 T_MAX
146};
147
Max847ed9f2018-02-20 18:16:11 +0100148enum tbf_counters { /* TBF counters from 3GPP TS 44.060 §13.4 */
149 /* counters are reset when: */
150 N3101, /* received a valid data block from mobile station in a block assigned for this USF */
151 N3103, /* transmitting the final PACKET UPLINK ACK/NACK message */
152 N3105, /* after sending a RRBP field in the downlink RLC data block, receives a valid RLC/MAC control message */
153 N_MAX
154};
155
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200156#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
157#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
158#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
159#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
160#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
161#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
162#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
163#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
164#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
165
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200166#define T_START(tbf, t, T, r, f) tbf->t_start(t, T, r, f, __FILE__, __LINE__)
Max467f6332017-12-20 18:13:29 +0100167
Max2399b1d2018-01-12 15:48:12 +0100168#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100169#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
170#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 +0100171#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Maxcac6b662018-01-24 11:00:17 +0100172#define TBF_POLL_SCHED_SET(t) do { t->poll_sched_set(__FILE__, __LINE__); } while(0)
173#define TBF_POLL_SCHED_UNSET(t) do { t->poll_sched_unset(__FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100174#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 +0100175#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
176#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100177
Vadim Yanitskiycef2f842019-10-09 21:52:50 +0700178#ifdef __cplusplus
179
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200180struct gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200181 gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200182
183 static void free_all(struct gprs_rlcmac_trx *trx);
Holger Hans Peter Freyther4f6a4e5d2013-10-16 17:58:46 +0200184 static void free_all(struct gprs_rlcmac_pdch *pdch);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200185
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200186 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
187 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100188 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
189 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100190 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Maxcac6b662018-01-24 11:00:17 +0100191 bool poll_scheduled() const;
Max2399b1d2018-01-12 15:48:12 +0100192 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100193 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
194 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 +0100195 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100196 void poll_sched_set(const char *file, int line);
197 void poll_sched_unset(const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100198 void check_pending_ass();
Max8dce1de2018-01-02 14:17:04 +0100199 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100200 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100201 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200202 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200203
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100204 const char *name() const;
205
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100206 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
207 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530208 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200209
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200210 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200211 void set_ms(GprsMs *ms);
212
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100213 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100214
Holger Hans Peter Freyther7380bab2013-10-16 18:09:19 +0200215 int rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200216
Max847ed9f2018-02-20 18:16:11 +0100217 bool n_inc(enum tbf_counters n);
218 void n_reset(enum tbf_counters n);
219
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200220 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200221 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100222 void stop_timers(const char *reason);
223 bool timers_pending(enum tbf_timers t);
224 void t_stop(enum tbf_timers t, const char *reason);
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200225 void t_start(enum tbf_timers t, int T, const char *reason, bool force,
Max467f6332017-12-20 18:13:29 +0100226 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200227 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200228
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100229 int check_polling(uint32_t fn, uint8_t ts,
230 uint32_t *poll_fn, unsigned int *rrbp);
Maxf60cf622017-07-10 14:40:09 +0200231 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 +0200232 void poll_timeout();
233
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100234 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100235 uint32_t tlli() const;
236 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100237
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200238 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200239 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200240
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100241 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100242 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100243
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100244 const char *imsi() const;
245 void assign_imsi(const char *imsi);
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200246 uint8_t ta() const;
247 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200248 uint8_t ms_class() const;
249 void set_ms_class(uint8_t);
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200250 enum CodingScheme current_cs() const;
Max869c0c22018-01-03 12:00:36 +0100251 size_t llc_queue_size() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100252
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100253 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200254 uint8_t dl_slots() const;
255 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100256
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100257 bool is_control_ts(uint8_t ts) const;
258
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100259 /* EGPRS */
260 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100261 void disable_egprs();
262
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100263 /* attempt to make things a bit more fair */
264 void rotate_in_list();
265
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200266 LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}
267 const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}
268
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100269 LListHead<gprs_rlcmac_tbf>& list();
270 const LListHead<gprs_rlcmac_tbf>& list() const;
271
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200272 uint32_t state_flags;
273 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200274 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200275 uint8_t first_ts; /* first TS used by TBF */
276 uint8_t first_common_ts; /* first TS that the phone can send and
277 reveive simultaniously */
278 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200279 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100280
281 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200282
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200283 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100284 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200285
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100286 gprs_rlc m_rlc;
Max847ed9f2018-02-20 18:16:11 +0100287
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200288 struct osmo_gsm_timer_list gsm_timer;
289 unsigned int fT; /* fTxxxx number */
290 unsigned int num_fT_exp; /* number of consecutive fT expirations */
291
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200292 struct Meas {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200293 struct timespec rssi_tv; /* timestamp for rssi calculation */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200294 int32_t rssi_sum; /* sum of rssi values */
295 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200296
297 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200298 } meas;
299
Daniel Willmann73191a42014-05-30 17:58:00 +0200300 /* Remember if the tbf was in wait_release state when we want to
301 * schedule a new dl assignment */
302 uint8_t was_releasing;
303
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200304 /* Can/should we upgrade this tbf to use multiple slots? */
305 uint8_t upgrade_to_multislot;
306
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200307 /* store the BTS this TBF belongs to */
308 BTS *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200309
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100310 /*
311 * private fields. We can't make it private as it is breaking the
312 * llist macros.
313 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100314 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100315 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100316
sivasankari53950732016-12-08 17:15:17 +0530317 struct rate_ctr_group *m_ctrs;
318
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200319protected:
320 gprs_rlcmac_bts *bts_data() const;
Max25a3ca42017-12-13 18:47:52 +0100321 void enable_egprs();
Jacob Erlbecke8f5fe52015-12-14 13:23:15 +0100322 int set_tlli_from_ul(uint32_t new_tlli);
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200323 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100324
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200325 gprs_llc_queue *llc_queue();
326 const gprs_llc_queue *llc_queue() const;
327
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200328 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100329
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200330 class GprsMs *m_ms;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200331
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200332 /* Fields to take the TA/MS class values if no MS is associated */
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200333 uint8_t m_ta;
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200334 uint8_t m_ms_class;
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200335
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100336private:
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 Freyther17c31ce2013-08-24 18:31:27 +0200350
Pau Espin Pedrol17402a52020-05-08 17:44:33 +0200351struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts, GprsMs *ms,
Pau Espin Pedrol5dc6e462020-05-12 19:27:16 +0200352 int8_t use_trx, uint32_t tlli);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200353
Pau Espin Pedrol17402a52020-05-08 17:44:33 +0200354struct 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 +0200355
Pau Espin Pedrol322456e2020-05-08 18:15:59 +0200356struct 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 +0200357
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200358void tbf_free(struct gprs_rlcmac_tbf *tbf);
359
aravind sirsikare9a138e2017-01-24 12:36:08 +0530360struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts,
361 GprsMs *ms, uint32_t tlli, uint8_t trx_no, uint8_t ts_no);
362
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200363int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
364
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200365inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
366{
367 return state == rhs;
368}
369
Max0e599802018-01-23 20:09:06 +0100370inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
371{
372 return dl_ass_state == rhs;
373}
374
375inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
376{
377 return ul_ass_state == rhs;
378}
379
Max088c7df2018-01-23 20:16:23 +0100380inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
381{
382 return ul_ack_state == rhs;
383}
384
Maxcac6b662018-01-24 11:00:17 +0100385inline bool gprs_rlcmac_tbf::poll_scheduled() const
386{
387 return poll_state == GPRS_RLCMAC_POLL_SCHED;
388}
389
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200390inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
391{
392 return state != rhs;
393}
394
Daniel Willmanneb100242014-08-08 11:43:53 +0200395const char *tbf_name(gprs_rlcmac_tbf *tbf);
396
Daniel Willmann08e57c82014-08-15 18:11:57 +0200397inline const char *gprs_rlcmac_tbf::state_name() const
398{
399 return tbf_state_name[state];
400}
401
Max8dce1de2018-01-02 14:17:04 +0100402/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100403inline 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 +0100404{
Max2399b1d2018-01-12 15:48:12 +0100405 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100406 if (check_ccch) {
407 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100408 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100409 } else
410 state_flags |= (1 << state_flag);
411}
412
Max5d7f7572018-01-30 16:56:43 +0100413inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
414{
415 const char *ch = "UNKNOWN";
416 switch (t) {
417 case GPRS_RLCMAC_FLAG_CCCH:
418 if (unset) {
419 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
420 return;
421 } else {
422 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
423 LOGPSRC(DTBF, LOGL_ERROR, file, line,
424 "%s attempted to set ass. type CCCH which is already set.\n",
425 tbf_name(this));
426 }
427 ch = "CCCH";
428 break;
429 case GPRS_RLCMAC_FLAG_PACCH:
430 if (unset) {
431 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
432 return;
433 } else {
434 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
435 LOGPSRC(DTBF, LOGL_ERROR, file, line,
436 "%s attempted to set ass. type PACCH which is already set.\n",
437 tbf_name(this));
438 }
439 ch = "PACCH";
440 break;
441 default:
442 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
443 tbf_name(this), unset ? "un" : "", t);
444 return;
445 }
446
447 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
448 tbf_name(this), unset ? "un" : "", ch,
449 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
450 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
451
452 if (unset) {
453 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
454 state_flags &= ~(1 << t);
455 } else
456 state_flags |= (1 << t);
457}
458
Max2399b1d2018-01-12 15:48:12 +0100459inline 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 +0200460{
Max0524e382018-01-19 18:22:25 +0100461 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200462 tbf_name(this),
463 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200464 state = new_state;
465}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100466
Max0e599802018-01-23 20:09:06 +0100467inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
468{
469 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
470 tbf_name(this),
471 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
472 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
473 dl_ass_state = new_state;
474}
475
476inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
477{
478 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
479 tbf_name(this),
480 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
481 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
482 ul_ass_state = new_state;
483}
484
Max088c7df2018-01-23 20:16:23 +0100485inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
486{
487 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
488 tbf_name(this),
489 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
490 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
491 ul_ack_state = new_state;
492}
493
Maxcac6b662018-01-24 11:00:17 +0100494inline void gprs_rlcmac_tbf::poll_sched_set(const char *file, int line)
495{
496 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_SCHED\n",
497 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
498 poll_state = GPRS_RLCMAC_POLL_SCHED;
499}
500
501inline void gprs_rlcmac_tbf::poll_sched_unset(const char *file, int line)
502{
503 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_NONE\n",
504 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
505 poll_state = GPRS_RLCMAC_POLL_NONE;
506}
507
Max0e599802018-01-23 20:09:06 +0100508inline void gprs_rlcmac_tbf::check_pending_ass()
509{
510 if (ul_ass_state != GPRS_RLCMAC_UL_ASS_NONE)
511 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending uplink assignment in state %s. "
512 "This may not happen, because the assignment message never gets transmitted. "
513 "Please be sure not to free in this state. PLEASE FIX!\n",
514 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state));
515
516 if (dl_ass_state != GPRS_RLCMAC_DL_ASS_NONE)
517 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending downlink assignment in state %s. "
518 "This may not happen, because the assignment message never gets transmitted. "
519 "Please be sure not to free in this state. PLEASE FIX!\n",
520 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state));
521}
522
Max8dce1de2018-01-02 14:17:04 +0100523inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
524{
525 if ((state_flags & (1 << state_flag))) {
526 state_flags &= ~(1 << state_flag);
527 return true;
528 }
529
530 return false;
531}
532
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100533inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
534{
535 return this->m_list;
536}
537
538inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
539{
540 return this->m_list;
541}
542
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200543inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200544{
545 return m_ms;
546}
547
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100548inline bool gprs_rlcmac_tbf::is_tlli_valid() const
549{
Jacob Erlbeck767193e2015-05-20 12:06:46 +0200550 return tlli() != 0;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100551}
552
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100553inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
554{
555 /* The TBF is established or has been assigned by a IMM.ASS for
556 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200557 return state > GPRS_RLCMAC_ASSIGN ||
558 (direction == GPRS_RLCMAC_DL_TBF &&
559 state == GPRS_RLCMAC_ASSIGN &&
560 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100561}
562
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100563inline uint8_t gprs_rlcmac_tbf::tfi() const
564{
565 return m_tfi;
566}
567
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100568inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100569{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100570 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100571}
572
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100573inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
574{
575 return m_egprs_enabled;
576}
577
578inline void gprs_rlcmac_tbf::enable_egprs()
579{
580 m_egprs_enabled = true;
581}
582
583inline void gprs_rlcmac_tbf::disable_egprs()
584{
585 m_egprs_enabled = false;
586}
587
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200588inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
589{
590 return (enum gprs_rlcmac_tbf_direction)
591 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
592}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100593
Max9d7357e2017-12-14 15:02:33 +0100594uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots);
595
Daniel Willmannafa72f52014-01-15 17:06:19 +0100596#endif