/* * Copyright (C) 2013 by Holger Hans Peter Freyther * Copyright (C) 2019 by sysmocom - s.f.m.c. GmbH * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #pragma once #ifdef __cplusplus #include #include "tbf.h" /* * TBF instance */ enum tbf_gprs_ul_counters { TBF_CTR_GPRS_UL_CS1, TBF_CTR_GPRS_UL_CS2, TBF_CTR_GPRS_UL_CS3, TBF_CTR_GPRS_UL_CS4, }; enum tbf_egprs_ul_counters { TBF_CTR_EGPRS_UL_MCS1, TBF_CTR_EGPRS_UL_MCS2, TBF_CTR_EGPRS_UL_MCS3, TBF_CTR_EGPRS_UL_MCS4, TBF_CTR_EGPRS_UL_MCS5, TBF_CTR_EGPRS_UL_MCS6, TBF_CTR_EGPRS_UL_MCS7, TBF_CTR_EGPRS_UL_MCS8, TBF_CTR_EGPRS_UL_MCS9, }; /* Used in ul_tbf->m_usf[] to flag unassigned USF on a given TS: */ #define USF_INVALID 0xFF struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf { gprs_rlcmac_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms); ~gprs_rlcmac_ul_tbf(); gprs_rlc_window *window(); struct msgb *create_ul_ack(uint32_t fn, uint8_t ts); bool ctrl_ack_to_toggle(); bool handle_ctrl_ack(enum pdch_ulc_tbf_poll_reason reason); /* blocks were acked */ int rcv_data_block_acknowledged( const struct gprs_rlc_data_info *rlc, uint8_t *data, struct pcu_l1_meas *meas); /* TODO: extract LLC class? */ int assemble_forward_llc(const gprs_rlc_data *data); int snd_ul_ud(); egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_spb( const struct gprs_rlc_data_info *rlc, struct gprs_rlc_data *block, uint8_t *data, const uint8_t block_idx); egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_first_seg( const struct gprs_rlc_data_info *rlc, struct gprs_rlc_data *block, uint8_t *data, const uint8_t block_idx); egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_second_seg( const struct gprs_rlc_data_info *rlc, struct gprs_rlc_data *block, uint8_t *data, const uint8_t block_idx); uint16_t window_size() const; void set_window_size(); void update_coding_scheme_counter_ul(enum CodingScheme cs); void usf_timeout(); void contention_resolution_start(); void contention_resolution_success(); /* Please note that all variables here will be reset when changing * from WAIT RELEASE back to FLOW state (re-use of TBF). * All states that need reset must be in this struct, so this is why * variables are in both (dl and ul) structs and not outside union. */ int32_t m_rx_counter; /* count all received blocks */ uint8_t m_usf[8]; /* list USFs per PDCH (timeslot), initialized to USF_INVALID */ uint8_t m_contention_resolution_done; /* set after done */ uint8_t m_final_ack_sent; /* set if we sent final ack */ struct rate_ctr_group *m_ul_gprs_ctrs; struct rate_ctr_group *m_ul_egprs_ctrs; protected: void maybe_schedule_uplink_acknack(const gprs_rlc_data_info *rlc, bool countdown_finished); /* Please note that all variables below will be reset when changing * from WAIT RELEASE back to FLOW state (re-use of TBF). * All states that need reset must be in this struct, so this is why * variables are in both (dl and ul) structs and not outside union. */ gprs_rlc_ul_window m_window; }; inline uint16_t gprs_rlcmac_ul_tbf::window_size() const { return m_window.ws(); } struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, bool single_slot); struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_pacch(struct gprs_rlcmac_bts *bts, GprsMs *ms, int8_t use_trx, uint32_t tlli); struct gprs_rlcmac_ul_tbf *tbf_alloc_ul_ccch(struct gprs_rlcmac_bts *bts, struct GprsMs *ms); struct gprs_rlcmac_ul_tbf *handle_tbf_reject(struct gprs_rlcmac_bts *bts, GprsMs *ms, uint8_t trx_no, uint8_t ts_no); #else /* ifdef __cplusplus */ struct gprs_rlcmac_ul_tbf; #endif #ifdef __cplusplus extern "C" { #endif void update_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, int8_t ta_delta); void set_tbf_ta(struct gprs_rlcmac_ul_tbf *tbf, uint8_t ta); struct gprs_rlcmac_ul_tbf *as_ul_tbf(struct gprs_rlcmac_tbf *tbf); void tbf_usf_timeout(struct gprs_rlcmac_ul_tbf *tbf); bool ul_tbf_contention_resolution_done(const struct gprs_rlcmac_ul_tbf *tbf); #define LOGPTBFUL(tbf, level, fmt, args...) LOGP(DTBFUL, level, "%s " fmt, tbf_name(tbf), ## args) #ifdef __cplusplus } #endif