aboutsummaryrefslogtreecommitdiffstats
path: root/src/rlc.h
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-11-24 20:36:36 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-11-26 21:00:51 +0100
commitf1593b7c49bd54caae9326c79156741e6078c412 (patch)
tree25104f4c817acd77276df41ece87ee59ff203d54 /src/rlc.h
parentab6cd921e3e47481ecdab93d1df1ce7f14b72e0a (diff)
tbf/rlc: Big change and move the window handling out to the rlc
The send and receive window is now managed by an external object. There are some issues that can only be solved with C++11 but it is progres and removes some of the spaghetti code. For GPRS the sns and ws is hardcoded. Move that into the window code.
Diffstat (limited to 'src/rlc.h')
-rw-r--r--src/rlc.h173
1 files changed, 161 insertions, 12 deletions
diff --git a/src/rlc.h b/src/rlc.h
index ba4d013c..e08a5d70 100644
--- a/src/rlc.h
+++ b/src/rlc.h
@@ -44,24 +44,67 @@ struct gprs_rlc {
gprs_rlc_data blocks[RLC_MAX_SNS/2];
};
+
+/**
+ * TODO: The UL/DL code could/should share a baseclass but
+ * we are using llist_for_each_entry for the TBF which
+ * requires everything which creates a requirement for a POD
+ * type and in < C++11 something that is using even if the
+ * most simple form of inheritance is not a POD anymore.
+ */
+struct gprs_rlc_dl_window {
+ const uint16_t mod_sns() const;
+ const uint16_t mod_sns_half() const;
+ const uint16_t sns() const;
+ const uint16_t ws() const;
+
+ bool window_stalled() const;
+ bool window_empty() const;
+
+ void increment_send();
+ void raise(int moves);
+
+ const uint16_t v_s() const;
+ const uint16_t v_s_mod(int offset) const;
+ const uint16_t v_s_mod_half(int offset) const;
+ const uint16_t v_a() const;
+ const int16_t distance() const;
+
+ uint16_t m_bsn; /* block sequence number */
+ uint16_t m_v_s; /* send state */
+ uint16_t m_v_a; /* ack state */
+};
+
+struct gprs_rlc_ul_window {
+ const uint16_t mod_sns() const;
+ const uint16_t mod_sns_half() const;
+ const uint16_t sns() const;
+ const uint16_t ws() const;
+
+ const uint16_t v_r() const;
+ const uint16_t v_q() const;
+
+ void raise(int moves);
+ void increment_q(int);
+
+ uint16_t m_bsn; /* block sequence number */
+ uint16_t m_v_r; /* receive state */
+ uint16_t m_v_q; /* receive window state */
+};
+
/**
* TODO: for GPRS/EDGE maybe make sns a template parameter
* so we create specialized versions...
*/
struct gprs_rlc_v_b {
- int resend_needed(const uint16_t acked, const uint16_t sent,
- const uint16_t mod_sns, const uint16_t mod_sns_half);
- int mark_for_resend(const uint16_t acked, const uint16_t sent,
- const uint16_t mod_sns, const uint16_t mod_sns_half);
- void update(BTS *bts, char *show_rbb, uint8_t ssn, const uint16_t v_a,
- const uint16_t mod_sns, const uint16_t mod_sns_half,
+ int resend_needed(const gprs_rlc_dl_window& window);
+ int mark_for_resend(const gprs_rlc_dl_window& window);
+ void update(BTS *bts, char *show_rbb, uint8_t ssn,
+ const gprs_rlc_dl_window& window,
uint16_t *lost, uint16_t *received);
- int move_window(const uint16_t v_a, const uint16_t v_s,
- const uint16_t mod_sns, const uint16_t mod_sns_half);
- void state(char *show_rbb, const uint16_t v_a, const uint16_t v_s,
- const uint16_t mod_sns, const uint16_t mod_sns_half);
- int count_unacked(const uint16_t v_a, const uint16_t v_s,
- const uint16_t mod_sns, const uint16_t mod_sns_half);
+ int move_window(const gprs_rlc_dl_window& window);
+ void state(char *show_rbb, const gprs_rlc_dl_window& window);
+ int count_unacked(const gprs_rlc_dl_window& window);
/* Check for an individual frame */
bool is_unacked(int index) const;
@@ -180,3 +223,109 @@ inline void gprs_rlc_v_b::mark_invalid(int index)
{
return mark(index, 'I');
}
+
+
+inline const uint16_t gprs_rlc_dl_window::sns() const
+{
+ return 128;
+}
+
+inline const uint16_t gprs_rlc_dl_window::ws() const
+{
+ return 64;
+}
+
+inline const uint16_t gprs_rlc_dl_window::mod_sns() const
+{
+ return sns() - 1;
+}
+
+inline const uint16_t gprs_rlc_dl_window::mod_sns_half() const
+{
+ return (sns() >> 1) - 1;
+}
+
+inline const uint16_t gprs_rlc_dl_window::v_s() const
+{
+ return m_v_s;
+}
+
+inline const uint16_t gprs_rlc_dl_window::v_s_mod_half(int offset) const
+{
+ return (m_v_s + offset) & mod_sns_half();
+}
+
+inline const uint16_t gprs_rlc_dl_window::v_s_mod(int offset) const
+{
+ return (m_v_s + offset) & mod_sns();
+}
+
+inline const uint16_t gprs_rlc_dl_window::v_a() const
+{
+ return m_v_a;
+}
+
+inline bool gprs_rlc_dl_window::window_stalled() const
+{
+ return ((m_v_s - m_v_a) & mod_sns()) == ws();
+}
+
+inline bool gprs_rlc_dl_window::window_empty() const
+{
+ return m_v_s == m_v_a;
+}
+
+inline void gprs_rlc_dl_window::increment_send()
+{
+ m_v_s = (m_v_s + 1) & mod_sns();
+}
+
+inline void gprs_rlc_dl_window::raise(int moves)
+{
+ m_v_a = (m_v_a + moves) & mod_sns();
+}
+
+inline const int16_t gprs_rlc_dl_window::distance() const
+{
+ return (m_v_s - m_v_a) & mod_sns();
+}
+
+inline const uint16_t gprs_rlc_ul_window::sns() const
+{
+ return 128;
+}
+
+inline const uint16_t gprs_rlc_ul_window::ws() const
+{
+ return 64;
+}
+
+inline const uint16_t gprs_rlc_ul_window::mod_sns() const
+{
+ return sns() - 1;
+}
+
+inline const uint16_t gprs_rlc_ul_window::mod_sns_half() const
+{
+ return (sns() >> 1) - 1;
+}
+
+inline const uint16_t gprs_rlc_ul_window::v_r() const
+{
+ return m_v_r;
+}
+
+inline const uint16_t gprs_rlc_ul_window::v_q() const
+{
+ return m_v_q;
+}
+
+inline void gprs_rlc_ul_window::raise(int moves)
+{
+ m_v_r = (m_v_r + moves) & mod_sns();
+}
+
+inline void gprs_rlc_ul_window::increment_q(int incr)
+{
+ m_v_q = (m_v_q + incr) & mod_sns();
+}