blob: 779bc2630548ed5cc30f08b92358722ef8c08d67 [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 Pedrolda971ee2020-12-16 15:59:45 +010049#ifdef __cplusplus
Maxe66de5b2017-01-05 18:26:58 +010050}
Vadim Yanitskiycef2f842019-10-09 21:52:50 +070051#endif
52
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020053/*
54 * TBF instance
55 */
56
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020057enum gprs_rlcmac_tbf_state {
58 GPRS_RLCMAC_NULL = 0, /* new created TBF */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +020059 GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020060 GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
61 GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
62 GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
63 GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
64};
65
Maxf60cf622017-07-10 14:40:09 +020066enum gprs_rlcmac_tbf_poll_type {
67 GPRS_RLCMAC_POLL_UL_ASS,
68 GPRS_RLCMAC_POLL_DL_ASS,
69 GPRS_RLCMAC_POLL_UL_ACK,
70 GPRS_RLCMAC_POLL_DL_ACK,
Pau Espin Pedrol952cb3d2021-02-01 14:52:48 +010071 GPRS_RLCMAC_POLL_CELL_CHG_CONTINUE,
Maxf60cf622017-07-10 14:40:09 +020072};
73
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020074enum gprs_rlcmac_tbf_poll_state {
75 GPRS_RLCMAC_POLL_NONE = 0,
76 GPRS_RLCMAC_POLL_SCHED, /* a polling was scheduled */
77};
78
Maxcac6b662018-01-24 11:00:17 +010079extern const struct value_string gprs_rlcmac_tbf_poll_state_names[];
80
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020081enum gprs_rlcmac_tbf_dl_ass_state {
82 GPRS_RLCMAC_DL_ASS_NONE = 0,
83 GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
84 GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
85};
86
Maxe66de5b2017-01-05 18:26:58 +010087extern const struct value_string gprs_rlcmac_tbf_dl_ass_state_names[];
88
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020089enum gprs_rlcmac_tbf_ul_ass_state {
90 GPRS_RLCMAC_UL_ASS_NONE = 0,
91 GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
aravind sirsikared3413e2016-11-11 17:15:10 +053092 GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020093 GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
94};
95
Maxe66de5b2017-01-05 18:26:58 +010096extern const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[];
97
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020098enum gprs_rlcmac_tbf_ul_ack_state {
99 GPRS_RLCMAC_UL_ACK_NONE = 0,
100 GPRS_RLCMAC_UL_ACK_SEND_ACK, /* send acknowledge on next RTS */
101 GPRS_RLCMAC_UL_ACK_WAIT_ACK, /* wait for PACKET CONTROL ACK */
102};
103
Max088c7df2018-01-23 20:16:23 +0100104extern const struct value_string gprs_rlcmac_tbf_ul_ack_state_names[];
105
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200106enum gprs_rlcmac_tbf_direction {
107 GPRS_RLCMAC_DL_TBF,
108 GPRS_RLCMAC_UL_TBF
109};
110
Max847ed9f2018-02-20 18:16:11 +0100111enum tbf_rlc_counters {
sivasankari53950732016-12-08 17:15:17 +0530112 TBF_CTR_RLC_NACKED,
113};
114
115enum tbf_gprs_counters {
116 TBF_CTR_GPRS_DL_CS1,
117 TBF_CTR_GPRS_DL_CS2,
118 TBF_CTR_GPRS_DL_CS3,
119 TBF_CTR_GPRS_DL_CS4,
120};
121
122enum tbf_egprs_counters {
123 TBF_CTR_EGPRS_DL_MCS1,
124 TBF_CTR_EGPRS_DL_MCS2,
125 TBF_CTR_EGPRS_DL_MCS3,
126 TBF_CTR_EGPRS_DL_MCS4,
127 TBF_CTR_EGPRS_DL_MCS5,
128 TBF_CTR_EGPRS_DL_MCS6,
129 TBF_CTR_EGPRS_DL_MCS7,
130 TBF_CTR_EGPRS_DL_MCS8,
131 TBF_CTR_EGPRS_DL_MCS9,
132};
133
Pau Espin Pedrol442198c2020-10-23 22:30:04 +0200134extern const struct rate_ctr_group_desc tbf_ctrg_desc;
135extern unsigned int next_tbf_ctr_group_id;
136
Max0524e382018-01-19 18:22:25 +0100137#define LOGPTBF(tbf, level, fmt, args...) LOGP(DTBF, level, "%s " fmt, tbf_name(tbf), ## args)
Maxc21f0072017-12-15 17:36:45 +0100138
Maxee5be3a2017-12-20 17:31:13 +0100139enum tbf_timers {
Maxb2de1f72017-12-20 18:05:29 +0100140 /* internal assign/reject timer */
141 T0,
142
Maxee5be3a2017-12-20 17:31:13 +0100143 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
144 T3169,
145
146 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
147 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
148 T3191,
149
150 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
151 MS for this TBF. */
152 T3193,
153
154 /* Wait for reuse of TFI(s) when there is no response from the MS
155 (radio failure or cell change) for this TBF/MBMS radio bearer. */
156 T3195,
157 T_MAX
158};
159
Max847ed9f2018-02-20 18:16:11 +0100160enum tbf_counters { /* TBF counters from 3GPP TS 44.060 §13.4 */
161 /* counters are reset when: */
162 N3101, /* received a valid data block from mobile station in a block assigned for this USF */
163 N3103, /* transmitting the final PACKET UPLINK ACK/NACK message */
164 N3105, /* after sending a RRBP field in the downlink RLC data block, receives a valid RLC/MAC control message */
165 N_MAX
166};
167
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200168#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
169#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
170#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
171#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
172#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
173#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
174#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
175#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
176#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
177
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200178#define T_START(tbf, t, T, r, f) tbf->t_start(t, T, r, f, __FILE__, __LINE__)
Max467f6332017-12-20 18:13:29 +0100179
Max2399b1d2018-01-12 15:48:12 +0100180#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100181#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
182#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 +0100183#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Maxcac6b662018-01-24 11:00:17 +0100184#define TBF_POLL_SCHED_SET(t) do { t->poll_sched_set(__FILE__, __LINE__); } while(0)
185#define TBF_POLL_SCHED_UNSET(t) do { t->poll_sched_unset(__FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100186#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 +0100187#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
188#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100189
Vadim Yanitskiycef2f842019-10-09 21:52:50 +0700190#ifdef __cplusplus
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100191extern "C" {
192#endif
193struct gprs_rlcmac_tbf;
Pau Espin Pedrol57dcde42021-02-01 18:14:23 +0100194const char *tbf_name(const struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100195enum gprs_rlcmac_tbf_state tbf_state(const struct gprs_rlcmac_tbf *tbf);
196enum gprs_rlcmac_tbf_direction tbf_direction(const struct gprs_rlcmac_tbf *tbf);
197void tbf_set_ms(struct gprs_rlcmac_tbf *tbf, struct GprsMs *ms);
198struct llist_head *tbf_ms_list(struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrol2182e622021-01-14 16:48:38 +0100199struct llist_head *tbf_bts_list(struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrol1e77ca82021-01-27 13:22:03 +0100200struct GprsMs *tbf_ms(const struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100201bool tbf_timers_pending(struct gprs_rlcmac_tbf *tbf, enum tbf_timers t);
202void tbf_free(struct gprs_rlcmac_tbf *tbf);
203struct gprs_llc *tbf_llc(struct gprs_rlcmac_tbf *tbf);
204uint8_t tbf_first_common_ts(const struct gprs_rlcmac_tbf *tbf);
205uint8_t tbf_dl_slots(const struct gprs_rlcmac_tbf *tbf);
206uint8_t tbf_ul_slots(const struct gprs_rlcmac_tbf *tbf);
207bool tbf_is_tfi_assigned(const struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrolc0a250d2021-01-21 18:46:13 +0100208uint8_t tbf_tfi(const struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100209int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrol952cb3d2021-02-01 14:52:48 +0100210int tbf_check_polling(const struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts, uint32_t *poll_fn, unsigned int *rrbp);
211void tbf_set_polling(struct gprs_rlcmac_tbf *tbf, uint32_t new_poll_fn, uint8_t ts, enum gprs_rlcmac_tbf_poll_type t);
Pau Espin Pedrol99360a32021-03-09 17:18:12 +0100212void tbf_poll_timeout(struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100213#ifdef __cplusplus
214}
215#endif
216
217#ifdef __cplusplus
Vadim Yanitskiycef2f842019-10-09 21:52:50 +0700218
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200219struct gprs_rlcmac_tbf {
Pau Espin Pedrol2182e622021-01-14 16:48:38 +0100220 gprs_rlcmac_tbf(struct gprs_rlcmac_bts *bts_, GprsMs *ms, gprs_rlcmac_tbf_direction dir);
Eric11881672021-01-11 18:49:12 +0100221 virtual ~gprs_rlcmac_tbf() {}
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200222
Pau Espin Pedrolb3f23972020-10-23 21:00:23 +0200223 virtual gprs_rlc_window *window() = 0;
224
Pau Espin Pedrole9f77d32020-10-23 18:41:40 +0200225 int setup(int8_t use_trx, bool single_slot);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200226 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
227 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100228 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
229 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100230 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Maxcac6b662018-01-24 11:00:17 +0100231 bool poll_scheduled() const;
Max2399b1d2018-01-12 15:48:12 +0100232 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100233 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
234 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 +0100235 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100236 void poll_sched_set(const char *file, int line);
237 void poll_sched_unset(const char *file, int line);
Max8dce1de2018-01-02 14:17:04 +0100238 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100239 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100240 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200241 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200242
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100243 const char *name() const;
244
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100245 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
246 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530247 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200248
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200249 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200250 void set_ms(GprsMs *ms);
251
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100252 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100253
Pau Espin Pedrolcd6c4662020-09-22 13:41:00 +0200254 std::string rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200255
Max847ed9f2018-02-20 18:16:11 +0100256 bool n_inc(enum tbf_counters n);
257 void n_reset(enum tbf_counters n);
258
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200259 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200260 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100261 void stop_timers(const char *reason);
262 bool timers_pending(enum tbf_timers t);
263 void t_stop(enum tbf_timers t, const char *reason);
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200264 void t_start(enum tbf_timers t, int T, const char *reason, bool force,
Max467f6332017-12-20 18:13:29 +0100265 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200266 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200267
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100268 int check_polling(uint32_t fn, uint8_t ts,
Pau Espin Pedrol57dcde42021-02-01 18:14:23 +0100269 uint32_t *poll_fn, unsigned int *rrbp) const;
Maxf60cf622017-07-10 14:40:09 +0200270 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 +0200271 void poll_timeout();
272
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100273 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100274 uint32_t tlli() const;
275 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100276
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200277 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200278 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200279
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100280 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100281 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100282
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100283 const char *imsi() const;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200284 uint8_t ta() const;
285 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200286 uint8_t ms_class() const;
Pau Espin Pedrol2ae83372020-05-18 11:35:35 +0200287 enum CodingScheme current_cs() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100288
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100289 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200290 uint8_t dl_slots() const;
291 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100292
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100293 bool is_control_ts(uint8_t ts) const;
294
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100295 /* EGPRS */
296 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100297
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100298 /* attempt to make things a bit more fair */
299 void rotate_in_list();
300
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200301 uint32_t state_flags;
302 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200303 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200304 uint8_t first_ts; /* first TS used by TBF */
Pau Espin Pedrol01aef5e2020-09-22 19:08:57 +0200305 uint8_t first_common_ts; /* first TS where the phone can send and
306 receive simultaniously */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200307 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200308 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100309
310 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200311
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200312 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100313 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200314
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100315 gprs_rlc m_rlc;
Max847ed9f2018-02-20 18:16:11 +0100316
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200317 unsigned int fT; /* fTxxxx number */
318 unsigned int num_fT_exp; /* number of consecutive fT expirations */
319
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200320 struct Meas {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200321 struct timespec rssi_tv; /* timestamp for rssi calculation */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200322 int32_t rssi_sum; /* sum of rssi values */
323 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200324
325 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200326 } meas;
327
Daniel Willmann73191a42014-05-30 17:58:00 +0200328 /* Remember if the tbf was in wait_release state when we want to
329 * schedule a new dl assignment */
330 uint8_t was_releasing;
331
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200332 /* Can/should we upgrade this tbf to use multiple slots? */
333 uint8_t upgrade_to_multislot;
334
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200335 /* store the BTS this TBF belongs to */
Pau Espin Pedrol2182e622021-01-14 16:48:38 +0100336 struct gprs_rlcmac_bts *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200337
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100338 /*
339 * private fields. We can't make it private as it is breaking the
340 * llist macros.
341 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100342 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100343 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100344
sivasankari53950732016-12-08 17:15:17 +0530345 struct rate_ctr_group *m_ctrs;
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100346 enum gprs_rlcmac_tbf_state state;
347 struct llist_item m_ms_list;
Pau Espin Pedrol2182e622021-01-14 16:48:38 +0100348 struct llist_item m_bts_list;
sivasankari53950732016-12-08 17:15:17 +0530349
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200350protected:
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200351 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100352
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200353 gprs_llc_queue *llc_queue();
354 const gprs_llc_queue *llc_queue() const;
355
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200356 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100357
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100358 struct GprsMs *m_ms;
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100359private:
Pau Espin Pedrole9f77d32020-10-23 18:41:40 +0200360 void enable_egprs();
Max0e599802018-01-23 20:09:06 +0100361 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
362 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
Max088c7df2018-01-23 20:16:23 +0100363 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
Maxcac6b662018-01-24 11:00:17 +0100364 enum gprs_rlcmac_tbf_poll_state poll_state;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100365 bool m_egprs_enabled;
Pau Espin Pedrolef1fe582019-09-05 14:40:24 +0200366 struct osmo_timer_list Tarr[T_MAX];
367 uint8_t Narr[N_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100368 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200369};
370
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200371inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
372{
373 return state == rhs;
374}
375
Max0e599802018-01-23 20:09:06 +0100376inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
377{
378 return dl_ass_state == rhs;
379}
380
381inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
382{
383 return ul_ass_state == rhs;
384}
385
Max088c7df2018-01-23 20:16:23 +0100386inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
387{
388 return ul_ack_state == rhs;
389}
390
Maxcac6b662018-01-24 11:00:17 +0100391inline bool gprs_rlcmac_tbf::poll_scheduled() const
392{
393 return poll_state == GPRS_RLCMAC_POLL_SCHED;
394}
395
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200396inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
397{
398 return state != rhs;
399}
400
Daniel Willmann08e57c82014-08-15 18:11:57 +0200401inline const char *gprs_rlcmac_tbf::state_name() const
402{
403 return tbf_state_name[state];
404}
405
Max8dce1de2018-01-02 14:17:04 +0100406/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100407inline 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 +0100408{
Max2399b1d2018-01-12 15:48:12 +0100409 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100410 if (check_ccch) {
411 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100412 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100413 } else
414 state_flags |= (1 << state_flag);
415}
416
Max5d7f7572018-01-30 16:56:43 +0100417inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
418{
419 const char *ch = "UNKNOWN";
420 switch (t) {
421 case GPRS_RLCMAC_FLAG_CCCH:
422 if (unset) {
423 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
424 return;
425 } else {
426 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
427 LOGPSRC(DTBF, LOGL_ERROR, file, line,
428 "%s attempted to set ass. type CCCH which is already set.\n",
429 tbf_name(this));
430 }
431 ch = "CCCH";
432 break;
433 case GPRS_RLCMAC_FLAG_PACCH:
434 if (unset) {
435 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
436 return;
437 } else {
438 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
439 LOGPSRC(DTBF, LOGL_ERROR, file, line,
440 "%s attempted to set ass. type PACCH which is already set.\n",
441 tbf_name(this));
442 }
443 ch = "PACCH";
444 break;
445 default:
446 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
447 tbf_name(this), unset ? "un" : "", t);
448 return;
449 }
450
451 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
452 tbf_name(this), unset ? "un" : "", ch,
453 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
454 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
455
456 if (unset) {
457 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
458 state_flags &= ~(1 << t);
459 } else
460 state_flags |= (1 << t);
461}
462
Max2399b1d2018-01-12 15:48:12 +0100463inline 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 +0200464{
Max0524e382018-01-19 18:22:25 +0100465 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200466 tbf_name(this),
467 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200468 state = new_state;
469}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100470
Max0e599802018-01-23 20:09:06 +0100471inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
472{
473 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
474 tbf_name(this),
475 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
476 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
477 dl_ass_state = new_state;
478}
479
480inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
481{
482 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
483 tbf_name(this),
484 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
485 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
486 ul_ass_state = new_state;
487}
488
Max088c7df2018-01-23 20:16:23 +0100489inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
490{
491 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
492 tbf_name(this),
493 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
494 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
495 ul_ack_state = new_state;
496}
497
Maxcac6b662018-01-24 11:00:17 +0100498inline void gprs_rlcmac_tbf::poll_sched_set(const char *file, int line)
499{
500 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_SCHED\n",
501 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
502 poll_state = GPRS_RLCMAC_POLL_SCHED;
503}
504
505inline void gprs_rlcmac_tbf::poll_sched_unset(const char *file, int line)
506{
507 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_NONE\n",
508 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
509 poll_state = GPRS_RLCMAC_POLL_NONE;
510}
511
Max8dce1de2018-01-02 14:17:04 +0100512inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
513{
514 if ((state_flags & (1 << state_flag))) {
515 state_flags &= ~(1 << state_flag);
516 return true;
517 }
518
519 return false;
520}
521
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200522inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200523{
524 return m_ms;
525}
526
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100527inline bool gprs_rlcmac_tbf::is_tlli_valid() const
528{
Vadim Yanitskiycb988942020-11-08 13:27:35 +0700529 return tlli() != GSM_RESERVED_TMSI;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100530}
531
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100532inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
533{
534 /* The TBF is established or has been assigned by a IMM.ASS for
535 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200536 return state > GPRS_RLCMAC_ASSIGN ||
537 (direction == GPRS_RLCMAC_DL_TBF &&
538 state == GPRS_RLCMAC_ASSIGN &&
539 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100540}
541
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100542inline uint8_t gprs_rlcmac_tbf::tfi() const
543{
544 return m_tfi;
545}
546
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100547inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100548{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100549 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100550}
551
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100552inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
553{
554 return m_egprs_enabled;
555}
556
557inline void gprs_rlcmac_tbf::enable_egprs()
558{
559 m_egprs_enabled = true;
Pau Espin Pedrol7bde60f2020-10-23 21:21:09 +0200560 window()->set_sns(RLC_EGPRS_SNS);
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100561}
562
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200563inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
564{
565 return (enum gprs_rlcmac_tbf_direction)
566 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
567}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100568
Pau Espin Pedrol0ece97d2021-01-18 12:53:54 +0100569uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts, uint8_t slots);
Max9d7357e2017-12-14 15:02:33 +0100570
Daniel Willmannafa72f52014-01-15 17:06:19 +0100571#endif