blob: aa54c8fbba916f3bfc607b1d968efb96e30520b5 [file] [log] [blame]
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +02001/*
2 * Copyright (C) 2013 by Holger Hans Peter Freyther
3 * Copyright (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +020014 */
15
16#pragma once
17
18#ifdef __cplusplus
19
Pau Espin Pedrolc33a0242020-05-15 16:57:48 +020020#include <stdbool.h>
21
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +020022#include "tbf.h"
Pau Espin Pedrolea8dbdd2021-07-29 18:39:16 +020023
24#ifdef __cplusplus
25extern "C" {
26#endif
Pau Espin Pedrol343c0ee2022-11-17 19:55:08 +010027#include <tbf_fsm.h>
Pau Espin Pedrolea8dbdd2021-07-29 18:39:16 +020028#include <tbf_ul_ack_fsm.h>
29#ifdef __cplusplus
30}
31#endif
32
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +020033/*
34 * TBF instance
35 */
36
37enum tbf_gprs_ul_counters {
38 TBF_CTR_GPRS_UL_CS1,
39 TBF_CTR_GPRS_UL_CS2,
40 TBF_CTR_GPRS_UL_CS3,
41 TBF_CTR_GPRS_UL_CS4,
42};
43
44enum tbf_egprs_ul_counters {
45 TBF_CTR_EGPRS_UL_MCS1,
46 TBF_CTR_EGPRS_UL_MCS2,
47 TBF_CTR_EGPRS_UL_MCS3,
48 TBF_CTR_EGPRS_UL_MCS4,
49 TBF_CTR_EGPRS_UL_MCS5,
50 TBF_CTR_EGPRS_UL_MCS6,
51 TBF_CTR_EGPRS_UL_MCS7,
52 TBF_CTR_EGPRS_UL_MCS8,
53 TBF_CTR_EGPRS_UL_MCS9,
54};
55
Pau Espin Pedrol7bd92a32021-03-24 13:14:09 +010056/* Used in ul_tbf->m_usf[] to flag unassigned USF on a given TS: */
57#define USF_INVALID 0xFF
58
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +020059struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
Pau Espin Pedrol2182e622021-01-14 16:48:38 +010060 gprs_rlcmac_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms);
Pau Espin Pedrol131deb02021-07-26 18:24:14 +020061 ~gprs_rlcmac_ul_tbf();
Pau Espin Pedrolb3f23972020-10-23 21:00:23 +020062 gprs_rlc_window *window();
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +020063 /* blocks were acked */
64 int rcv_data_block_acknowledged(
65 const struct gprs_rlc_data_info *rlc,
66 uint8_t *data, struct pcu_l1_meas *meas);
67
68
69 /* TODO: extract LLC class? */
70 int assemble_forward_llc(const gprs_rlc_data *data);
71 int snd_ul_ud();
72
73 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_spb(
74 const struct gprs_rlc_data_info *rlc,
75 struct gprs_rlc_data *block,
76 uint8_t *data, const uint8_t block_idx);
77
78 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_first_seg(
79 const struct gprs_rlc_data_info *rlc,
80 struct gprs_rlc_data *block,
81 uint8_t *data, const uint8_t block_idx);
82
83 egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_second_seg(
84 const struct gprs_rlc_data_info *rlc,
85 struct gprs_rlc_data *block,
86 uint8_t *data, const uint8_t block_idx);
87
88 uint16_t window_size() const;
89 void set_window_size();
90 void update_coding_scheme_counter_ul(enum CodingScheme cs);
Pau Espin Pedrol0b998b12021-03-24 14:45:43 +010091 void usf_timeout();
Pau Espin Pedrol4b6f0bf2021-05-10 18:54:52 +020092 void contention_resolution_start();
93 void contention_resolution_success();
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +020094
95 /* Please note that all variables here will be reset when changing
96 * from WAIT RELEASE back to FLOW state (re-use of TBF).
97 * All states that need reset must be in this struct, so this is why
98 * variables are in both (dl and ul) structs and not outside union.
99 */
100 int32_t m_rx_counter; /* count all received blocks */
Pau Espin Pedrol7bd92a32021-03-24 13:14:09 +0100101 uint8_t m_usf[8]; /* list USFs per PDCH (timeslot), initialized to USF_INVALID */
Pau Espin Pedrol0f859562022-10-31 10:51:20 +0100102 bool m_contention_resolution_done; /* set after done */
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +0200103
104 struct rate_ctr_group *m_ul_gprs_ctrs;
105 struct rate_ctr_group *m_ul_egprs_ctrs;
106
Pau Espin Pedrol343c0ee2022-11-17 19:55:08 +0100107 struct tbf_ul_fsm_ctx state_fsm;
Pau Espin Pedrol57b25892022-12-13 16:37:24 +0100108 struct tbf_ul_ack_fsm_ctx ul_ack_fsm;
Pau Espin Pedrolea8dbdd2021-07-29 18:39:16 +0200109
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +0200110protected:
Pau Espin Pedrolc33a0242020-05-15 16:57:48 +0200111 void maybe_schedule_uplink_acknack(const gprs_rlc_data_info *rlc, bool countdown_finished);
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +0200112
113 /* Please note that all variables below will be reset when changing
114 * from WAIT RELEASE back to FLOW state (re-use of TBF).
115 * All states that need reset must be in this struct, so this is why
116 * variables are in both (dl and ul) structs and not outside union.
117 */
118 gprs_rlc_ul_window m_window;
119};
120
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +0200121inline uint16_t gprs_rlcmac_ul_tbf::window_size() const
122{
123 return m_window.ws();
124}
125
Pau Espin Pedrol442198c2020-10-23 22:30:04 +0200126
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100127#else /* ifdef __cplusplus */
128struct gprs_rlcmac_ul_tbf;
129#endif
130
131
132#ifdef __cplusplus
133extern "C" {
134#endif
Pau Espin Pedrolbda7bb72022-10-31 14:33:09 +0100135struct gprs_rlcmac_ul_tbf *ul_tbf_alloc(struct gprs_rlcmac_bts *bts, struct GprsMs *ms, int8_t use_trx, bool single_slot);
Pau Espin Pedrola621d592022-12-13 17:35:04 +0100136struct gprs_rlcmac_ul_tbf *ul_tbf_alloc_rejected(struct gprs_rlcmac_bts *bts, struct GprsMs *ms,
137 struct gprs_rlcmac_pdch *pdch);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100138void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta);
139void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta);
Pau Espin Pedrolcc30b052022-10-27 15:25:55 +0200140struct gprs_rlcmac_ul_tbf *tbf_as_ul_tbf(struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrol1e1275f2022-11-17 20:57:34 +0100141const struct gprs_rlcmac_ul_tbf *tbf_as_ul_tbf_const(const struct gprs_rlcmac_tbf *tbf);
Pau Espin Pedrol0b998b12021-03-24 14:45:43 +0100142void tbf_usf_timeout(struct gprs_rlcmac_ul_tbf *tbf);
Pau Espin Pedrol94386132022-10-28 19:50:09 +0200143void ul_tbf_contention_resolution_start(struct gprs_rlcmac_ul_tbf *tbf);
144void ul_tbf_contention_resolution_success(struct gprs_rlcmac_ul_tbf *tbf);
Pau Espin Pedrol49a2f402021-07-27 17:33:07 +0200145bool ul_tbf_contention_resolution_done(const struct gprs_rlcmac_ul_tbf *tbf);
Pau Espin Pedrolea8dbdd2021-07-29 18:39:16 +0200146struct osmo_fsm_inst *tbf_ul_ack_fi(const struct gprs_rlcmac_ul_tbf *tbf);
Pau Espin Pedrol6ad11a62021-07-27 12:27:08 +0200147
Pau Espin Pedrolbd1f01f2022-10-27 15:19:39 +0200148static inline struct gprs_rlcmac_tbf *ul_tbf_as_tbf(struct gprs_rlcmac_ul_tbf *ul_tbf)
149{
150 return (struct gprs_rlcmac_tbf *)ul_tbf;
151}
152
153static inline const struct gprs_rlcmac_tbf *ul_tbf_as_tbf_const(const struct gprs_rlcmac_ul_tbf *ul_tbf)
154{
155 return (const struct gprs_rlcmac_tbf *)ul_tbf;
156}
157
158#define LOGPTBFUL(ul_tbf, level, fmt, args...) LOGP(DTBFUL, level, "%s " fmt, tbf_name(ul_tbf_as_tbf_const(ul_tbf)), ## args)
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100159#ifdef __cplusplus
160}
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +0200161#endif