diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/bts.cpp | 1 | ||||
-rw-r--r-- | src/encoding.cpp | 1 | ||||
-rw-r--r-- | src/gprs_ms.cpp | 1 | ||||
-rw-r--r-- | src/gprs_ms.h | 1 | ||||
-rw-r--r-- | src/gprs_rlcmac_meas.cpp | 1 | ||||
-rw-r--r-- | src/gprs_rlcmac_sched.cpp | 1 | ||||
-rw-r--r-- | src/gprs_rlcmac_ts_alloc.cpp | 1 | ||||
-rw-r--r-- | src/pcu_vty_functions.cpp | 1 | ||||
-rw-r--r-- | src/pdch.cpp | 1 | ||||
-rw-r--r-- | src/poll_controller.cpp | 1 | ||||
-rw-r--r-- | src/tbf.cpp | 2 | ||||
-rw-r--r-- | src/tbf.h | 238 | ||||
-rw-r--r-- | src/tbf_dl.cpp | 2 | ||||
-rw-r--r-- | src/tbf_dl.h | 160 | ||||
-rw-r--r-- | src/tbf_ul.cpp | 1 | ||||
-rw-r--r-- | src/tbf_ul.h | 138 | ||||
-rw-r--r-- | tests/alloc/AllocTest.cpp | 1 | ||||
-rw-r--r-- | tests/ms/MsTest.cpp | 1 | ||||
-rw-r--r-- | tests/tbf/TbfTest.cpp | 1 | ||||
-rw-r--r-- | tests/types/TypesTest.cpp | 1 |
21 files changed, 319 insertions, 238 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7148267b..a84a511a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -91,6 +91,8 @@ noinst_HEADERS = \ pcu_vty_functions.h \ mslot_class.h \ tbf.h \ + tbf_ul.h \ + tbf_dl.h \ bts.h \ pdch.h \ poll_controller.h \ diff --git a/src/bts.cpp b/src/bts.cpp index a8760ae7..df58494a 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -21,6 +21,7 @@ #include <bts.h> #include <poll_controller.h> #include <tbf.h> +#include <tbf_ul.h> #include <encoding.h> #include <decoding.h> #include <rlc.h> diff --git a/src/encoding.cpp b/src/encoding.cpp index 3fac75e0..82703540 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -23,6 +23,7 @@ #include <gprs_rlcmac.h> #include <bts.h> #include <tbf.h> +#include <tbf_ul.h> #include <gprs_debug.h> #include <egprs_rlc_compression.h> diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp index 75f75e17..5b35e65d 100644 --- a/src/gprs_ms.cpp +++ b/src/gprs_ms.cpp @@ -23,6 +23,7 @@ #include <gprs_coding_scheme.h> #include "bts.h" #include "tbf.h" +#include "tbf_ul.h" #include "gprs_debug.h" #include "gprs_codel.h" #include "pcu_utils.h" diff --git a/src/gprs_ms.h b/src/gprs_ms.h index 781dd59f..688708e7 100644 --- a/src/gprs_ms.h +++ b/src/gprs_ms.h @@ -26,6 +26,7 @@ struct gprs_codel; #include "cxx_linuxlist.h" #include "llc.h" #include "tbf.h" +#include "tbf_dl.h" #include "pcu_l1_if.h" #include <gprs_coding_scheme.h> diff --git a/src/gprs_rlcmac_meas.cpp b/src/gprs_rlcmac_meas.cpp index 4e58df38..998e01c7 100644 --- a/src/gprs_rlcmac_meas.cpp +++ b/src/gprs_rlcmac_meas.cpp @@ -23,6 +23,7 @@ #include <gprs_debug.h> #include <pcu_l1_if.h> #include <tbf.h> +#include <tbf_dl.h> #include <string.h> #include <errno.h> diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp index 5fedb5ae..fe6f1595 100644 --- a/src/gprs_rlcmac_sched.cpp +++ b/src/gprs_rlcmac_sched.cpp @@ -22,6 +22,7 @@ #include <pcu_l1_if.h> #include <bts.h> #include <tbf.h> +#include <tbf_ul.h> #include <gprs_debug.h> #include <gprs_ms.h> #include <rlc.h> diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp index 0476d6db..cf3f9a91 100644 --- a/src/gprs_rlcmac_ts_alloc.cpp +++ b/src/gprs_rlcmac_ts_alloc.cpp @@ -23,6 +23,7 @@ #include <gprs_debug.h> #include <bts.h> #include <tbf.h> +#include <tbf_ul.h> #include <pdch.h> #include <gprs_ms.h> #include <pcu_utils.h> diff --git a/src/pcu_vty_functions.cpp b/src/pcu_vty_functions.cpp index 98e81850..3008267f 100644 --- a/src/pcu_vty_functions.cpp +++ b/src/pcu_vty_functions.cpp @@ -32,6 +32,7 @@ #include <pcu_l1_if.h> #include <rlc.h> #include <tbf.h> +#include <tbf_ul.h> #include <pdch.h> extern "C" { diff --git a/src/pdch.cpp b/src/pdch.cpp index 24bbbb18..e4b25e1b 100644 --- a/src/pdch.cpp +++ b/src/pdch.cpp @@ -32,6 +32,7 @@ #include <rlc.h> #include <sba.h> #include <tbf.h> +#include <tbf_ul.h> #include <cxx_linuxlist.h> #include <gsm_rlcmac.h> diff --git a/src/poll_controller.cpp b/src/poll_controller.cpp index 744b612f..ac795101 100644 --- a/src/poll_controller.cpp +++ b/src/poll_controller.cpp @@ -23,6 +23,7 @@ #include <poll_controller.h> #include <bts.h> #include <tbf.h> +#include <tbf_ul.h> #include <cxx_linuxlist.h> #include <sba.h> diff --git a/src/tbf.cpp b/src/tbf.cpp index 37435f5d..3ca39bff 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -21,6 +21,8 @@ #include <bts.h> #include <tbf.h> +#include <tbf_dl.h> +#include <tbf_ul.h> #include <rlc.h> #include <encoding.h> #include <gprs_rlcmac.h> @@ -95,15 +95,6 @@ enum gprs_rlcmac_tbf_direction { GPRS_RLCMAC_UL_TBF }; -enum tbf_dl_prio { - DL_PRIO_NONE, - DL_PRIO_SENT_DATA, /* the data has been sent and not (yet) nacked */ - DL_PRIO_LOW_AGE, /* the age has reached the first threshold */ - DL_PRIO_NEW_DATA, /* the data has not been sent yet or nacked */ - DL_PRIO_HIGH_AGE, /* the age has reached the second threshold */ - DL_PRIO_CONTROL, /* a control block needs to be sent */ -}; - enum tbf_rlc_counters { TBF_CTR_RLC_NACKED, }; @@ -127,28 +118,7 @@ enum tbf_egprs_counters { TBF_CTR_EGPRS_DL_MCS9, }; -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, -}; - #define LOGPTBF(tbf, level, fmt, args...) LOGP(DTBF, level, "%s " fmt, tbf_name(tbf), ## args) -#define LOGPTBFUL(tbf, level, fmt, args...) LOGP(DTBFUL, level, "%s " fmt, tbf_name(tbf), ## args) -#define LOGPTBFDL(tbf, level, fmt, args...) LOGP(DTBFDL, level, "%s " fmt, tbf_name(tbf), ## args) enum tbf_timers { /* internal assign/reject timer */ @@ -612,220 +582,12 @@ inline void gprs_rlcmac_tbf::disable_egprs() m_egprs_enabled = false; } -struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf { - gprs_rlcmac_dl_tbf(BTS *bts); - gprs_rlc_dl_window *window(); - void cleanup(); - void enable_egprs(); - /* dispatch Unitdata.DL messages */ - static int handle(struct gprs_rlcmac_bts *bts, - const uint32_t tlli, const uint32_t old_tlli, - const char *imsi, const uint8_t ms_class, - const uint8_t egprs_ms_class, const uint16_t delay_csec, - const uint8_t *data, const uint16_t len); - - int append_data(const uint8_t ms_class, - const uint16_t pdu_delay_csec, - const uint8_t *data, const 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); - void trigger_ass(struct gprs_rlcmac_tbf *old_tbf); - - bool handle_ack_nack(); - void request_dl_ack(); - bool need_control_ts() 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); - - /* TODO: add the gettimeofday as parameter */ - 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; - int32_t m_last_dl_drained_fn; - - struct BandWidth { - struct timespec dl_bw_tv; /* timestamp for dl bw calculation */ - uint32_t dl_bw_octets; /* number of octets since bw_tv */ - uint32_t dl_throughput; /* throughput to be displayed in stats */ - - struct timespec dl_loss_tv; /* timestamp for loss calculation */ - uint16_t dl_loss_lost; /* sum of lost packets */ - uint16_t dl_loss_received; /* sum of received packets */ - - BandWidth(); - } m_bw; - - struct rate_ctr_group *m_dl_gprs_ctrs; - struct rate_ctr_group *m_dl_egprs_ctrs; - -protected: - struct ana_result { - unsigned received_packets; - unsigned lost_packets; - unsigned received_bytes; - unsigned lost_bytes; - }; - - int take_next_bsn(uint32_t fn, int previous_bsn, - bool *may_combine); - bool restart_bsn_cycle(); - int create_new_bsn(const uint32_t fn, GprsCodingScheme 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); - int update_window(unsigned first_bsn, const struct bitvec *rbb); - int maybe_start_new_window(); - 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(); - - enum egprs_rlc_dl_reseg_bsn_state egprs_dl_get_data - (int bsn, uint8_t **block_data); - 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 - * variables are in both (dl and ul) structs and not outside union. - */ - gprs_rlc_dl_window m_window; -}; - -struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf { - gprs_rlcmac_ul_tbf(BTS *bts); - gprs_rlc_ul_window *window(); - struct msgb *create_ul_ack(uint32_t fn, uint8_t ts); - bool ctrl_ack_to_toggle(); - bool handle_ctrl_ack(); - void enable_egprs(); - /* 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); - - /* 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) */ - 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); - - /* 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; -}; - -#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); -#ifdef __cplusplus -} -#endif - inline enum gprs_rlcmac_tbf_direction reverse(enum gprs_rlcmac_tbf_direction dir) { return (enum gprs_rlcmac_tbf_direction) ((int)GPRS_RLCMAC_UL_TBF - (int)dir + (int)GPRS_RLCMAC_DL_TBF); } -inline uint16_t gprs_rlcmac_ul_tbf::window_size() const -{ - return m_window.ws(); -} - -inline uint16_t gprs_rlcmac_dl_tbf::window_size() const -{ - return m_window.ws(); -} - -inline void gprs_rlcmac_ul_tbf::enable_egprs() -{ - m_window.set_sns(RLC_EGPRS_SNS); - gprs_rlcmac_tbf::enable_egprs(); -} - -inline void gprs_rlcmac_dl_tbf::enable_egprs() -{ - m_window.set_sns(RLC_EGPRS_SNS); - gprs_rlcmac_tbf::enable_egprs(); -} - -inline gprs_rlcmac_ul_tbf *as_ul_tbf(gprs_rlcmac_tbf *tbf) -{ - if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF) - return static_cast<gprs_rlcmac_ul_tbf *>(tbf); - else - return NULL; -} - -inline gprs_rlcmac_dl_tbf *as_dl_tbf(gprs_rlcmac_tbf *tbf) -{ - if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF) - return static_cast<gprs_rlcmac_dl_tbf *>(tbf); - else - return NULL; -} - uint16_t egprs_window_size(const struct gprs_rlcmac_bts *bts_data, uint8_t slots); #endif diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index 12c098a9..e9190f6e 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -21,6 +21,8 @@ #include <bts.h> #include <tbf.h> +#include <tbf_dl.h> +#include <tbf_ul.h> #include <rlc.h> #include <gprs_rlcmac.h> #include <gprs_debug.h> diff --git a/src/tbf_dl.h b/src/tbf_dl.h new file mode 100644 index 00000000..10116654 --- /dev/null +++ b/src/tbf_dl.h @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2013 by Holger Hans Peter Freyther + * Copyright (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * + * 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 "tbf.h" + +/* + * TBF instance + */ + +enum tbf_dl_prio { + DL_PRIO_NONE, + DL_PRIO_SENT_DATA, /* the data has been sent and not (yet) nacked */ + DL_PRIO_LOW_AGE, /* the age has reached the first threshold */ + DL_PRIO_NEW_DATA, /* the data has not been sent yet or nacked */ + DL_PRIO_HIGH_AGE, /* the age has reached the second threshold */ + 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_rlcmac_dl_tbf : public gprs_rlcmac_tbf { + gprs_rlcmac_dl_tbf(BTS *bts); + gprs_rlc_dl_window *window(); + void cleanup(); + void enable_egprs(); + /* dispatch Unitdata.DL messages */ + static int handle(struct gprs_rlcmac_bts *bts, + const uint32_t tlli, const uint32_t old_tlli, + const char *imsi, const uint8_t ms_class, + const uint8_t egprs_ms_class, const uint16_t delay_csec, + const uint8_t *data, const uint16_t len); + + int append_data(const uint8_t ms_class, + const uint16_t pdu_delay_csec, + const uint8_t *data, const 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); + void trigger_ass(struct gprs_rlcmac_tbf *old_tbf); + + bool handle_ack_nack(); + void request_dl_ack(); + bool need_control_ts() 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); + + /* TODO: add the gettimeofday as parameter */ + 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; + int32_t m_last_dl_drained_fn; + + struct BandWidth { + struct timespec dl_bw_tv; /* timestamp for dl bw calculation */ + uint32_t dl_bw_octets; /* number of octets since bw_tv */ + uint32_t dl_throughput; /* throughput to be displayed in stats */ + + struct timespec dl_loss_tv; /* timestamp for loss calculation */ + uint16_t dl_loss_lost; /* sum of lost packets */ + uint16_t dl_loss_received; /* sum of received packets */ + + BandWidth(); + } m_bw; + + struct rate_ctr_group *m_dl_gprs_ctrs; + struct rate_ctr_group *m_dl_egprs_ctrs; + +protected: + struct ana_result { + unsigned received_packets; + unsigned lost_packets; + unsigned received_bytes; + unsigned lost_bytes; + }; + + int take_next_bsn(uint32_t fn, int previous_bsn, + bool *may_combine); + bool restart_bsn_cycle(); + int create_new_bsn(const uint32_t fn, GprsCodingScheme 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); + int update_window(unsigned first_bsn, const struct bitvec *rbb); + int maybe_start_new_window(); + 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(); + + enum egprs_rlc_dl_reseg_bsn_state egprs_dl_get_data + (int bsn, uint8_t **block_data); + 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 + * variables are in both (dl and ul) structs and not outside union. + */ + gprs_rlc_dl_window m_window; +}; + +inline uint16_t gprs_rlcmac_dl_tbf::window_size() const +{ + return m_window.ws(); +} + +inline void gprs_rlcmac_dl_tbf::enable_egprs() +{ + m_window.set_sns(RLC_EGPRS_SNS); + gprs_rlcmac_tbf::enable_egprs(); +} + +inline gprs_rlcmac_dl_tbf *as_dl_tbf(gprs_rlcmac_tbf *tbf) +{ + if (tbf && tbf->direction == GPRS_RLCMAC_DL_TBF) + return static_cast<gprs_rlcmac_dl_tbf *>(tbf); + else + return NULL; +} +#endif diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp index 3fa8009e..a993cce5 100644 --- a/src/tbf_ul.cpp +++ b/src/tbf_ul.cpp @@ -21,6 +21,7 @@ #include <bts.h> #include <tbf.h> +#include <tbf_ul.h> #include <rlc.h> #include <encoding.h> #include <gprs_rlcmac.h> diff --git a/src/tbf_ul.h b/src/tbf_ul.h new file mode 100644 index 00000000..85da4f61 --- /dev/null +++ b/src/tbf_ul.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2013 by Holger Hans Peter Freyther + * Copyright (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * + * 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 "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, +}; + +#define LOGPTBFUL(tbf, level, fmt, args...) LOGP(DTBFUL, level, "%s " fmt, tbf_name(tbf), ## args) + +struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf { + gprs_rlcmac_ul_tbf(BTS *bts); + gprs_rlc_ul_window *window(); + struct msgb *create_ul_ack(uint32_t fn, uint8_t ts); + bool ctrl_ack_to_toggle(); + bool handle_ctrl_ack(); + void enable_egprs(); + /* 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); + + /* 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) */ + 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); + + /* 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; +}; + +#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); +#ifdef __cplusplus +} +#endif + +inline uint16_t gprs_rlcmac_ul_tbf::window_size() const +{ + return m_window.ws(); +} + +inline void gprs_rlcmac_ul_tbf::enable_egprs() +{ + m_window.set_sns(RLC_EGPRS_SNS); + gprs_rlcmac_tbf::enable_egprs(); +} + +inline gprs_rlcmac_ul_tbf *as_ul_tbf(gprs_rlcmac_tbf *tbf) +{ + if (tbf && tbf->direction == GPRS_RLCMAC_UL_TBF) + return static_cast<gprs_rlcmac_ul_tbf *>(tbf); + else + return NULL; +} + +#endif diff --git a/tests/alloc/AllocTest.cpp b/tests/alloc/AllocTest.cpp index 64d6a50f..123f879b 100644 --- a/tests/alloc/AllocTest.cpp +++ b/tests/alloc/AllocTest.cpp @@ -20,6 +20,7 @@ #include "gprs_rlcmac.h" #include "gprs_debug.h" #include "tbf.h" +#include "tbf_ul.h" #include "bts.h" #include <string.h> diff --git a/tests/ms/MsTest.cpp b/tests/ms/MsTest.cpp index c74b3a65..0c5ab9e5 100644 --- a/tests/ms/MsTest.cpp +++ b/tests/ms/MsTest.cpp @@ -21,6 +21,7 @@ */ #include "tbf.h" +#include "tbf_ul.h" #include "gprs_debug.h" #include "gprs_ms.h" #include "gprs_ms_storage.h" diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp index 2036023d..bd4fbc1f 100644 --- a/tests/tbf/TbfTest.cpp +++ b/tests/tbf/TbfTest.cpp @@ -22,6 +22,7 @@ #include "bts.h" #include "tbf.h" +#include "tbf_ul.h" #include "gprs_debug.h" #include "pcu_utils.h" #include "gprs_bssgp_pcu.h" diff --git a/tests/types/TypesTest.cpp b/tests/types/TypesTest.cpp index ee4e9370..aa0a3668 100644 --- a/tests/types/TypesTest.cpp +++ b/tests/types/TypesTest.cpp @@ -22,6 +22,7 @@ */ #include "bts.h" #include "tbf.h" +#include "tbf_ul.h" #include "pcu_utils.h" #include "gprs_debug.h" #include "encoding.h" |