blob: 17f5b1856c931026a4c52773d883d85249220342 [file] [log] [blame]
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +02001/*
2 * Copyright (C) 2013 by Holger Hans Peter Freyther
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#pragma once
20
Daniel Willmannafa72f52014-01-15 17:06:19 +010021#ifdef __cplusplus
22
Pau Espin Pedrolcd6c4662020-09-22 13:41:00 +020023#include <string>
24
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +010025#include "llc.h"
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010026#include "rlc.h"
Jacob Erlbeck6835cea2015-08-21 15:24:02 +020027#include "cxx_linuxlist.h"
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010028#include "pcu_utils.h"
Daniel Willmanneb100242014-08-08 11:43:53 +020029#include <gprs_debug.h>
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020030#include <stdint.h>
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +020031
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010032struct bssgp_bvc_ctx;
33struct gprs_rlcmac_bts;
34
35#endif
36
37struct GprsMs;
38
39#ifdef __cplusplus
Maxe66de5b2017-01-05 18:26:58 +010040extern "C" {
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010041#endif
Maxe66de5b2017-01-05 18:26:58 +010042#include <osmocom/core/utils.h>
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +020043#include <osmocom/core/linuxlist.h>
44#include <osmocom/core/logging.h>
45#include <osmocom/core/timer.h>
Vadim Yanitskiycb988942020-11-08 13:27:35 +070046#include <osmocom/gsm/gsm48.h>
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +020047
48#include "coding_scheme.h"
Pau Espin Pedrol86580e12021-03-29 18:15:30 +020049#include <pdch_ul_controller.h>
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010050#ifdef __cplusplus
Maxe66de5b2017-01-05 18:26:58 +010051}
Vadim Yanitskiycef2f842019-10-09 21:52:50 +070052#endif
53
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020054/*
55 * TBF instance
56 */
57
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020058enum gprs_rlcmac_tbf_state {
59 GPRS_RLCMAC_NULL = 0, /* new created TBF */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +020060 GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020061 GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
62 GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
63 GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
64 GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
65};
66
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020067enum gprs_rlcmac_tbf_dl_ass_state {
68 GPRS_RLCMAC_DL_ASS_NONE = 0,
69 GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
70 GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
71};
72
Maxe66de5b2017-01-05 18:26:58 +010073extern const struct value_string gprs_rlcmac_tbf_dl_ass_state_names[];
74
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020075enum gprs_rlcmac_tbf_ul_ass_state {
76 GPRS_RLCMAC_UL_ASS_NONE = 0,
77 GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
aravind sirsikared3413e2016-11-11 17:15:10 +053078 GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020079 GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
80};
81
Maxe66de5b2017-01-05 18:26:58 +010082extern const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[];
83
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020084enum gprs_rlcmac_tbf_ul_ack_state {
85 GPRS_RLCMAC_UL_ACK_NONE = 0,
86 GPRS_RLCMAC_UL_ACK_SEND_ACK, /* send acknowledge on next RTS */
87 GPRS_RLCMAC_UL_ACK_WAIT_ACK, /* wait for PACKET CONTROL ACK */
88};
89
Max088c7df2018-01-23 20:16:23 +010090extern const struct value_string gprs_rlcmac_tbf_ul_ack_state_names[];
91
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020092enum gprs_rlcmac_tbf_direction {
93 GPRS_RLCMAC_DL_TBF,
94 GPRS_RLCMAC_UL_TBF
95};
96
Max847ed9f2018-02-20 18:16:11 +010097enum tbf_rlc_counters {
sivasankari53950732016-12-08 17:15:17 +053098 TBF_CTR_RLC_NACKED,
99};
100
101enum tbf_gprs_counters {
102 TBF_CTR_GPRS_DL_CS1,
103 TBF_CTR_GPRS_DL_CS2,
104 TBF_CTR_GPRS_DL_CS3,
105 TBF_CTR_GPRS_DL_CS4,
106};
107
108enum tbf_egprs_counters {
109 TBF_CTR_EGPRS_DL_MCS1,
110 TBF_CTR_EGPRS_DL_MCS2,
111 TBF_CTR_EGPRS_DL_MCS3,
112 TBF_CTR_EGPRS_DL_MCS4,
113 TBF_CTR_EGPRS_DL_MCS5,
114 TBF_CTR_EGPRS_DL_MCS6,
115 TBF_CTR_EGPRS_DL_MCS7,
116 TBF_CTR_EGPRS_DL_MCS8,
117 TBF_CTR_EGPRS_DL_MCS9,
118};
119
Pau Espin Pedrol442198c2020-10-23 22:30:04 +0200120extern const struct rate_ctr_group_desc tbf_ctrg_desc;
121extern unsigned int next_tbf_ctr_group_id;
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
Pau Espin Pedrol4b6f0bf2021-05-10 18:54:52 +0200129 /* Wait contention resolution success on UL TBFs assigned over CCCH */
130 T3141,
131
Maxee5be3a2017-12-20 17:31:13 +0100132 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
133 T3169,
134
135 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
136 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
137 T3191,
138
139 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
140 MS for this TBF. */
141 T3193,
142
143 /* Wait for reuse of TFI(s) when there is no response from the MS
144 (radio failure or cell change) for this TBF/MBMS radio bearer. */
145 T3195,
146 T_MAX
147};
148
Max847ed9f2018-02-20 18:16:11 +0100149enum tbf_counters { /* TBF counters from 3GPP TS 44.060 §13.4 */
150 /* counters are reset when: */
151 N3101, /* received a valid data block from mobile station in a block assigned for this USF */
152 N3103, /* transmitting the final PACKET UPLINK ACK/NACK message */
153 N3105, /* after sending a RRBP field in the downlink RLC data block, receives a valid RLC/MAC control message */
154 N_MAX
155};
156
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200157#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
158#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
159#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
160#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
161#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
162#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
163#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
164#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
165#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
166
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200167#define T_START(tbf, t, T, r, f) tbf->t_start(t, T, r, f, __FILE__, __LINE__)
Max467f6332017-12-20 18:13:29 +0100168
Max2399b1d2018-01-12 15:48:12 +0100169#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100170#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
171#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 +0100172#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100173#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 +0100174#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
175#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100176
Vadim Yanitskiycef2f842019-10-09 21:52:50 +0700177#ifdef __cplusplus
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100178extern "C" {
179#endif
180struct gprs_rlcmac_tbf;
Pau Espin Pedrol57dcde42021-02-01 18:14:23 +0100181const char *tbf_name(const struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100182enum gprs_rlcmac_tbf_state tbf_state(const struct gprs_rlcmac_tbf *tbf);
183enum gprs_rlcmac_tbf_direction tbf_direction(const struct gprs_rlcmac_tbf *tbf);
184void tbf_set_ms(struct gprs_rlcmac_tbf *tbf, struct GprsMs *ms);
185struct llist_head *tbf_ms_list(struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrol2182e622021-01-14 16:48:38 +0100186struct llist_head *tbf_bts_list(struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrol1e77ca82021-01-27 13:22:03 +0100187struct GprsMs *tbf_ms(const struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100188bool tbf_timers_pending(struct gprs_rlcmac_tbf *tbf, enum tbf_timers t);
189void tbf_free(struct gprs_rlcmac_tbf *tbf);
190struct gprs_llc *tbf_llc(struct gprs_rlcmac_tbf *tbf);
191uint8_t tbf_first_common_ts(const struct gprs_rlcmac_tbf *tbf);
192uint8_t tbf_dl_slots(const struct gprs_rlcmac_tbf *tbf);
193uint8_t tbf_ul_slots(const struct gprs_rlcmac_tbf *tbf);
194bool tbf_is_tfi_assigned(const struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrolc0a250d2021-01-21 18:46:13 +0100195uint8_t tbf_tfi(const struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100196int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrol952cb3d2021-02-01 14:52:48 +0100197int tbf_check_polling(const struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts, uint32_t *poll_fn, unsigned int *rrbp);
Pau Espin Pedrol86580e12021-03-29 18:15:30 +0200198void tbf_set_polling(struct gprs_rlcmac_tbf *tbf, uint32_t new_poll_fn, uint8_t ts, enum pdch_ulc_tbf_poll_reason t);
Pau Espin Pedrol16e16782021-03-29 19:10:19 +0200199void tbf_poll_timeout(struct gprs_rlcmac_tbf *tbf, struct gprs_rlcmac_pdch *pdch, uint32_t poll_fn, enum pdch_ulc_tbf_poll_reason reason);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100200#ifdef __cplusplus
201}
202#endif
203
204#ifdef __cplusplus
Vadim Yanitskiycef2f842019-10-09 21:52:50 +0700205
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200206struct gprs_rlcmac_tbf {
Pau Espin Pedrol2182e622021-01-14 16:48:38 +0100207 gprs_rlcmac_tbf(struct gprs_rlcmac_bts *bts_, GprsMs *ms, gprs_rlcmac_tbf_direction dir);
Eric11881672021-01-11 18:49:12 +0100208 virtual ~gprs_rlcmac_tbf() {}
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200209
Pau Espin Pedrolb3f23972020-10-23 21:00:23 +0200210 virtual gprs_rlc_window *window() = 0;
211
Pau Espin Pedrole9f77d32020-10-23 18:41:40 +0200212 int setup(int8_t use_trx, bool single_slot);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200213 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
214 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100215 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
216 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100217 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Max2399b1d2018-01-12 15:48:12 +0100218 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100219 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
220 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 +0100221 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100222 void poll_sched_set(const char *file, int line);
223 void poll_sched_unset(const char *file, int line);
Max8dce1de2018-01-02 14:17:04 +0100224 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100225 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100226 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200227 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200228
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100229 const char *name() const;
230
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100231 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
232 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530233 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200234
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200235 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200236 void set_ms(GprsMs *ms);
237
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100238 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100239
Pau Espin Pedrolcd6c4662020-09-22 13:41:00 +0200240 std::string rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200241
Max847ed9f2018-02-20 18:16:11 +0100242 bool n_inc(enum tbf_counters n);
243 void n_reset(enum tbf_counters n);
244
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200245 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200246 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100247 void stop_timers(const char *reason);
248 bool timers_pending(enum tbf_timers t);
249 void t_stop(enum tbf_timers t, const char *reason);
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200250 void t_start(enum tbf_timers t, int T, const char *reason, bool force,
Max467f6332017-12-20 18:13:29 +0100251 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200252 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200253
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100254 int check_polling(uint32_t fn, uint8_t ts,
Pau Espin Pedrol57dcde42021-02-01 18:14:23 +0100255 uint32_t *poll_fn, unsigned int *rrbp) const;
Pau Espin Pedrol86580e12021-03-29 18:15:30 +0200256 void set_polling(uint32_t poll_fn, uint8_t ts, enum pdch_ulc_tbf_poll_reason reason);
Pau Espin Pedrol16e16782021-03-29 19:10:19 +0200257 void poll_timeout(struct gprs_rlcmac_pdch *pdch, uint32_t poll_fn, enum pdch_ulc_tbf_poll_reason reason);
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200258
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100259 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100260 uint32_t tlli() const;
261 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100262
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200263 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200264 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200265
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100266 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100267 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100268
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100269 const char *imsi() const;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200270 uint8_t ta() const;
271 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200272 uint8_t ms_class() const;
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200273 enum CodingScheme current_cs() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100274
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100275 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200276 uint8_t dl_slots() const;
277 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100278
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100279 bool is_control_ts(uint8_t ts) const;
280
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100281 /* EGPRS */
282 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100283
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100284 /* attempt to make things a bit more fair */
285 void rotate_in_list();
286
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200287 uint32_t state_flags;
288 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200289 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200290 uint8_t first_ts; /* first TS used by TBF */
Pau Espin Pedrol01aef5e2020-09-22 19:08:57 +0200291 uint8_t first_common_ts; /* first TS where the phone can send and
292 receive simultaniously */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200293 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200294 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100295
296 gprs_llc m_llc;
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100297 gprs_rlc m_rlc;
Max847ed9f2018-02-20 18:16:11 +0100298
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200299 unsigned int fT; /* fTxxxx number */
300 unsigned int num_fT_exp; /* number of consecutive fT expirations */
301
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200302 struct Meas {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200303 struct timespec rssi_tv; /* timestamp for rssi calculation */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200304 int32_t rssi_sum; /* sum of rssi values */
305 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200306
307 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200308 } meas;
309
Daniel Willmann73191a42014-05-30 17:58:00 +0200310 /* Remember if the tbf was in wait_release state when we want to
311 * schedule a new dl assignment */
312 uint8_t was_releasing;
313
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200314 /* Can/should we upgrade this tbf to use multiple slots? */
315 uint8_t upgrade_to_multislot;
316
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200317 /* store the BTS this TBF belongs to */
Pau Espin Pedrol2182e622021-01-14 16:48:38 +0100318 struct gprs_rlcmac_bts *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200319
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100320 /*
321 * private fields. We can't make it private as it is breaking the
322 * llist macros.
323 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100324 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100325 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100326
sivasankari53950732016-12-08 17:15:17 +0530327 struct rate_ctr_group *m_ctrs;
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100328 enum gprs_rlcmac_tbf_state state;
329 struct llist_item m_ms_list;
Pau Espin Pedrol2182e622021-01-14 16:48:38 +0100330 struct llist_item m_bts_list;
sivasankari53950732016-12-08 17:15:17 +0530331
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200332protected:
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200333 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100334
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200335 gprs_llc_queue *llc_queue();
336 const gprs_llc_queue *llc_queue() const;
337
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200338 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100339
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100340 struct GprsMs *m_ms;
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100341private:
Pau Espin Pedrole9f77d32020-10-23 18:41:40 +0200342 void enable_egprs();
Max0e599802018-01-23 20:09:06 +0100343 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
344 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
Max088c7df2018-01-23 20:16:23 +0100345 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100346 bool m_egprs_enabled;
Pau Espin Pedrolef1fe582019-09-05 14:40:24 +0200347 struct osmo_timer_list Tarr[T_MAX];
348 uint8_t Narr[N_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100349 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200350};
351
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200352inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
353{
354 return state == rhs;
355}
356
Max0e599802018-01-23 20:09:06 +0100357inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
358{
359 return dl_ass_state == rhs;
360}
361
362inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
363{
364 return ul_ass_state == rhs;
365}
366
Max088c7df2018-01-23 20:16:23 +0100367inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
368{
369 return ul_ack_state == rhs;
370}
371
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200372inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
373{
374 return state != rhs;
375}
376
Daniel Willmann08e57c82014-08-15 18:11:57 +0200377inline const char *gprs_rlcmac_tbf::state_name() const
378{
379 return tbf_state_name[state];
380}
381
Max8dce1de2018-01-02 14:17:04 +0100382/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100383inline 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 +0100384{
Max2399b1d2018-01-12 15:48:12 +0100385 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100386 if (check_ccch) {
387 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100388 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100389 } else
390 state_flags |= (1 << state_flag);
391}
392
Max5d7f7572018-01-30 16:56:43 +0100393inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
394{
395 const char *ch = "UNKNOWN";
396 switch (t) {
397 case GPRS_RLCMAC_FLAG_CCCH:
398 if (unset) {
399 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
400 return;
401 } else {
402 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
403 LOGPSRC(DTBF, LOGL_ERROR, file, line,
404 "%s attempted to set ass. type CCCH which is already set.\n",
405 tbf_name(this));
406 }
407 ch = "CCCH";
408 break;
409 case GPRS_RLCMAC_FLAG_PACCH:
410 if (unset) {
411 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
412 return;
413 } else {
414 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
415 LOGPSRC(DTBF, LOGL_ERROR, file, line,
416 "%s attempted to set ass. type PACCH which is already set.\n",
417 tbf_name(this));
418 }
419 ch = "PACCH";
420 break;
421 default:
422 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
423 tbf_name(this), unset ? "un" : "", t);
424 return;
425 }
426
427 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
428 tbf_name(this), unset ? "un" : "", ch,
429 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
430 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
431
432 if (unset) {
433 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
434 state_flags &= ~(1 << t);
435 } else
436 state_flags |= (1 << t);
437}
438
Max2399b1d2018-01-12 15:48:12 +0100439inline 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 +0200440{
Max0524e382018-01-19 18:22:25 +0100441 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200442 tbf_name(this),
443 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200444 state = new_state;
445}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100446
Max0e599802018-01-23 20:09:06 +0100447inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
448{
449 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
450 tbf_name(this),
451 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
452 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
453 dl_ass_state = new_state;
454}
455
456inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
457{
458 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
459 tbf_name(this),
460 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
461 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
462 ul_ass_state = new_state;
463}
464
Max088c7df2018-01-23 20:16:23 +0100465inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
466{
467 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
468 tbf_name(this),
469 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
470 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
471 ul_ack_state = new_state;
472}
473
Max8dce1de2018-01-02 14:17:04 +0100474inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
475{
476 if ((state_flags & (1 << state_flag))) {
477 state_flags &= ~(1 << state_flag);
478 return true;
479 }
480
481 return false;
482}
483
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200484inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200485{
486 return m_ms;
487}
488
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100489inline bool gprs_rlcmac_tbf::is_tlli_valid() const
490{
Vadim Yanitskiycb988942020-11-08 13:27:35 +0700491 return tlli() != GSM_RESERVED_TMSI;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100492}
493
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100494inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
495{
496 /* The TBF is established or has been assigned by a IMM.ASS for
497 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200498 return state > GPRS_RLCMAC_ASSIGN ||
499 (direction == GPRS_RLCMAC_DL_TBF &&
500 state == GPRS_RLCMAC_ASSIGN &&
501 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100502}
503
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100504inline uint8_t gprs_rlcmac_tbf::tfi() const
505{
506 return m_tfi;
507}
508
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100509inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100510{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100511 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100512}
513
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100514inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
515{
516 return m_egprs_enabled;
517}
518
519inline void gprs_rlcmac_tbf::enable_egprs()
520{
521 m_egprs_enabled = true;
Pau Espin Pedrol7bde60f2020-10-23 21:21:09 +0200522 window()->set_sns(RLC_EGPRS_SNS);
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100523}
524
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200525inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
526{
527 return (enum gprs_rlcmac_tbf_direction)
528 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
529}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100530
Pau Espin Pedrol0ece97d2021-01-18 12:53:54 +0100531uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts, uint8_t slots);
Max9d7357e2017-12-14 15:02:33 +0100532
Daniel Willmannafa72f52014-01-15 17:06:19 +0100533#endif