diff options
Diffstat (limited to 'src/tbf_dl.h')
-rw-r--r-- | src/tbf_dl.h | 86 |
1 files changed, 57 insertions, 29 deletions
diff --git a/src/tbf_dl.h b/src/tbf_dl.h index 58d863b3..59a03565 100644 --- a/src/tbf_dl.h +++ b/src/tbf_dl.h @@ -11,10 +11,6 @@ * 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 @@ -22,9 +18,18 @@ #ifdef __cplusplus #include "tbf.h" +#include "rlc_window_dl.h" #include <stdint.h> +#ifdef __cplusplus +extern "C" { +#endif +#include <tbf_fsm.h> +#ifdef __cplusplus +} +#endif + /* * TBF instance */ @@ -38,46 +43,51 @@ enum tbf_dl_prio { DL_PRIO_CONTROL, /* a control block needs to be sent */ }; -#define LOGPTBFDL(tbf, level, fmt, args...) LOGP(DTBFDL, level, "%s " fmt, tbf_name(tbf), ## args) +struct gprs_dl_llc_llist_item { + struct llist_head list; /* this item added in dl_tbf->tx_llc_until_first_dl_ack_rcvd */ + struct gprs_llc llc; +}; struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf { gprs_rlcmac_dl_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms); + ~gprs_rlcmac_dl_tbf(); gprs_rlc_window *window(); - void cleanup(); + void apply_allocated_resources(const struct alloc_resources_res *res); - int append_data(uint16_t pdu_delay_csec, - const uint8_t *data, uint16_t len); - - int rcvd_dl_ack(bool final, uint8_t ssn, uint8_t *rbb); int rcvd_dl_ack(bool final_ack, unsigned first_bsn, struct bitvec *rbb); - struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts, enum mcs_kind req_mcs_kind = EGPRS); - void trigger_ass(struct gprs_rlcmac_tbf *old_tbf); + struct msgb *create_dl_acked_block(uint32_t fn, const gprs_rlcmac_pdch *pdch, + enum mcs_kind req_mcs_kind = EGPRS); - bool handle_ack_nack(); void request_dl_ack(); - bool need_control_ts() const; + bool need_poll_for_dl_ack_nack() const; bool have_data() const; int frames_since_last_poll(unsigned fn) const; int frames_since_last_drain(unsigned fn) const; bool keep_open(unsigned fn) const; int release(); - int abort(); uint16_t window_size() const; void set_window_size(); void update_coding_scheme_counter_dl(enum CodingScheme cs); - struct msgb *llc_dequeue(bssgp_bvc_ctx *bctx); - /* 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_tx_counter; /* count all transmitted blocks */ - uint8_t m_wait_confirm; /* wait for CCCH IMM.ASS cnf */ bool m_dl_ack_requested; int32_t m_last_dl_poll_fn; + /* Whether we failed to receive ("poll timeout") last PKT CTRL ACK from + * MS polled during DL ACK/NACK with RRBP set in "m_last_dl_poll_fn": */ + bool m_last_dl_poll_ack_lost; int32_t m_last_dl_drained_fn; + /* Whether we receive at least one PKT DL ACK/NACK from MS since this DL TBF was assigned: */ + bool m_first_dl_ack_rcvd; + + /* Keep transmitted LLC PDUs until first ACK to avoid losing them if MS is not there. + * list of gprs_dl_llc_llist_item, stored in inverse order of transmission (last transmitted + * is first in the list ) */ + struct llist_head tx_llc_until_first_dl_ack_rcvd; struct BandWidth { struct timespec dl_bw_tv; /* timestamp for dl bw calculation */ @@ -94,6 +104,8 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf { struct rate_ctr_group *m_dl_gprs_ctrs; struct rate_ctr_group *m_dl_egprs_ctrs; + struct tbf_dl_fsm_ctx state_fsm; + protected: struct ana_result { unsigned received_packets; @@ -106,14 +118,12 @@ protected: bool *may_combine); bool restart_bsn_cycle(); int create_new_bsn(const uint32_t fn, enum CodingScheme cs); - struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts, - int index, int index2 = -1); - int update_window(const uint8_t ssn, const uint8_t *rbb); + struct msgb *create_dl_acked_block(const uint32_t fn, const struct gprs_rlcmac_pdch *pdch, + int index, int index2 = -1); int update_window(unsigned first_bsn, const struct bitvec *rbb); - int maybe_start_new_window(); + int rcvd_dl_final_ack(); bool dl_window_stalled() const; void reuse_tbf(); - void start_llc_timer(); int analyse_errors(char *show_rbb, uint8_t ssn, ana_result *res); void schedule_next_frame(); @@ -122,8 +132,6 @@ protected: unsigned int get_egprs_dl_spb_status(int bsn); enum egprs_rlcmac_dl_spb get_egprs_dl_spb(int bsn); - struct osmo_timer_list m_llc_timer; - /* 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 @@ -137,9 +145,6 @@ inline uint16_t gprs_rlcmac_dl_tbf::window_size() const return m_window.ws(); } -struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, GprsMs *ms, - int8_t use_trx, bool single_slot); - #else /* ifdef __cplusplus */ struct gprs_rlcmac_dl_tbf; #endif @@ -149,7 +154,10 @@ extern "C" { #endif struct gprs_rlcmac_bts; -struct gprs_rlcmac_dl_tbf *as_dl_tbf(struct gprs_rlcmac_tbf *tbf); +struct gprs_rlcmac_dl_tbf *dl_tbf_alloc(struct gprs_rlcmac_bts *bts, struct GprsMs *ms); + +struct gprs_rlcmac_dl_tbf *tbf_as_dl_tbf(struct gprs_rlcmac_tbf *tbf); +const struct gprs_rlcmac_dl_tbf *tbf_as_dl_tbf_const(const struct gprs_rlcmac_tbf *tbf); /* dispatch Unitdata.DL messages */ int dl_tbf_handle(struct gprs_rlcmac_bts *bts, const uint32_t tlli, const uint32_t old_tlli, @@ -157,6 +165,26 @@ int dl_tbf_handle(struct gprs_rlcmac_bts *bts, const uint8_t egprs_ms_class, const uint16_t delay_csec, const uint8_t *data, const uint16_t len); +void dl_tbf_apply_allocated_resources(struct gprs_rlcmac_dl_tbf *dl_tbf, const struct alloc_resources_res *res); +void dl_tbf_trigger_ass_on_pacch(struct gprs_rlcmac_dl_tbf *tbf, struct gprs_rlcmac_tbf *old_tbf); +void dl_tbf_trigger_ass_on_pch(struct gprs_rlcmac_dl_tbf *tbf); +void dl_tbf_request_dl_ack(struct gprs_rlcmac_dl_tbf *tbf); +bool dl_tbf_first_dl_ack_rcvd(const struct gprs_rlcmac_dl_tbf *tbf); +int dl_tbf_upgrade_to_multislot(struct gprs_rlcmac_dl_tbf *tbf); + +void dl_tbf_copy_unacked_pdus_to_llc_queue(struct gprs_rlcmac_dl_tbf *tbf); + +static inline struct gprs_rlcmac_tbf *dl_tbf_as_tbf(struct gprs_rlcmac_dl_tbf *dl_tbf) +{ + return (struct gprs_rlcmac_tbf *)dl_tbf; +} + +static inline const struct gprs_rlcmac_tbf *dl_tbf_as_tbf_const(const struct gprs_rlcmac_dl_tbf *dl_tbf) +{ + return (const struct gprs_rlcmac_tbf *)dl_tbf; +} + +#define LOGPTBFDL(dl_tbf, level, fmt, args...) LOGP(DTBFDL, level, "%s " fmt, tbf_name(dl_tbf_as_tbf_const(dl_tbf)), ## args) #ifdef __cplusplus } #endif |