blob: fd65b205ee3e9f927a8b99436a99d4f818da845c [file] [log] [blame]
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +02001/*
2 * Copyright (C) 2013 by Holger Hans Peter Freyther
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#pragma once
20
Daniel Willmannafa72f52014-01-15 17:06:19 +010021#ifdef __cplusplus
22
Holger Hans Peter Freytherbe570812013-11-07 08:01:49 +010023#include "llc.h"
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010024#include "rlc.h"
Jacob Erlbeck6835cea2015-08-21 15:24:02 +020025#include "cxx_linuxlist.h"
Daniel Willmanneb100242014-08-08 11:43:53 +020026#include <gprs_debug.h>
Max1187a772018-01-26 13:31:42 +010027#include <gprs_coding_scheme.h>
28#include <gsm_timer.h>
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020029#include <stdint.h>
Maxe66de5b2017-01-05 18:26:58 +010030extern "C" {
31#include <osmocom/core/utils.h>
Max1187a772018-01-26 13:31:42 +010032 #include <osmocom/core/linuxlist.h>
33 #include <osmocom/core/logging.h>
34 #include <osmocom/core/timer.h>
Maxe66de5b2017-01-05 18:26:58 +010035}
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +020036
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020037struct bssgp_bvc_ctx;
Jacob Erlbeckfecece02015-05-08 12:13:08 +020038class GprsMs;
Max1187a772018-01-26 13:31:42 +010039struct gprs_rlcmac_bts;
Holger Hans Peter Freyther1702f102013-10-20 08:44:02 +020040
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020041/*
42 * TBF instance
43 */
44
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020045enum gprs_rlcmac_tbf_state {
46 GPRS_RLCMAC_NULL = 0, /* new created TBF */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +020047 GPRS_RLCMAC_ASSIGN, /* wait for downlink assignment */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020048 GPRS_RLCMAC_FLOW, /* RLC/MAC flow, resource needed */
49 GPRS_RLCMAC_FINISHED, /* flow finished, wait for release */
50 GPRS_RLCMAC_WAIT_RELEASE,/* wait for release or restart of DL TBF */
51 GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
52};
53
Maxf60cf622017-07-10 14:40:09 +020054enum gprs_rlcmac_tbf_poll_type {
55 GPRS_RLCMAC_POLL_UL_ASS,
56 GPRS_RLCMAC_POLL_DL_ASS,
57 GPRS_RLCMAC_POLL_UL_ACK,
58 GPRS_RLCMAC_POLL_DL_ACK,
59};
60
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020061enum gprs_rlcmac_tbf_poll_state {
62 GPRS_RLCMAC_POLL_NONE = 0,
63 GPRS_RLCMAC_POLL_SCHED, /* a polling was scheduled */
64};
65
Maxcac6b662018-01-24 11:00:17 +010066extern const struct value_string gprs_rlcmac_tbf_poll_state_names[];
67
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020068enum gprs_rlcmac_tbf_dl_ass_state {
69 GPRS_RLCMAC_DL_ASS_NONE = 0,
70 GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
71 GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
72};
73
Maxe66de5b2017-01-05 18:26:58 +010074extern const struct value_string gprs_rlcmac_tbf_dl_ass_state_names[];
75
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020076enum gprs_rlcmac_tbf_ul_ass_state {
77 GPRS_RLCMAC_UL_ASS_NONE = 0,
78 GPRS_RLCMAC_UL_ASS_SEND_ASS, /* send uplink assignment on next RTS */
aravind sirsikared3413e2016-11-11 17:15:10 +053079 GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ, /* send assignment reject next RTS */
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020080 GPRS_RLCMAC_UL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
81};
82
Maxe66de5b2017-01-05 18:26:58 +010083extern const struct value_string gprs_rlcmac_tbf_ul_ass_state_names[];
84
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020085enum gprs_rlcmac_tbf_ul_ack_state {
86 GPRS_RLCMAC_UL_ACK_NONE = 0,
87 GPRS_RLCMAC_UL_ACK_SEND_ACK, /* send acknowledge on next RTS */
88 GPRS_RLCMAC_UL_ACK_WAIT_ACK, /* wait for PACKET CONTROL ACK */
89};
90
Max088c7df2018-01-23 20:16:23 +010091extern const struct value_string gprs_rlcmac_tbf_ul_ack_state_names[];
92
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +020093enum gprs_rlcmac_tbf_direction {
94 GPRS_RLCMAC_DL_TBF,
95 GPRS_RLCMAC_UL_TBF
96};
97
Max847ed9f2018-02-20 18:16:11 +010098enum tbf_rlc_counters {
sivasankari53950732016-12-08 17:15:17 +053099 TBF_CTR_RLC_NACKED,
100};
101
102enum tbf_gprs_counters {
103 TBF_CTR_GPRS_DL_CS1,
104 TBF_CTR_GPRS_DL_CS2,
105 TBF_CTR_GPRS_DL_CS3,
106 TBF_CTR_GPRS_DL_CS4,
107};
108
109enum tbf_egprs_counters {
110 TBF_CTR_EGPRS_DL_MCS1,
111 TBF_CTR_EGPRS_DL_MCS2,
112 TBF_CTR_EGPRS_DL_MCS3,
113 TBF_CTR_EGPRS_DL_MCS4,
114 TBF_CTR_EGPRS_DL_MCS5,
115 TBF_CTR_EGPRS_DL_MCS6,
116 TBF_CTR_EGPRS_DL_MCS7,
117 TBF_CTR_EGPRS_DL_MCS8,
118 TBF_CTR_EGPRS_DL_MCS9,
119};
120
Max0524e382018-01-19 18:22:25 +0100121#define LOGPTBF(tbf, level, fmt, args...) LOGP(DTBF, level, "%s " fmt, tbf_name(tbf), ## args)
Maxc21f0072017-12-15 17:36:45 +0100122
Maxee5be3a2017-12-20 17:31:13 +0100123enum tbf_timers {
Maxb2de1f72017-12-20 18:05:29 +0100124 /* internal assign/reject timer */
125 T0,
126
Maxee5be3a2017-12-20 17:31:13 +0100127 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
128 T3169,
129
130 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
131 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
132 T3191,
133
134 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
135 MS for this TBF. */
136 T3193,
137
138 /* Wait for reuse of TFI(s) when there is no response from the MS
139 (radio failure or cell change) for this TBF/MBMS radio bearer. */
140 T3195,
141 T_MAX
142};
143
Max847ed9f2018-02-20 18:16:11 +0100144enum tbf_counters { /* TBF counters from 3GPP TS 44.060 ยง13.4 */
145 /* counters are reset when: */
146 N3101, /* received a valid data block from mobile station in a block assigned for this USF */
147 N3103, /* transmitting the final PACKET UPLINK ACK/NACK message */
148 N3105, /* after sending a RRBP field in the downlink RLC data block, receives a valid RLC/MAC control message */
149 N_MAX
150};
151
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200152#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
153#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
154#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
155#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
156#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
157#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
158#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
159#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
160#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
161
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200162#define T_START(tbf, t, T, r, f) tbf->t_start(t, T, r, f, __FILE__, __LINE__)
Max467f6332017-12-20 18:13:29 +0100163
Max2399b1d2018-01-12 15:48:12 +0100164#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100165#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
166#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 +0100167#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Maxcac6b662018-01-24 11:00:17 +0100168#define TBF_POLL_SCHED_SET(t) do { t->poll_sched_set(__FILE__, __LINE__); } while(0)
169#define TBF_POLL_SCHED_UNSET(t) do { t->poll_sched_unset(__FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100170#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 +0100171#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
172#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100173
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200174struct gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200175 gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200176
177 static void free_all(struct gprs_rlcmac_trx *trx);
Holger Hans Peter Freyther4f6a4e5d2013-10-16 17:58:46 +0200178 static void free_all(struct gprs_rlcmac_pdch *pdch);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200179
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200180 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
181 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100182 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
183 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100184 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Maxcac6b662018-01-24 11:00:17 +0100185 bool poll_scheduled() const;
Max2399b1d2018-01-12 15:48:12 +0100186 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100187 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
188 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 +0100189 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100190 void poll_sched_set(const char *file, int line);
191 void poll_sched_unset(const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100192 void check_pending_ass();
Max8dce1de2018-01-02 14:17:04 +0100193 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100194 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100195 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200196 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200197
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100198 const char *name() const;
199
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100200 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
201 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530202 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200203
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200204 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200205 void set_ms(GprsMs *ms);
206
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100207 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100208
Holger Hans Peter Freyther7380bab2013-10-16 18:09:19 +0200209 int rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200210
Max847ed9f2018-02-20 18:16:11 +0100211 bool n_inc(enum tbf_counters n);
212 void n_reset(enum tbf_counters n);
213
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200214 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200215 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100216 void stop_timers(const char *reason);
217 bool timers_pending(enum tbf_timers t);
218 void t_stop(enum tbf_timers t, const char *reason);
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200219 void t_start(enum tbf_timers t, int T, const char *reason, bool force,
Max467f6332017-12-20 18:13:29 +0100220 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200221 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200222
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100223 int check_polling(uint32_t fn, uint8_t ts,
224 uint32_t *poll_fn, unsigned int *rrbp);
Maxf60cf622017-07-10 14:40:09 +0200225 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 +0200226 void poll_timeout();
227
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100228 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100229 uint32_t tlli() const;
230 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100231
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200232 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200233 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200234
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100235 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100236 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100237
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100238 const char *imsi() const;
239 void assign_imsi(const char *imsi);
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200240 uint8_t ta() const;
241 void set_ta(uint8_t);
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200242 uint8_t ms_class() const;
243 void set_ms_class(uint8_t);
Jacob Erlbeckcb728902016-01-05 15:33:03 +0100244 GprsCodingScheme current_cs() const;
Max869c0c22018-01-03 12:00:36 +0100245 size_t llc_queue_size() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100246
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100247 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200248 uint8_t dl_slots() const;
249 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100250
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100251 bool is_control_ts(uint8_t ts) const;
252
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100253 /* EGPRS */
254 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100255 void disable_egprs();
256
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100257 /* attempt to make things a bit more fair */
258 void rotate_in_list();
259
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200260 LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}
261 const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}
262
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100263 LListHead<gprs_rlcmac_tbf>& list();
264 const LListHead<gprs_rlcmac_tbf>& list() const;
265
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200266 uint32_t state_flags;
267 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200268 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200269 uint8_t first_ts; /* first TS used by TBF */
270 uint8_t first_common_ts; /* first TS that the phone can send and
271 reveive simultaniously */
272 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200273 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100274
275 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200276
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200277 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100278 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200279
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100280 gprs_rlc m_rlc;
Max847ed9f2018-02-20 18:16:11 +0100281
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200282 struct osmo_gsm_timer_list gsm_timer;
283 unsigned int fT; /* fTxxxx number */
284 unsigned int num_fT_exp; /* number of consecutive fT expirations */
285
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200286 struct Meas {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200287 struct timespec rssi_tv; /* timestamp for rssi calculation */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200288 int32_t rssi_sum; /* sum of rssi values */
289 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200290
291 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200292 } meas;
293
Daniel Willmann73191a42014-05-30 17:58:00 +0200294 /* Remember if the tbf was in wait_release state when we want to
295 * schedule a new dl assignment */
296 uint8_t was_releasing;
297
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200298 /* Can/should we upgrade this tbf to use multiple slots? */
299 uint8_t upgrade_to_multislot;
300
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200301 /* store the BTS this TBF belongs to */
302 BTS *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200303
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100304 /*
305 * private fields. We can't make it private as it is breaking the
306 * llist macros.
307 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100308 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100309 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100310
sivasankari53950732016-12-08 17:15:17 +0530311 struct rate_ctr_group *m_ctrs;
312
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200313protected:
314 gprs_rlcmac_bts *bts_data() const;
Max25a3ca42017-12-13 18:47:52 +0100315 void enable_egprs();
Jacob Erlbecke8f5fe52015-12-14 13:23:15 +0100316 int set_tlli_from_ul(uint32_t new_tlli);
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200317 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100318
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200319 gprs_llc_queue *llc_queue();
320 const gprs_llc_queue *llc_queue() const;
321
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200322 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100323
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200324 class GprsMs *m_ms;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200325
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200326 /* Fields to take the TA/MS class values if no MS is associated */
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200327 uint8_t m_ta;
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200328 uint8_t m_ms_class;
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200329
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100330private:
Max50818062017-12-06 13:35:08 +0100331 enum gprs_rlcmac_tbf_state state;
Max0e599802018-01-23 20:09:06 +0100332 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
333 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
Max088c7df2018-01-23 20:16:23 +0100334 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
Maxcac6b662018-01-24 11:00:17 +0100335 enum gprs_rlcmac_tbf_poll_state poll_state;
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100336 LListHead<gprs_rlcmac_tbf> m_list;
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200337 LListHead<gprs_rlcmac_tbf> m_ms_list;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100338 bool m_egprs_enabled;
Pau Espin Pedrolef1fe582019-09-05 14:40:24 +0200339 struct osmo_timer_list Tarr[T_MAX];
340 uint8_t Narr[N_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100341 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200342};
343
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +0200344
Daniel Willmann0d12a2f2014-07-10 17:44:07 +0200345struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck86b6f052015-11-27 15:17:34 +0100346 int8_t use_trx, uint8_t ms_class, uint8_t egprs_ms_class,
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200347 uint32_t tlli, uint8_t ta, GprsMs *ms);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200348
Maxe9fe0e32017-09-28 15:56:05 +0200349struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, uint8_t ms_class,
350 uint8_t egprs_ms_class, bool single_slot);
Daniel Willmann48aa0b02014-07-16 18:54:10 +0200351
Maxe9fe0e32017-09-28 15:56:05 +0200352struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, uint8_t ms_class,
353 uint8_t egprs_ms_class, bool single_slot);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200354
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200355void tbf_free(struct gprs_rlcmac_tbf *tbf);
356
aravind sirsikare9a138e2017-01-24 12:36:08 +0530357struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts,
358 GprsMs *ms, uint32_t tlli, uint8_t trx_no, uint8_t ts_no);
359
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200360int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
361
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200362inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
363{
364 return state == rhs;
365}
366
Max0e599802018-01-23 20:09:06 +0100367inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
368{
369 return dl_ass_state == rhs;
370}
371
372inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
373{
374 return ul_ass_state == rhs;
375}
376
Max088c7df2018-01-23 20:16:23 +0100377inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
378{
379 return ul_ack_state == rhs;
380}
381
Maxcac6b662018-01-24 11:00:17 +0100382inline bool gprs_rlcmac_tbf::poll_scheduled() const
383{
384 return poll_state == GPRS_RLCMAC_POLL_SCHED;
385}
386
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200387inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
388{
389 return state != rhs;
390}
391
Daniel Willmanneb100242014-08-08 11:43:53 +0200392const char *tbf_name(gprs_rlcmac_tbf *tbf);
393
Daniel Willmann08e57c82014-08-15 18:11:57 +0200394inline const char *gprs_rlcmac_tbf::state_name() const
395{
396 return tbf_state_name[state];
397}
398
Max8dce1de2018-01-02 14:17:04 +0100399/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100400inline 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 +0100401{
Max2399b1d2018-01-12 15:48:12 +0100402 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100403 if (check_ccch) {
404 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100405 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100406 } else
407 state_flags |= (1 << state_flag);
408}
409
Max5d7f7572018-01-30 16:56:43 +0100410inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
411{
412 const char *ch = "UNKNOWN";
413 switch (t) {
414 case GPRS_RLCMAC_FLAG_CCCH:
415 if (unset) {
416 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
417 return;
418 } else {
419 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
420 LOGPSRC(DTBF, LOGL_ERROR, file, line,
421 "%s attempted to set ass. type CCCH which is already set.\n",
422 tbf_name(this));
423 }
424 ch = "CCCH";
425 break;
426 case GPRS_RLCMAC_FLAG_PACCH:
427 if (unset) {
428 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
429 return;
430 } else {
431 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
432 LOGPSRC(DTBF, LOGL_ERROR, file, line,
433 "%s attempted to set ass. type PACCH which is already set.\n",
434 tbf_name(this));
435 }
436 ch = "PACCH";
437 break;
438 default:
439 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
440 tbf_name(this), unset ? "un" : "", t);
441 return;
442 }
443
444 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
445 tbf_name(this), unset ? "un" : "", ch,
446 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
447 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
448
449 if (unset) {
450 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
451 state_flags &= ~(1 << t);
452 } else
453 state_flags |= (1 << t);
454}
455
Max2399b1d2018-01-12 15:48:12 +0100456inline 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 +0200457{
Max0524e382018-01-19 18:22:25 +0100458 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200459 tbf_name(this),
460 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200461 state = new_state;
462}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100463
Max0e599802018-01-23 20:09:06 +0100464inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
465{
466 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
467 tbf_name(this),
468 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
469 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
470 dl_ass_state = new_state;
471}
472
473inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
474{
475 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
476 tbf_name(this),
477 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
478 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
479 ul_ass_state = new_state;
480}
481
Max088c7df2018-01-23 20:16:23 +0100482inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
483{
484 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
485 tbf_name(this),
486 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
487 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
488 ul_ack_state = new_state;
489}
490
Maxcac6b662018-01-24 11:00:17 +0100491inline void gprs_rlcmac_tbf::poll_sched_set(const char *file, int line)
492{
493 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_SCHED\n",
494 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
495 poll_state = GPRS_RLCMAC_POLL_SCHED;
496}
497
498inline void gprs_rlcmac_tbf::poll_sched_unset(const char *file, int line)
499{
500 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_NONE\n",
501 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
502 poll_state = GPRS_RLCMAC_POLL_NONE;
503}
504
Max0e599802018-01-23 20:09:06 +0100505inline void gprs_rlcmac_tbf::check_pending_ass()
506{
507 if (ul_ass_state != GPRS_RLCMAC_UL_ASS_NONE)
508 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending uplink assignment in state %s. "
509 "This may not happen, because the assignment message never gets transmitted. "
510 "Please be sure not to free in this state. PLEASE FIX!\n",
511 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state));
512
513 if (dl_ass_state != GPRS_RLCMAC_DL_ASS_NONE)
514 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending downlink assignment in state %s. "
515 "This may not happen, because the assignment message never gets transmitted. "
516 "Please be sure not to free in this state. PLEASE FIX!\n",
517 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state));
518}
519
Max8dce1de2018-01-02 14:17:04 +0100520inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
521{
522 if ((state_flags & (1 << state_flag))) {
523 state_flags &= ~(1 << state_flag);
524 return true;
525 }
526
527 return false;
528}
529
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100530inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
531{
532 return this->m_list;
533}
534
535inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
536{
537 return this->m_list;
538}
539
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200540inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200541{
542 return m_ms;
543}
544
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100545inline bool gprs_rlcmac_tbf::is_tlli_valid() const
546{
Jacob Erlbeck767193e2015-05-20 12:06:46 +0200547 return tlli() != 0;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100548}
549
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100550inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
551{
552 /* The TBF is established or has been assigned by a IMM.ASS for
553 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200554 return state > GPRS_RLCMAC_ASSIGN ||
555 (direction == GPRS_RLCMAC_DL_TBF &&
556 state == GPRS_RLCMAC_ASSIGN &&
557 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100558}
559
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100560inline uint8_t gprs_rlcmac_tbf::tfi() const
561{
562 return m_tfi;
563}
564
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100565inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100566{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100567 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100568}
569
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100570inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
571{
572 return m_egprs_enabled;
573}
574
575inline void gprs_rlcmac_tbf::enable_egprs()
576{
577 m_egprs_enabled = true;
578}
579
580inline void gprs_rlcmac_tbf::disable_egprs()
581{
582 m_egprs_enabled = false;
583}
584
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200585inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
586{
587 return (enum gprs_rlcmac_tbf_direction)
588 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
589}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100590
Max9d7357e2017-12-14 15:02:33 +0100591uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots);
592
Daniel Willmannafa72f52014-01-15 17:06:19 +0100593#endif