blob: 6eab9d0d029b407ab6b2e55fe9f0e7aacd48bcdd [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
Maxd0532b52017-12-13 18:27:32 +010098enum tbf_dl_prio {
99 DL_PRIO_NONE,
100 DL_PRIO_SENT_DATA, /* the data has been sent and not (yet) nacked */
101 DL_PRIO_LOW_AGE, /* the age has reached the first threshold */
102 DL_PRIO_NEW_DATA, /* the data has not been sent yet or nacked */
103 DL_PRIO_HIGH_AGE, /* the age has reached the second threshold */
104 DL_PRIO_CONTROL, /* a control block needs to be sent */
105};
106
Max847ed9f2018-02-20 18:16:11 +0100107enum tbf_rlc_counters {
sivasankari53950732016-12-08 17:15:17 +0530108 TBF_CTR_RLC_NACKED,
109};
110
111enum tbf_gprs_counters {
112 TBF_CTR_GPRS_DL_CS1,
113 TBF_CTR_GPRS_DL_CS2,
114 TBF_CTR_GPRS_DL_CS3,
115 TBF_CTR_GPRS_DL_CS4,
116};
117
118enum tbf_egprs_counters {
119 TBF_CTR_EGPRS_DL_MCS1,
120 TBF_CTR_EGPRS_DL_MCS2,
121 TBF_CTR_EGPRS_DL_MCS3,
122 TBF_CTR_EGPRS_DL_MCS4,
123 TBF_CTR_EGPRS_DL_MCS5,
124 TBF_CTR_EGPRS_DL_MCS6,
125 TBF_CTR_EGPRS_DL_MCS7,
126 TBF_CTR_EGPRS_DL_MCS8,
127 TBF_CTR_EGPRS_DL_MCS9,
128};
129
sivasankarida7250a2016-12-16 12:57:18 +0530130enum tbf_gprs_ul_counters {
131 TBF_CTR_GPRS_UL_CS1,
132 TBF_CTR_GPRS_UL_CS2,
133 TBF_CTR_GPRS_UL_CS3,
134 TBF_CTR_GPRS_UL_CS4,
135};
136
137enum tbf_egprs_ul_counters {
138 TBF_CTR_EGPRS_UL_MCS1,
139 TBF_CTR_EGPRS_UL_MCS2,
140 TBF_CTR_EGPRS_UL_MCS3,
141 TBF_CTR_EGPRS_UL_MCS4,
142 TBF_CTR_EGPRS_UL_MCS5,
143 TBF_CTR_EGPRS_UL_MCS6,
144 TBF_CTR_EGPRS_UL_MCS7,
145 TBF_CTR_EGPRS_UL_MCS8,
146 TBF_CTR_EGPRS_UL_MCS9,
147};
148
Max0524e382018-01-19 18:22:25 +0100149#define LOGPTBF(tbf, level, fmt, args...) LOGP(DTBF, level, "%s " fmt, tbf_name(tbf), ## args)
150#define LOGPTBFUL(tbf, level, fmt, args...) LOGP(DTBFUL, level, "%s " fmt, tbf_name(tbf), ## args)
151#define LOGPTBFDL(tbf, level, fmt, args...) LOGP(DTBFDL, level, "%s " fmt, tbf_name(tbf), ## args)
Maxc21f0072017-12-15 17:36:45 +0100152
Maxee5be3a2017-12-20 17:31:13 +0100153enum tbf_timers {
Maxb2de1f72017-12-20 18:05:29 +0100154 /* internal assign/reject timer */
155 T0,
156
Maxee5be3a2017-12-20 17:31:13 +0100157 /* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
158 T3169,
159
160 /* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
161 Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
162 T3191,
163
164 /* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
165 MS for this TBF. */
166 T3193,
167
168 /* Wait for reuse of TFI(s) when there is no response from the MS
169 (radio failure or cell change) for this TBF/MBMS radio bearer. */
170 T3195,
171 T_MAX
172};
173
Max847ed9f2018-02-20 18:16:11 +0100174enum tbf_counters { /* TBF counters from 3GPP TS 44.060 §13.4 */
175 /* counters are reset when: */
176 N3101, /* received a valid data block from mobile station in a block assigned for this USF */
177 N3103, /* transmitting the final PACKET UPLINK ACK/NACK message */
178 N3105, /* after sending a RRBP field in the downlink RLC data block, receives a valid RLC/MAC control message */
179 N_MAX
180};
181
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200182#define GPRS_RLCMAC_FLAG_CCCH 0 /* assignment on CCCH */
183#define GPRS_RLCMAC_FLAG_PACCH 1 /* assignment on PACCH */
184#define GPRS_RLCMAC_FLAG_UL_DATA 2 /* uplink data received */
185#define GPRS_RLCMAC_FLAG_DL_ACK 3 /* downlink acknowledge received */
186#define GPRS_RLCMAC_FLAG_TO_UL_ACK 4
187#define GPRS_RLCMAC_FLAG_TO_DL_ACK 5
188#define GPRS_RLCMAC_FLAG_TO_UL_ASS 6
189#define GPRS_RLCMAC_FLAG_TO_DL_ASS 7
190#define GPRS_RLCMAC_FLAG_TO_MASK 0xf0 /* timeout bits */
191
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200192#define T_START(tbf, t, T, r, f) tbf->t_start(t, T, r, f, __FILE__, __LINE__)
Max467f6332017-12-20 18:13:29 +0100193
Max2399b1d2018-01-12 15:48:12 +0100194#define TBF_SET_STATE(t, st) do { t->set_state(st, __FILE__, __LINE__); } while(0)
Max0e599802018-01-23 20:09:06 +0100195#define TBF_SET_ASS_STATE_DL(t, st) do { t->set_ass_state_dl(st, __FILE__, __LINE__); } while(0)
196#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 +0100197#define TBF_SET_ACK_STATE(t, st) do { t->set_ack_state(st, __FILE__, __LINE__); } while(0)
Maxcac6b662018-01-24 11:00:17 +0100198#define TBF_POLL_SCHED_SET(t) do { t->poll_sched_set(__FILE__, __LINE__); } while(0)
199#define TBF_POLL_SCHED_UNSET(t) do { t->poll_sched_unset(__FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100200#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 +0100201#define TBF_ASS_TYPE_SET(t, kind) do { t->ass_type_mod(kind, false, __FILE__, __LINE__); } while(0)
202#define TBF_ASS_TYPE_UNSET(t, kind) do { t->ass_type_mod(kind, true, __FILE__, __LINE__); } while(0)
Max2399b1d2018-01-12 15:48:12 +0100203
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200204struct gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200205 gprs_rlcmac_tbf(BTS *bts_, gprs_rlcmac_tbf_direction dir);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200206
207 static void free_all(struct gprs_rlcmac_trx *trx);
Holger Hans Peter Freyther4f6a4e5d2013-10-16 17:58:46 +0200208 static void free_all(struct gprs_rlcmac_pdch *pdch);
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200209
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200210 bool state_is(enum gprs_rlcmac_tbf_state rhs) const;
211 bool state_is_not(enum gprs_rlcmac_tbf_state rhs) const;
Max0e599802018-01-23 20:09:06 +0100212 bool dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const;
213 bool ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const;
Max088c7df2018-01-23 20:16:23 +0100214 bool ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const;
Maxcac6b662018-01-24 11:00:17 +0100215 bool poll_scheduled() const;
Max2399b1d2018-01-12 15:48:12 +0100216 void set_state(enum gprs_rlcmac_tbf_state new_state, const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100217 void set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line);
218 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 +0100219 void set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line);
Maxcac6b662018-01-24 11:00:17 +0100220 void poll_sched_set(const char *file, int line);
221 void poll_sched_unset(const char *file, int line);
Max0e599802018-01-23 20:09:06 +0100222 void check_pending_ass();
Max8dce1de2018-01-02 14:17:04 +0100223 bool check_n_clear(uint8_t state_flag);
Max2399b1d2018-01-12 15:48:12 +0100224 void set_assigned_on(uint8_t state_flag, bool check_ccch, const char *file, int line);
Max5d7f7572018-01-30 16:56:43 +0100225 void ass_type_mod(uint8_t t, bool unset, const char *file, int line);
Daniel Willmann08e57c82014-08-15 18:11:57 +0200226 const char *state_name() const;
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200227
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100228 const char *name() const;
229
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100230 struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
231 struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
aravind sirsikared3413e2016-11-11 17:15:10 +0530232 struct msgb *create_packet_access_reject();
Holger Hans Peter Freyther2db7e7e2013-10-26 20:45:35 +0200233
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200234 GprsMs *ms() const;
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200235 void set_ms(GprsMs *ms);
236
Holger Hans Peter Freyther8f399de2013-12-25 20:22:35 +0100237 uint8_t tsc() const;
Holger Hans Peter Freythera1da2512013-11-07 07:32:51 +0100238
Holger Hans Peter Freyther7380bab2013-10-16 18:09:19 +0200239 int rlcmac_diag();
Holger Hans Peter Freyther964ddb62013-10-16 17:53:23 +0200240
Max847ed9f2018-02-20 18:16:11 +0100241 bool n_inc(enum tbf_counters n);
242 void n_reset(enum tbf_counters n);
243
Jacob Erlbecke0c734d2015-07-03 14:03:33 +0200244 int update();
Holger Hans Peter Freytheraf8094d2013-10-26 17:56:15 +0200245 void handle_timeout();
Maxee5be3a2017-12-20 17:31:13 +0100246 void stop_timers(const char *reason);
247 bool timers_pending(enum tbf_timers t);
248 void t_stop(enum tbf_timers t, const char *reason);
Pau Espin Pedrol28f160e2019-09-05 14:48:35 +0200249 void t_start(enum tbf_timers t, int T, const char *reason, bool force,
Max467f6332017-12-20 18:13:29 +0100250 const char *file, unsigned line);
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200251 int establish_dl_tbf_on_pacch();
Holger Hans Peter Freytheraa9c3262013-10-26 17:49:36 +0200252
Jacob Erlbeckf2694b72016-01-26 21:46:26 +0100253 int check_polling(uint32_t fn, uint8_t ts,
254 uint32_t *poll_fn, unsigned int *rrbp);
Maxf60cf622017-07-10 14:40:09 +0200255 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 +0200256 void poll_timeout();
257
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100258 /** tlli handling */
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100259 uint32_t tlli() const;
260 bool is_tlli_valid() const;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100261
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200262 /** MS updating */
Jacob Erlbeckbe0cbc12015-05-18 14:35:11 +0200263 void update_ms(uint32_t tlli, enum gprs_rlcmac_tbf_direction);
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200264
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100265 uint8_t tfi() const;
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100266 bool is_tfi_assigned() const;
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100267
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100268 const char *imsi() const;
269 void assign_imsi(const char *imsi);
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;
273 void set_ms_class(uint8_t);
Jacob Erlbeckcb728902016-01-05 15:33:03 +0100274 GprsCodingScheme current_cs() const;
Max869c0c22018-01-03 12:00:36 +0100275 size_t llc_queue_size() const;
Holger Hans Peter Freyther5464c9b2013-10-27 20:57:35 +0100276
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100277 time_t created_ts() const;
Jacob Erlbeck617c7122015-06-30 09:18:30 +0200278 uint8_t dl_slots() const;
279 uint8_t ul_slots() const;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100280
Jacob Erlbeck646da1b2016-01-22 17:41:33 +0100281 bool is_control_ts(uint8_t ts) const;
282
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100283 /* EGPRS */
284 bool is_egprs_enabled() const;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100285 void disable_egprs();
286
Holger Hans Peter Freyther7a5f3c22013-11-26 13:08:12 +0100287 /* attempt to make things a bit more fair */
288 void rotate_in_list();
289
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200290 LListHead<gprs_rlcmac_tbf>& ms_list() {return this->m_ms_list;}
291 const LListHead<gprs_rlcmac_tbf>& ms_list() const {return this->m_ms_list;}
292
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100293 LListHead<gprs_rlcmac_tbf>& list();
294 const LListHead<gprs_rlcmac_tbf>& list() const;
295
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200296 uint32_t state_flags;
297 enum gprs_rlcmac_tbf_direction direction;
Holger Hans Peter Freyther743bafa2013-09-29 07:50:50 +0200298 struct gprs_rlcmac_trx *trx;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200299 uint8_t first_ts; /* first TS used by TBF */
300 uint8_t first_common_ts; /* first TS that the phone can send and
301 reveive simultaniously */
302 uint8_t control_ts; /* timeslot control messages and polling */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200303 struct gprs_rlcmac_pdch *pdch[8]; /* list of PDCHs allocated to TBF */
Holger Hans Peter Freyther28e53782013-11-06 20:23:56 +0100304
305 gprs_llc m_llc;
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200306
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200307 uint32_t poll_fn; /* frame number to poll */
Jacob Erlbeck8eb17142016-01-22 17:58:17 +0100308 uint8_t poll_ts; /* TS to poll */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200309
Holger Hans Peter Freyther9241fd02013-11-13 19:51:55 +0100310 gprs_rlc m_rlc;
Max847ed9f2018-02-20 18:16:11 +0100311
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200312 struct osmo_gsm_timer_list gsm_timer;
313 unsigned int fT; /* fTxxxx number */
314 unsigned int num_fT_exp; /* number of consecutive fT expirations */
315
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200316 struct Meas {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200317 struct timespec rssi_tv; /* timestamp for rssi calculation */
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200318 int32_t rssi_sum; /* sum of rssi values */
319 int rssi_num; /* number of rssi values added since rssi_tv */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200320
321 Meas();
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200322 } meas;
323
Daniel Willmann73191a42014-05-30 17:58:00 +0200324 /* Remember if the tbf was in wait_release state when we want to
325 * schedule a new dl assignment */
326 uint8_t was_releasing;
327
Daniel Willmanncf1fae72014-05-30 17:58:01 +0200328 /* Can/should we upgrade this tbf to use multiple slots? */
329 uint8_t upgrade_to_multislot;
330
Holger Hans Peter Freyther9f0c1d22013-10-19 21:24:34 +0200331 /* store the BTS this TBF belongs to */
332 BTS *bts;
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200333
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100334 /*
335 * private fields. We can't make it private as it is breaking the
336 * llist macros.
337 */
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100338 uint8_t m_tfi;
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100339 time_t m_created_ts;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100340
sivasankari53950732016-12-08 17:15:17 +0530341 struct rate_ctr_group *m_ctrs;
342
Holger Hans Peter Freytherd9262b32013-10-26 20:12:59 +0200343protected:
344 gprs_rlcmac_bts *bts_data() const;
Max25a3ca42017-12-13 18:47:52 +0100345 void enable_egprs();
Jacob Erlbecke8f5fe52015-12-14 13:23:15 +0100346 int set_tlli_from_ul(uint32_t new_tlli);
Jacob Erlbeck28c40b12015-08-16 18:19:32 +0200347 void merge_and_clear_ms(GprsMs *old_ms);
Holger Hans Peter Freyther4c06d912013-11-25 23:05:26 +0100348
Alexander Couzensd38b92e2016-08-21 19:38:30 +0200349 gprs_llc_queue *llc_queue();
350 const gprs_llc_queue *llc_queue() const;
351
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200352 static const char *tbf_state_name[6];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100353
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200354 class GprsMs *m_ms;
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200355
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200356 /* Fields to take the TA/MS class values if no MS is associated */
Jacob Erlbeck9200ce62015-05-22 17:48:04 +0200357 uint8_t m_ta;
Jacob Erlbeckbefc7602015-06-02 12:33:30 +0200358 uint8_t m_ms_class;
Jacob Erlbeck6dbe8222015-05-29 10:37:09 +0200359
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100360private:
Max50818062017-12-06 13:35:08 +0100361 enum gprs_rlcmac_tbf_state state;
Max0e599802018-01-23 20:09:06 +0100362 enum gprs_rlcmac_tbf_dl_ass_state dl_ass_state;
363 enum gprs_rlcmac_tbf_ul_ass_state ul_ass_state;
Max088c7df2018-01-23 20:16:23 +0100364 enum gprs_rlcmac_tbf_ul_ack_state ul_ack_state;
Maxcac6b662018-01-24 11:00:17 +0100365 enum gprs_rlcmac_tbf_poll_state poll_state;
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100366 LListHead<gprs_rlcmac_tbf> m_list;
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200367 LListHead<gprs_rlcmac_tbf> m_ms_list;
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100368 bool m_egprs_enabled;
Pau Espin Pedrolef1fe582019-09-05 14:40:24 +0200369 struct osmo_timer_list Tarr[T_MAX];
370 uint8_t Narr[N_MAX];
Jacob Erlbeckadcdf152015-03-03 14:45:55 +0100371 mutable char m_name_buf[60];
Holger Hans Peter Freyther099535a2013-10-16 17:42:31 +0200372};
373
Holger Hans Peter Freyther17c31ce2013-08-24 18:31:27 +0200374
Daniel Willmann0d12a2f2014-07-10 17:44:07 +0200375struct gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck86b6f052015-11-27 15:17:34 +0100376 int8_t use_trx, uint8_t ms_class, uint8_t egprs_ms_class,
Jacob Erlbecke2e004e2015-06-18 17:16:26 +0200377 uint32_t tlli, uint8_t ta, GprsMs *ms);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200378
Maxe9fe0e32017-09-28 15:56:05 +0200379struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, uint8_t ms_class,
380 uint8_t egprs_ms_class, bool single_slot);
Daniel Willmann48aa0b02014-07-16 18:54:10 +0200381
Maxe9fe0e32017-09-28 15:56:05 +0200382struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, uint8_t ms_class,
383 uint8_t egprs_ms_class, bool single_slot);
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200384
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200385void tbf_free(struct gprs_rlcmac_tbf *tbf);
386
aravind sirsikare9a138e2017-01-24 12:36:08 +0530387struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts,
388 GprsMs *ms, uint32_t tlli, uint8_t trx_no, uint8_t ts_no);
389
Holger Hans Peter Freyther9e21d842013-10-16 17:48:12 +0200390int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
391
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200392inline bool gprs_rlcmac_tbf::state_is(enum gprs_rlcmac_tbf_state rhs) const
393{
394 return state == rhs;
395}
396
Max0e599802018-01-23 20:09:06 +0100397inline bool gprs_rlcmac_tbf::dl_ass_state_is(enum gprs_rlcmac_tbf_dl_ass_state rhs) const
398{
399 return dl_ass_state == rhs;
400}
401
402inline bool gprs_rlcmac_tbf::ul_ass_state_is(enum gprs_rlcmac_tbf_ul_ass_state rhs) const
403{
404 return ul_ass_state == rhs;
405}
406
Max088c7df2018-01-23 20:16:23 +0100407inline bool gprs_rlcmac_tbf::ul_ack_state_is(enum gprs_rlcmac_tbf_ul_ack_state rhs) const
408{
409 return ul_ack_state == rhs;
410}
411
Maxcac6b662018-01-24 11:00:17 +0100412inline bool gprs_rlcmac_tbf::poll_scheduled() const
413{
414 return poll_state == GPRS_RLCMAC_POLL_SCHED;
415}
416
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200417inline bool gprs_rlcmac_tbf::state_is_not(enum gprs_rlcmac_tbf_state rhs) const
418{
419 return state != rhs;
420}
421
Daniel Willmanneb100242014-08-08 11:43:53 +0200422const char *tbf_name(gprs_rlcmac_tbf *tbf);
423
Daniel Willmann08e57c82014-08-15 18:11:57 +0200424inline const char *gprs_rlcmac_tbf::state_name() const
425{
426 return tbf_state_name[state];
427}
428
Max8dce1de2018-01-02 14:17:04 +0100429/* Set assignment state and corrsponding flags */
Max2399b1d2018-01-12 15:48:12 +0100430inline 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 +0100431{
Max2399b1d2018-01-12 15:48:12 +0100432 set_state(GPRS_RLCMAC_ASSIGN, file, line);
Max8dce1de2018-01-02 14:17:04 +0100433 if (check_ccch) {
434 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
Max5d7f7572018-01-30 16:56:43 +0100435 ass_type_mod(state_flag, false, file, line);
Max8dce1de2018-01-02 14:17:04 +0100436 } else
437 state_flags |= (1 << state_flag);
438}
439
Max5d7f7572018-01-30 16:56:43 +0100440inline void gprs_rlcmac_tbf::ass_type_mod(uint8_t t, bool unset, const char *file, int line)
441{
442 const char *ch = "UNKNOWN";
443 switch (t) {
444 case GPRS_RLCMAC_FLAG_CCCH:
445 if (unset) {
446 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
447 return;
448 } else {
449 if (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
450 LOGPSRC(DTBF, LOGL_ERROR, file, line,
451 "%s attempted to set ass. type CCCH which is already set.\n",
452 tbf_name(this));
453 }
454 ch = "CCCH";
455 break;
456 case GPRS_RLCMAC_FLAG_PACCH:
457 if (unset) {
458 if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH)))
459 return;
460 } else {
461 if (state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH))
462 LOGPSRC(DTBF, LOGL_ERROR, file, line,
463 "%s attempted to set ass. type PACCH which is already set.\n",
464 tbf_name(this));
465 }
466 ch = "PACCH";
467 break;
468 default:
469 LOGPSRC(DTBF, LOGL_ERROR, file, line, "%s attempted to %sset unexpected ass. type %d - FIXME!\n",
470 tbf_name(this), unset ? "un" : "", t);
471 return;
472 }
473
474 LOGPSRC(DTBF, LOGL_INFO, file, line, "%s %sset ass. type %s [prev CCCH:%u, PACCH:%u]\n",
475 tbf_name(this), unset ? "un" : "", ch,
476 state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH),
477 state_flags & (1 << GPRS_RLCMAC_FLAG_PACCH));
478
479 if (unset) {
480 state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep to flags */
481 state_flags &= ~(1 << t);
482 } else
483 state_flags |= (1 << t);
484}
485
Max2399b1d2018-01-12 15:48:12 +0100486inline 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 +0200487{
Max0524e382018-01-19 18:22:25 +0100488 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes state from %s to %s\n",
Daniel Willmanneb100242014-08-08 11:43:53 +0200489 tbf_name(this),
490 tbf_state_name[state], tbf_state_name[new_state]);
Holger Hans Peter Freyther1c344e22013-10-16 18:33:18 +0200491 state = new_state;
492}
Holger Hans Peter Freytherbd449f52013-10-27 16:39:36 +0100493
Max0e599802018-01-23 20:09:06 +0100494inline void gprs_rlcmac_tbf::set_ass_state_dl(enum gprs_rlcmac_tbf_dl_ass_state new_state, const char *file, int line)
495{
496 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes DL ASS state from %s to %s\n",
497 tbf_name(this),
498 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state),
499 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, new_state));
500 dl_ass_state = new_state;
501}
502
503inline void gprs_rlcmac_tbf::set_ass_state_ul(enum gprs_rlcmac_tbf_ul_ass_state new_state, const char *file, int line)
504{
505 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ASS state from %s to %s\n",
506 tbf_name(this),
507 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state),
508 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, new_state));
509 ul_ass_state = new_state;
510}
511
Max088c7df2018-01-23 20:16:23 +0100512inline void gprs_rlcmac_tbf::set_ack_state(enum gprs_rlcmac_tbf_ul_ack_state new_state, const char *file, int line)
513{
514 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes UL ACK state from %s to %s\n",
515 tbf_name(this),
516 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, ul_ack_state),
517 get_value_string(gprs_rlcmac_tbf_ul_ack_state_names, new_state));
518 ul_ack_state = new_state;
519}
520
Maxcac6b662018-01-24 11:00:17 +0100521inline void gprs_rlcmac_tbf::poll_sched_set(const char *file, int line)
522{
523 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_SCHED\n",
524 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
525 poll_state = GPRS_RLCMAC_POLL_SCHED;
526}
527
528inline void gprs_rlcmac_tbf::poll_sched_unset(const char *file, int line)
529{
530 LOGPSRC(DTBF, LOGL_DEBUG, file, line, "%s changes poll state from %s to GPRS_RLCMAC_POLL_NONE\n",
531 tbf_name(this), get_value_string(gprs_rlcmac_tbf_poll_state_names, poll_state));
532 poll_state = GPRS_RLCMAC_POLL_NONE;
533}
534
Max0e599802018-01-23 20:09:06 +0100535inline void gprs_rlcmac_tbf::check_pending_ass()
536{
537 if (ul_ass_state != GPRS_RLCMAC_UL_ASS_NONE)
538 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending uplink assignment in state %s. "
539 "This may not happen, because the assignment message never gets transmitted. "
540 "Please be sure not to free in this state. PLEASE FIX!\n",
541 get_value_string(gprs_rlcmac_tbf_ul_ass_state_names, ul_ass_state));
542
543 if (dl_ass_state != GPRS_RLCMAC_DL_ASS_NONE)
544 LOGPTBF(this, LOGL_ERROR, "FIXME: Software error: Pending downlink assignment in state %s. "
545 "This may not happen, because the assignment message never gets transmitted. "
546 "Please be sure not to free in this state. PLEASE FIX!\n",
547 get_value_string(gprs_rlcmac_tbf_dl_ass_state_names, dl_ass_state));
548}
549
Max8dce1de2018-01-02 14:17:04 +0100550inline bool gprs_rlcmac_tbf::check_n_clear(uint8_t state_flag)
551{
552 if ((state_flags & (1 << state_flag))) {
553 state_flags &= ~(1 << state_flag);
554 return true;
555 }
556
557 return false;
558}
559
Jacob Erlbecked2dbf62015-12-28 19:15:40 +0100560inline LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list()
561{
562 return this->m_list;
563}
564
565inline const LListHead<gprs_rlcmac_tbf>& gprs_rlcmac_tbf::list() const
566{
567 return this->m_list;
568}
569
Jacob Erlbeck10ed7952015-06-02 11:37:22 +0200570inline GprsMs *gprs_rlcmac_tbf::ms() const
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200571{
572 return m_ms;
573}
574
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100575inline bool gprs_rlcmac_tbf::is_tlli_valid() const
576{
Jacob Erlbeck767193e2015-05-20 12:06:46 +0200577 return tlli() != 0;
Holger Hans Peter Freyther474685e2013-10-27 17:01:14 +0100578}
579
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100580inline bool gprs_rlcmac_tbf::is_tfi_assigned() const
581{
582 /* The TBF is established or has been assigned by a IMM.ASS for
583 * download */
Neels Hofmeyr4ea45262016-06-08 15:27:40 +0200584 return state > GPRS_RLCMAC_ASSIGN ||
585 (direction == GPRS_RLCMAC_DL_TBF &&
586 state == GPRS_RLCMAC_ASSIGN &&
587 (state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)));
Jacob Erlbeck6b356a52016-01-29 16:39:21 +0100588}
589
Holger Hans Peter Freyther34f6e5e2013-10-27 20:31:47 +0100590inline uint8_t gprs_rlcmac_tbf::tfi() const
591{
592 return m_tfi;
593}
594
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100595inline time_t gprs_rlcmac_tbf::created_ts() const
Daniel Willmann80367aa2014-01-15 17:40:28 +0100596{
Holger Hans Peter Freythera0047992014-01-16 10:07:20 +0100597 return m_created_ts;
Daniel Willmann80367aa2014-01-15 17:40:28 +0100598}
599
Jacob Erlbeck5643f352015-11-27 16:17:40 +0100600inline bool gprs_rlcmac_tbf::is_egprs_enabled() const
601{
602 return m_egprs_enabled;
603}
604
605inline void gprs_rlcmac_tbf::enable_egprs()
606{
607 m_egprs_enabled = true;
608}
609
610inline void gprs_rlcmac_tbf::disable_egprs()
611{
612 m_egprs_enabled = false;
613}
614
Daniel Willmann078bb712014-07-10 17:44:06 +0200615struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200616 gprs_rlcmac_dl_tbf(BTS *bts);
Maxea98b7d2018-01-04 15:13:27 +0100617 gprs_rlc_dl_window *window();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200618 void cleanup();
Max25a3ca42017-12-13 18:47:52 +0100619 void enable_egprs();
Daniel Willmann30168882014-08-07 12:48:29 +0200620 /* dispatch Unitdata.DL messages */
621 static int handle(struct gprs_rlcmac_bts *bts,
Jacob Erlbeck93990462015-05-15 15:50:43 +0200622 const uint32_t tlli, const uint32_t old_tlli,
623 const char *imsi, const uint8_t ms_class,
Jacob Erlbeck14e00f82015-11-27 18:10:39 +0100624 const uint8_t egprs_ms_class, const uint16_t delay_csec,
625 const uint8_t *data, const uint16_t len);
Daniel Willmann30168882014-08-07 12:48:29 +0200626
Daniel Willmann538ac5b2014-07-30 19:12:27 +0200627 int append_data(const uint8_t ms_class,
628 const uint16_t pdu_delay_csec,
629 const uint8_t *data, const uint16_t len);
630
Max7df82d42017-12-15 11:14:30 +0100631 int rcvd_dl_ack(bool final, uint8_t ssn, uint8_t *rbb);
632 int rcvd_dl_ack(bool final_ack, unsigned first_bsn, struct bitvec *rbb);
Daniel Willmannb8f26012014-07-30 19:12:28 +0200633 struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts);
Maxa10c3982017-07-07 18:25:41 +0200634 void trigger_ass(struct gprs_rlcmac_tbf *old_tbf);
Max8dce1de2018-01-02 14:17:04 +0100635
Maxaae1bfb2017-07-07 13:49:29 +0200636 bool handle_ack_nack();
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100637 void request_dl_ack();
Jacob Erlbeckeceb9102015-03-20 14:41:50 +0100638 bool need_control_ts() const;
639 bool have_data() const;
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100640 int frames_since_last_poll(unsigned fn) const;
Jacob Erlbeck3bed5d12015-03-19 11:22:38 +0100641 int frames_since_last_drain(unsigned fn) const;
642 bool keep_open(unsigned fn) const;
Jacob Erlbeck91ff7d12015-09-01 11:20:29 +0200643 int release();
Jacob Erlbeckf04a5b32016-01-21 20:42:40 +0100644 int abort();
Maxa4f570f2017-12-15 11:21:57 +0100645 uint16_t window_size() const;
Max9d7357e2017-12-14 15:02:33 +0100646 void set_window_size();
Maxfb59a932019-03-13 18:40:19 +0100647 void update_coding_scheme_counter_dl(enum CodingScheme cs);
Aravind Sirsikar8e70bb52016-09-15 17:51:16 +0530648
Daniel Willmanncf706b02014-08-07 17:35:22 +0200649 /* TODO: add the gettimeofday as parameter */
650 struct msgb *llc_dequeue(bssgp_bvc_ctx *bctx);
651
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200652 /* Please note that all variables here will be reset when changing
653 * from WAIT RELEASE back to FLOW state (re-use of TBF).
654 * All states that need reset must be in this struct, so this is why
655 * variables are in both (dl and ul) structs and not outside union.
656 */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200657 int32_t m_tx_counter; /* count all transmitted blocks */
658 uint8_t m_wait_confirm; /* wait for CCCH IMM.ASS cnf */
Jacob Erlbeck7c444152015-03-12 12:08:54 +0100659 bool m_dl_ack_requested;
Jacob Erlbeck005ee7f2015-03-20 14:53:54 +0100660 int32_t m_last_dl_poll_fn;
Jacob Erlbeck3bed5d12015-03-19 11:22:38 +0100661 int32_t m_last_dl_drained_fn;
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200662
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200663 struct BandWidth {
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200664 struct timespec dl_bw_tv; /* timestamp for dl bw calculation */
Daniel Willmann418a4232014-08-08 11:21:04 +0200665 uint32_t dl_bw_octets; /* number of octets since bw_tv */
sivasankari53950732016-12-08 17:15:17 +0530666 uint32_t dl_throughput; /* throughput to be displayed in stats */
Daniel Willmann418a4232014-08-08 11:21:04 +0200667
Stefan Sperlingf0f7df12018-05-25 15:12:30 +0200668 struct timespec dl_loss_tv; /* timestamp for loss calculation */
Daniel Willmann418a4232014-08-08 11:21:04 +0200669 uint16_t dl_loss_lost; /* sum of lost packets */
670 uint16_t dl_loss_received; /* sum of received packets */
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200671
672 BandWidth();
Daniel Willmann418a4232014-08-08 11:21:04 +0200673 } m_bw;
674
sivasankari53950732016-12-08 17:15:17 +0530675 struct rate_ctr_group *m_dl_gprs_ctrs;
676 struct rate_ctr_group *m_dl_egprs_ctrs;
677
Daniel Willmannb8f26012014-07-30 19:12:28 +0200678protected:
Jacob Erlbeck2db0f082015-09-07 18:49:00 +0200679 struct ana_result {
680 unsigned received_packets;
681 unsigned lost_packets;
682 unsigned received_bytes;
683 unsigned lost_bytes;
684 };
685
Jacob Erlbeckd6752492016-02-02 18:12:46 +0100686 int take_next_bsn(uint32_t fn, int previous_bsn,
Jacob Erlbeck64e7b832016-02-04 15:16:47 +0100687 bool *may_combine);
Jacob Erlbeckd6752492016-02-02 18:12:46 +0100688 bool restart_bsn_cycle();
689 int create_new_bsn(const uint32_t fn, GprsCodingScheme cs);
Daniel Willmannb8f26012014-07-30 19:12:28 +0200690 struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
Jacob Erlbeckbe314d92016-02-02 15:32:10 +0100691 int index, int index2 = -1);
Daniel Willmann30168882014-08-07 12:48:29 +0200692 int update_window(const uint8_t ssn, const uint8_t *rbb);
Jacob Erlbeckeb08f862016-02-05 17:07:12 +0100693 int update_window(unsigned first_bsn, const struct bitvec *rbb);
Daniel Willmann30168882014-08-07 12:48:29 +0200694 int maybe_start_new_window();
695 bool dl_window_stalled() const;
Jacob Erlbeck409efa12015-06-12 14:06:09 +0200696 void reuse_tbf();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200697 void start_llc_timer();
Jacob Erlbeck2db0f082015-09-07 18:49:00 +0200698 int analyse_errors(char *show_rbb, uint8_t ssn, ana_result *res);
Jacob Erlbeck409efa12015-06-12 14:06:09 +0200699 void schedule_next_frame();
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200700
Aravind Sirsikar50b09702016-08-22 17:21:10 +0530701 enum egprs_rlc_dl_reseg_bsn_state egprs_dl_get_data
702 (int bsn, uint8_t **block_data);
703 unsigned int get_egprs_dl_spb_status(int bsn);
704 enum egprs_rlcmac_dl_spb get_egprs_dl_spb(int bsn);
705
Jacob Erlbeckd0261b72015-04-02 13:58:09 +0200706 struct osmo_timer_list m_llc_timer;
Maxea98b7d2018-01-04 15:13:27 +0100707
708 /* Please note that all variables below will be reset when changing
709 * from WAIT RELEASE back to FLOW state (re-use of TBF).
710 * All states that need reset must be in this struct, so this is why
711 * variables are in both (dl and ul) structs and not outside union.
712 */
713 gprs_rlc_dl_window m_window;
Daniel Willmann078bb712014-07-10 17:44:06 +0200714};
715
716struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200717 gprs_rlcmac_ul_tbf(BTS *bts);
Maxea98b7d2018-01-04 15:13:27 +0100718 gprs_rlc_ul_window *window();
Jacob Erlbeck5a3c84d2016-01-22 17:25:38 +0100719 struct msgb *create_ul_ack(uint32_t fn, uint8_t ts);
Maxfd13f6c2017-07-07 14:29:36 +0200720 bool ctrl_ack_to_toggle();
721 bool handle_ctrl_ack();
Max25a3ca42017-12-13 18:47:52 +0100722 void enable_egprs();
Daniel Willmann350f64d2014-08-07 14:54:11 +0200723 /* blocks were acked */
Jacob Erlbeckb3100e12015-12-14 13:36:13 +0100724 int rcv_data_block_acknowledged(
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100725 const struct gprs_rlc_data_info *rlc,
Jacob Erlbeckfc1b3e62016-01-11 09:58:11 +0100726 uint8_t *data, struct pcu_l1_meas *meas);
Jacob Erlbeckb3100e12015-12-14 13:36:13 +0100727
Daniel Willmann350f64d2014-08-07 14:54:11 +0200728
Daniel Willmanne2732e22014-08-07 17:32:01 +0200729 /* TODO: extract LLC class? */
730 int assemble_forward_llc(const gprs_rlc_data *data);
731 int snd_ul_ud();
732
Aravind Sirsikar505a86d2016-07-26 18:26:21 +0530733 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_spb(
734 const struct gprs_rlc_data_info *rlc,
735 struct gprs_rlc_data *block,
736 uint8_t *data, const uint8_t block_idx);
737
738 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_first_seg(
739 const struct gprs_rlc_data_info *rlc,
740 struct gprs_rlc_data *block,
741 uint8_t *data, const uint8_t block_idx);
742
743 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_second_seg(
744 const struct gprs_rlc_data_info *rlc,
745 struct gprs_rlc_data *block,
746 uint8_t *data, const uint8_t block_idx);
747
Maxa4f570f2017-12-15 11:21:57 +0100748 uint16_t window_size() const;
Max9d7357e2017-12-14 15:02:33 +0100749 void set_window_size();
Maxfb59a932019-03-13 18:40:19 +0100750 void update_coding_scheme_counter_ul(enum CodingScheme cs);
Mrinal Mishraf86307e2016-11-10 18:16:30 +0530751
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200752 /* Please note that all variables here will be reset when changing
753 * from WAIT RELEASE back to FLOW state (re-use of TBF).
754 * All states that need reset must be in this struct, so this is why
755 * variables are in both (dl and ul) structs and not outside union.
756 */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200757 int32_t m_rx_counter; /* count all received blocks */
Daniel Willmann7e994e32014-08-07 15:49:21 +0200758 uint8_t m_usf[8]; /* list USFs per PDCH (timeslot) */
759 uint8_t m_contention_resolution_done; /* set after done */
760 uint8_t m_final_ack_sent; /* set if we sent final ack */
Daniel Willmann6a8a1dc2014-08-07 15:14:08 +0200761
sivasankarida7250a2016-12-16 12:57:18 +0530762 struct rate_ctr_group *m_ul_gprs_ctrs;
763 struct rate_ctr_group *m_ul_egprs_ctrs;
764
Daniel Willmann350f64d2014-08-07 14:54:11 +0200765protected:
Jacob Erlbeckf2ba4cb2016-01-07 18:59:28 +0100766 void maybe_schedule_uplink_acknack(const gprs_rlc_data_info *rlc);
Maxea98b7d2018-01-04 15:13:27 +0100767
768 /* Please note that all variables below will be reset when changing
769 * from WAIT RELEASE back to FLOW state (re-use of TBF).
770 * All states that need reset must be in this struct, so this is why
771 * variables are in both (dl and ul) structs and not outside union.
772 */
773 gprs_rlc_ul_window m_window;
Daniel Willmann078bb712014-07-10 17:44:06 +0200774};
775
Max701afa42017-12-01 17:13:22 +0100776#ifdef __cplusplus
777extern "C" {
778#endif
779void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta);
780void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta);
781#ifdef __cplusplus
782}
783#endif
784
Jacob Erlbeckac89a552015-06-29 14:18:46 +0200785inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir)
786{
787 return (enum gprs_rlcmac_tbf_direction)
788 ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF);
789}
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100790
Maxa4f570f2017-12-15 11:21:57 +0100791inline uint16_t gprs_rlcmac_ul_tbf::window_size() const
792{
793 return m_window.ws();
794}
795
796inline uint16_t gprs_rlcmac_dl_tbf::window_size() const
797{
798 return m_window.ws();
799}
800
Max25a3ca42017-12-13 18:47:52 +0100801inline void gprs_rlcmac_ul_tbf::enable_egprs()
802{
803 m_window.set_sns(RLC_EGPRS_SNS);
804 gprs_rlcmac_tbf::enable_egprs();
805}
806
807inline void gprs_rlcmac_dl_tbf::enable_egprs()
808{
809 m_window.set_sns(RLC_EGPRS_SNS);
810 gprs_rlcmac_tbf::enable_egprs();
811}
812
Jacob Erlbeckaa9daa12015-12-28 18:49:12 +0100813inline gprs_rlcmac_ul_tbf *as_ul_tbf(gprs_rlcmac_tbf *tbf)
814{
815 if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF)
816 return static_cast<gprs_rlcmac_ul_tbf *>(tbf);
817 else
818 return NULL;
819}
820
821inline gprs_rlcmac_dl_tbf *as_dl_tbf(gprs_rlcmac_tbf *tbf)
822{
823 if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF)
824 return static_cast<gprs_rlcmac_dl_tbf *>(tbf);
825 else
826 return NULL;
827}
828
Max9d7357e2017-12-14 15:02:33 +0100829uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots);
830
Daniel Willmannafa72f52014-01-15 17:06:19 +0100831#endif