rlc: Add unified gprs_rlc_window parent class

Currently gprs_rlc_ul_window and gprs_rlc_dl_window are completely
separate classes, containing several identical members and methods.

This commit add a shared parent class containing WS and SNS handling.

Sponsored-by: On-Waves ehf
diff --git a/src/bts.h b/src/bts.h
index e467c1e..c6247be 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -188,6 +188,8 @@
 	uint8_t cs_adj_lower_limit;
 	struct {int16_t low; int16_t high;} cs_lqual_ranges[4];
 	uint16_t cs_downgrade_threshold; /* downgrade if less packets left (DL) */
+	uint16_t egprs_ws_base;
+	uint16_t egprs_ws_lin;
 
 	/* State for dynamic algorithm selection */
 	int multislot_disabled;
diff --git a/src/rlc.cpp b/src/rlc.cpp
index 6d3cfd5..e4a9563 100644
--- a/src/rlc.cpp
+++ b/src/rlc.cpp
@@ -55,22 +55,6 @@
 	m_v_b.reset();
 }
 
-void gprs_rlc_dl_window::set_sns(uint16_t sns)
-{
-	OSMO_ASSERT(sns >= RLC_GPRS_SNS);
-	OSMO_ASSERT(sns <= RLC_MAX_SNS);
-	/* check for 2^n */
-	OSMO_ASSERT((sns & (-sns)) == sns);
-	m_sns = sns;
-}
-
-void gprs_rlc_dl_window::set_ws(uint16_t ws)
-{
-	OSMO_ASSERT(ws >= RLC_GPRS_SNS/2);
-	OSMO_ASSERT(ws <= RLC_MAX_SNS/2);
-	m_ws = ws;
-}
-
 int gprs_rlc_dl_window::resend_needed()
 {
 	for (uint16_t bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) {
@@ -219,7 +203,7 @@
 		m_v_n[i] = GPRS_RLC_UL_BSN_INVALID;
 }
 
-void gprs_rlc_ul_window::set_sns(uint16_t sns)
+void gprs_rlc_window::set_sns(uint16_t sns)
 {
 	OSMO_ASSERT(sns >= RLC_GPRS_SNS);
 	OSMO_ASSERT(sns <= RLC_MAX_SNS);
@@ -228,7 +212,7 @@
 	m_sns = sns;
 }
 
-void gprs_rlc_ul_window::set_ws(uint16_t ws)
+void gprs_rlc_window::set_ws(uint16_t ws)
 {
 	OSMO_ASSERT(ws >= RLC_GPRS_SNS/2);
 	OSMO_ASSERT(ws <= RLC_MAX_SNS/2);
diff --git a/src/rlc.h b/src/rlc.h
index 3f599d4..3a7f1a1 100644
--- a/src/rlc.h
+++ b/src/rlc.h
@@ -151,13 +151,26 @@
 /**
  * TODO: The UL/DL code could/should share a base class.
  */
-struct gprs_rlc_dl_window {
-	void reset();
+class gprs_rlc_window {
+public:
+	gprs_rlc_window();
+
 	const uint16_t mod_sns() const;
 	const uint16_t mod_sns(uint16_t bsn) const;
 	const uint16_t sns() const;
 	const uint16_t ws() const;
 
+	void set_sns(uint16_t sns);
+	void set_ws(uint16_t ws);
+
+protected:
+	uint16_t m_sns;
+	uint16_t m_ws;
+};
+
+struct gprs_rlc_dl_window: public gprs_rlc_window {
+	void reset();
+
 	bool window_stalled() const;
 	bool window_empty() const;
 
@@ -186,13 +199,7 @@
 
 	gprs_rlc_v_b m_v_b;
 
-	void set_sns(uint16_t sns);
-	void set_ws(uint16_t ws);
-
 	gprs_rlc_dl_window();
-private:
-	uint16_t m_sns;
-	uint16_t m_ws;
 };
 
 struct gprs_rlc_v_n {
@@ -210,12 +217,7 @@
 	gprs_rlc_ul_bsn_state m_v_n[RLC_MAX_SNS/2]; /* receive state array */
 };
 
-struct gprs_rlc_ul_window {
-	const uint16_t mod_sns() const;
-	const uint16_t mod_sns(uint16_t bsn) const;
-	const uint16_t sns() const;
-	const uint16_t ws() const;
-
+struct gprs_rlc_ul_window: public gprs_rlc_window {
 	const uint16_t v_r() const;
 	const uint16_t v_q() const;
 
@@ -239,13 +241,7 @@
 
 	gprs_rlc_v_n m_v_n;
 
-	void set_sns(uint16_t sns);
-	void set_ws(uint16_t ws);
-
 	gprs_rlc_ul_window();
-private:
-	uint16_t m_sns;
-	uint16_t m_ws;
 };
 
 extern "C" {
@@ -388,34 +384,38 @@
 	return mark(bsn, GPRS_RLC_DL_BSN_INVALID);
 }
 
-inline gprs_rlc_dl_window::gprs_rlc_dl_window()
-	: m_v_s(0)
-	, m_v_a(0)
-	, m_sns(RLC_GPRS_SNS)
+inline gprs_rlc_window::gprs_rlc_window()
+	: m_sns(RLC_GPRS_SNS)
 	, m_ws(RLC_GPRS_WS)
 {
 }
 
-inline const uint16_t gprs_rlc_dl_window::sns() const
+inline const uint16_t gprs_rlc_window::sns() const
 {
 	return m_sns;
 }
 
-inline const uint16_t gprs_rlc_dl_window::ws() const
+inline const uint16_t gprs_rlc_window::ws() const
 {
 	return m_ws;
 }
 
-inline const uint16_t gprs_rlc_dl_window::mod_sns() const
+inline const uint16_t gprs_rlc_window::mod_sns() const
 {
 	return sns() - 1;
 }
 
-inline const uint16_t gprs_rlc_dl_window::mod_sns(uint16_t bsn) const
+inline const uint16_t gprs_rlc_window::mod_sns(uint16_t bsn) const
 {
 	return bsn & mod_sns();
 }
 
+inline gprs_rlc_dl_window::gprs_rlc_dl_window()
+	: m_v_s(0)
+	, m_v_a(0)
+{
+}
+
 inline const uint16_t gprs_rlc_dl_window::v_s() const
 {
 	return m_v_s;
@@ -459,8 +459,6 @@
 inline gprs_rlc_ul_window::gprs_rlc_ul_window()
 	: m_v_r(0)
 	, m_v_q(0)
-	, m_sns(RLC_GPRS_SNS)
-	, m_ws(RLC_GPRS_WS)
 {
 }
 
@@ -484,26 +482,6 @@
 	return is_in_window(bsn) && m_v_n.is_received(bsn) && offset_v_r < ws();
 }
 
-inline const uint16_t gprs_rlc_ul_window::sns() const
-{
-	return m_sns;
-}
-
-inline const uint16_t gprs_rlc_ul_window::ws() const
-{
-	return m_ws;
-}
-
-inline const uint16_t gprs_rlc_ul_window::mod_sns() const
-{
-	return sns() - 1;
-}
-
-inline const uint16_t gprs_rlc_ul_window::mod_sns(uint16_t bsn) const
-{
-	return bsn & mod_sns();
-}
-
 inline const uint16_t gprs_rlc_ul_window::v_r() const
 {
 	return m_v_r;