lists.osmocom.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

gerrit-log

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
gerrit-log@lists.osmocom.org

July 2023

  • 1 participants
  • 3051 discussions
[XL] Change in osmo-pcu[master]: Split rlc_{dl_,ul_,}window out of rlc.{h,cpp}
by pespin 26 Jul '23

26 Jul '23
pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-pcu/+/33939 ) Change subject: Split rlc_{dl_,ul_,}window out of rlc.{h,cpp} ...................................................................... Split rlc_{dl_,ul_,}window out of rlc.{h,cpp} This new structure was already used when porting existing osmo-pcu code to libosmo-gprs-rlcmac, and proved to be much more clear. It makes no sense to keep both ul and dl window code mixed, since the code base is mostly different between them, and the developer usually is only interested in reading/debugging one side at a time. Change-Id: If21b6f48ef190a718502389cbfde8cbdfc8d7f7a --- M src/Makefile.am M src/decoding.cpp M src/rlc.cpp M src/rlc.h A src/rlc_window.cpp A src/rlc_window.h A src/rlc_window_dl.cpp A src/rlc_window_dl.h A src/rlc_window_ul.cpp A src/rlc_window_ul.h M src/tbf.h M src/tbf_dl.h M src/tbf_ul.h 13 files changed, 808 insertions(+), 656 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/39/33939/1 diff --git a/src/Makefile.am b/src/Makefile.am index 6153aa0..ded6632 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -79,6 +79,9 @@ decoding.cpp \ llc.c \ rlc.cpp \ + rlc_window.cpp \ + rlc_window_dl.cpp \ + rlc_window_ul.cpp \ osmobts_sock.c \ gprs_codel.c \ coding_scheme.c \ @@ -121,6 +124,9 @@ encoding.h \ sba.h \ rlc.h \ + rlc_window.h \ + rlc_window_dl.h \ + rlc_window_ul.h \ decoding.h \ llc.h \ pcu_utils.h \ diff --git a/src/decoding.cpp b/src/decoding.cpp index db6b072..9f93f01 100644 --- a/src/decoding.cpp +++ b/src/decoding.cpp @@ -15,6 +15,7 @@ */ #include <decoding.h> #include <rlc.h> +#include <rlc_window.h> #include <gprs_debug.h> #include <egprs_rlc_compression.h> diff --git a/src/rlc.cpp b/src/rlc.cpp index a082597..a8171a7 100644 --- a/src/rlc.cpp +++ b/src/rlc.cpp @@ -41,275 +41,11 @@ return rlc->block; } -void gprs_rlc_v_b::reset() -{ - for (size_t i = 0; i < ARRAY_SIZE(m_v_b); ++i) - mark_invalid(i); -} - -void gprs_rlc_dl_window::reset() -{ - m_v_s = 0; - m_v_a = 0; - m_v_b.reset(); -} - -int gprs_rlc_dl_window::resend_needed() const -{ - for (uint16_t bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) { - if (m_v_b.is_nacked(bsn) || m_v_b.is_resend(bsn)) - return bsn; - } - - return -1; -} - -int gprs_rlc_dl_window::mark_for_resend() -{ - int resend = 0; - - for (uint16_t bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) { - if (m_v_b.is_unacked(bsn)) { - /* mark to be re-send */ - m_v_b.mark_resend(bsn); - resend += 1; - } - } - - return resend; -} - -/* Update the receive block bitmap */ -uint16_t gprs_rlc_ul_window::update_egprs_rbb(uint8_t *rbb) -{ - uint16_t i; - uint16_t bsn; - uint16_t bitmask = 0x80; - int8_t pos = 0; - int8_t bit_pos = 0; - for (i = 0, bsn = (v_q()+1); ((bsn < (v_r())) && (i < ws())); i++, - bsn = this->mod_sns(bsn + 1)) { - if (m_v_n.is_received(bsn)) { - rbb[pos] = rbb[pos] | bitmask; - } else { - rbb[pos] = rbb[pos] & (~bitmask); - } - bitmask = bitmask >> 1; - bit_pos++; - bit_pos = bit_pos % 8; - if (bit_pos == 0) { - pos++; - bitmask = 0x80; - } - } - return i; -} - -int gprs_rlc_dl_window::count_unacked() -{ - uint16_t unacked = 0; - uint16_t bsn; - - for (bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) { - if (!m_v_b.is_acked(bsn)) - unacked += 1; - } - - return unacked; -} - static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn) { return (ssn - 1 - bitnum); } -void gprs_rlc_dl_window::update(struct gprs_rlcmac_bts *bts, const struct bitvec *rbb, - uint16_t first_bsn, uint16_t *lost, - uint16_t *received) -{ - unsigned dist = distance(); - unsigned num_blocks = rbb->cur_bit > dist - ? dist : rbb->cur_bit; - unsigned bsn; - - /* first_bsn is in range V(A)..V(S) */ - - for (unsigned int bitpos = 0; bitpos < num_blocks; bitpos++) { - bool is_ack; - bsn = mod_sns(first_bsn + bitpos); - if (bsn == mod_sns(v_a() - 1)) - break; - - is_ack = bitvec_get_bit_pos(rbb, bitpos) == 1; - - if (is_ack) { - LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn); - if (!m_v_b.is_acked(bsn)) - *received += 1; - m_v_b.mark_acked(bsn); - } else { - LOGP(DRLCMACDL, LOGL_DEBUG, "- got NACK for BSN=%d\n", bsn); - m_v_b.mark_nacked(bsn); - bts_do_rate_ctr_inc(bts, CTR_RLC_NACKED); - *lost += 1; - } - } -} - -void gprs_rlc_dl_window::update(struct gprs_rlcmac_bts *bts, char *show_rbb, uint16_t ssn, - uint16_t *lost, uint16_t *received) -{ - /* SSN - 1 is in range V(A)..V(S)-1 */ - for (int bitpos = 0; bitpos < ws(); bitpos++) { - uint16_t bsn = mod_sns(bitnum_to_bsn(bitpos, ssn)); - - if (bsn == mod_sns(v_a() - 1)) - break; - - if (show_rbb[ws() - 1 - bitpos] == 'R') { - LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn); - if (!m_v_b.is_acked(bsn)) - *received += 1; - m_v_b.mark_acked(bsn); - } else { - LOGP(DRLCMACDL, LOGL_DEBUG, "- got NACK for BSN=%d\n", bsn); - m_v_b.mark_nacked(bsn); - bts_do_rate_ctr_inc(bts, CTR_RLC_NACKED); - *lost += 1; - } - } -} - -int gprs_rlc_dl_window::move_window() -{ - int i; - uint16_t bsn; - int moved = 0; - - for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = mod_sns(bsn + 1)) { - if (m_v_b.is_acked(bsn)) { - m_v_b.mark_invalid(bsn); - moved += 1; - } else - break; - } - - return moved; -} - -void gprs_rlc_dl_window::show_state(char *show_v_b) -{ - int i; - uint16_t bsn; - - for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = mod_sns(bsn + 1)) { - uint16_t index = bsn & mod_sns_half(); - switch(m_v_b.get_state(index)) { - case GPRS_RLC_DL_BSN_INVALID: - show_v_b[i] = 'I'; - break; - case GPRS_RLC_DL_BSN_ACKED: - show_v_b[i] = 'A'; - break; - case GPRS_RLC_DL_BSN_RESEND: - show_v_b[i] = 'X'; - break; - case GPRS_RLC_DL_BSN_NACKED: - show_v_b[i] = 'N'; - break; - default: - show_v_b[i] = '?'; - } - } - show_v_b[i] = '\0'; -} - -void gprs_rlc_v_n::reset() -{ - for (size_t i = 0; i < ARRAY_SIZE(m_v_n); ++i) - m_v_n[i] = GPRS_RLC_UL_BSN_INVALID; -} - -void gprs_rlc_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_window::set_ws(uint16_t ws) -{ - LOGP(DRLCMAC, LOGL_INFO, "ws(%d)\n", - ws); - OSMO_ASSERT(ws >= RLC_GPRS_SNS/2); - OSMO_ASSERT(ws <= RLC_MAX_SNS/2); - m_ws = ws; -} - -/* Update the receive block bitmap */ -void gprs_rlc_ul_window::update_rbb(char *rbb) -{ - int i; - for (i=0; i < ws(); i++) { - if (m_v_n.is_received((ssn()-1-i) & mod_sns())) - rbb[ws()-1-i] = 'R'; - else - rbb[ws()-1-i] = 'I'; - } -} - -/* Raise V(R) to highest received sequence number not received. */ -void gprs_rlc_ul_window::raise_v_r(const uint16_t bsn) -{ - uint16_t offset_v_r; - offset_v_r = mod_sns(bsn + 1 - v_r()); - /* Positive offset, so raise. */ - if (offset_v_r < (sns() >> 1)) { - while (offset_v_r--) { - if (offset_v_r) /* all except the received block */ - m_v_n.mark_missing(v_r()); - raise_v_r_to(1); - } - LOGP(DRLCMACUL, LOGL_DEBUG, "- Raising V(R) to %d\n", v_r()); - } -} - -/* - * Raise V(Q) if possible. This is looped until there is a gap - * (non received block) or the window is empty. - */ -uint16_t gprs_rlc_ul_window::raise_v_q() -{ - uint16_t count = 0; - - while (v_q() != v_r()) { - if (!m_v_n.is_received(v_q())) - break; - LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising " - "V(Q) to %d\n", v_q(), mod_sns(v_q() + 1)); - raise_v_q(1); - count += 1; - } - - return count; -} - -void gprs_rlc_ul_window::receive_bsn(const uint16_t bsn) -{ - m_v_n.mark_received(bsn); - raise_v_r(bsn); -} - -bool gprs_rlc_ul_window::invalidate_bsn(const uint16_t bsn) -{ - bool was_valid = m_v_n.is_received(bsn); - m_v_n.mark_missing(bsn); - - return was_valid; -} - static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc, enum CodingScheme cs, bool with_padding, unsigned int header_bits, const unsigned int spb) diff --git a/src/rlc.h b/src/rlc.h index 5c6930c..dd2f0c7 100644 --- a/src/rlc.h +++ b/src/rlc.h @@ -29,34 +29,10 @@ #include <string.h> #define RLC_GPRS_SNS 128 /* GPRS, must be power of 2 */ -#define RLC_GPRS_WS 64 /* max window size */ -#define RLC_EGPRS_MIN_WS 64 /* min window size */ -#define RLC_EGPRS_MAX_WS 1024 /* min window size */ #define RLC_EGPRS_SNS 2048 /* EGPRS, must be power of 2 */ -#define RLC_EGPRS_MAX_BSN_DELTA 512 #define RLC_MAX_SNS RLC_EGPRS_SNS -#define RLC_MAX_WS RLC_EGPRS_MAX_WS #define RLC_MAX_LEN 74 /* MCS-9 data unit */ -struct gprs_rlcmac_bts; - -/* The state of a BSN in the send/receive window */ -enum gprs_rlc_ul_bsn_state { - GPRS_RLC_UL_BSN_INVALID, - GPRS_RLC_UL_BSN_RECEIVED, - GPRS_RLC_UL_BSN_MISSING, - GPRS_RLC_UL_BSN_MAX, -}; - -enum gprs_rlc_dl_bsn_state { - GPRS_RLC_DL_BSN_INVALID, - GPRS_RLC_DL_BSN_NACKED, - GPRS_RLC_DL_BSN_ACKED, - GPRS_RLC_DL_BSN_UNACKED, - GPRS_RLC_DL_BSN_RESEND, - GPRS_RLC_DL_BSN_MAX, -}; - /* * EGPRS resegment status information for UL * When only first split block is received bsn state @@ -239,138 +215,6 @@ gprs_rlc_data m_blocks[RLC_MAX_SNS/2]; }; -/** - * TODO: for GPRS/EDGE maybe make sns a template parameter - * so we create specialized versions... - */ -struct gprs_rlc_v_b { - /* Check for an individual frame */ - bool is_unacked(int bsn) const; - bool is_nacked(int bsn) const; - bool is_acked(int bsn) const; - bool is_resend(int bsn) const; - bool is_invalid(int bsn) const; - gprs_rlc_dl_bsn_state get_state(int bsn) const; - - /* Mark a RLC frame for something */ - void mark_unacked(int bsn); - void mark_nacked(int bsn); - void mark_acked(int bsn); - void mark_resend(int bsn); - void mark_invalid(int bsn); - - void reset(); - - -private: - bool is_state(int bsn, const gprs_rlc_dl_bsn_state state) const; - void mark(int bsn, const gprs_rlc_dl_bsn_state state); - - gprs_rlc_dl_bsn_state m_v_b[RLC_MAX_SNS/2]; /* acknowledge state array */ -}; - - -/** - * TODO: The UL/DL code could/should share a base class. - */ -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; - - 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_a() const; - const uint16_t distance() const; - - /* Methods to manage reception */ - int resend_needed() const; - int mark_for_resend(); - void update(struct gprs_rlcmac_bts *bts, char *show_rbb, uint16_t ssn, - uint16_t *lost, uint16_t *received); - void update(struct gprs_rlcmac_bts *bts, const struct bitvec *rbb, - uint16_t first_bsn, uint16_t *lost, - uint16_t *received); - int move_window(); - void show_state(char *show_v_b); - int count_unacked(); - - uint16_t m_v_s; /* send state */ - uint16_t m_v_a; /* ack state */ - - gprs_rlc_v_b m_v_b; - - gprs_rlc_dl_window(); -}; - -struct gprs_rlc_v_n { - void reset(); - - void mark_received(int bsn); - void mark_missing(int bsn); - - bool is_received(int bsn) const; - - gprs_rlc_ul_bsn_state state(int bsn) const; -private: - bool is_state(int bsn, const gprs_rlc_ul_bsn_state state) const; - void mark(int bsn, const gprs_rlc_ul_bsn_state state); - gprs_rlc_ul_bsn_state m_v_n[RLC_MAX_SNS/2]; /* receive state array */ -}; - -struct gprs_rlc_ul_window: public gprs_rlc_window { - const uint16_t v_r() const; - const uint16_t v_q() const; - - const void set_v_r(int); - const void set_v_q(int); - void reset_state(); - - const uint16_t ssn() const; - - bool is_in_window(uint16_t bsn) const; - bool is_received(uint16_t bsn) const; - - void update_rbb(char *rbb); - uint16_t update_egprs_rbb(uint8_t *rbb); - void raise_v_r_to(int moves); - void raise_v_r(const uint16_t bsn); - uint16_t raise_v_q(); - - void raise_v_q(int); - - void receive_bsn(const uint16_t bsn); - bool invalidate_bsn(const uint16_t bsn); - - uint16_t m_v_r; /* receive state */ - uint16_t m_v_q; /* receive window state */ - - gprs_rlc_v_n m_v_n; - - gprs_rlc_ul_window(); -}; - extern "C" { /* TS 44.060 10.2.2 */ struct rlc_ul_header { @@ -434,242 +278,6 @@ } __attribute__ ((packed)); } -inline bool gprs_rlc_v_b::is_state(int bsn, const gprs_rlc_dl_bsn_state type) const -{ - return m_v_b[bsn & mod_sns_half()] == type; -} - -inline void gprs_rlc_v_b::mark(int bsn, const gprs_rlc_dl_bsn_state type) -{ - m_v_b[bsn & mod_sns_half()] = type; -} - -inline bool gprs_rlc_v_b::is_nacked(int bsn) const -{ - return is_state(bsn, GPRS_RLC_DL_BSN_NACKED); -} - -inline bool gprs_rlc_v_b::is_acked(int bsn) const -{ - return is_state(bsn, GPRS_RLC_DL_BSN_ACKED); -} - -inline bool gprs_rlc_v_b::is_unacked(int bsn) const -{ - return is_state(bsn, GPRS_RLC_DL_BSN_UNACKED); -} - -inline bool gprs_rlc_v_b::is_resend(int bsn) const -{ - return is_state(bsn, GPRS_RLC_DL_BSN_RESEND); -} - -inline bool gprs_rlc_v_b::is_invalid(int bsn) const -{ - return is_state(bsn, GPRS_RLC_DL_BSN_INVALID); -} - -inline gprs_rlc_dl_bsn_state gprs_rlc_v_b::get_state(int bsn) const -{ - return m_v_b[bsn & mod_sns_half()]; -} - -inline void gprs_rlc_v_b::mark_resend(int bsn) -{ - return mark(bsn, GPRS_RLC_DL_BSN_RESEND); -} - -inline void gprs_rlc_v_b::mark_unacked(int bsn) -{ - return mark(bsn, GPRS_RLC_DL_BSN_UNACKED); -} - -inline void gprs_rlc_v_b::mark_acked(int bsn) -{ - return mark(bsn, GPRS_RLC_DL_BSN_ACKED); -} - -inline void gprs_rlc_v_b::mark_nacked(int bsn) -{ - return mark(bsn, GPRS_RLC_DL_BSN_NACKED); -} - -inline void gprs_rlc_v_b::mark_invalid(int bsn) -{ - return mark(bsn, GPRS_RLC_DL_BSN_INVALID); -} - -inline gprs_rlc_window::gprs_rlc_window() - : m_sns(RLC_GPRS_SNS) - , m_ws(RLC_GPRS_WS) -{ -} - -inline const uint16_t gprs_rlc_window::sns() const -{ - return m_sns; -} - -inline const uint16_t gprs_rlc_window::ws() const -{ - return m_ws; -} - -inline const uint16_t gprs_rlc_window::mod_sns() const -{ - return sns() - 1; -} - -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) -{ - reset(); -} - -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(int offset) const -{ - return mod_sns(m_v_s + offset); -} - -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 (mod_sns(m_v_s - m_v_a)) == 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 uint16_t gprs_rlc_dl_window::distance() const -{ - return (m_v_s - m_v_a) & mod_sns(); -} - -inline gprs_rlc_ul_window::gprs_rlc_ul_window() - : m_v_r(0) - , m_v_q(0) -{ - m_v_n.reset(); -} - -inline bool gprs_rlc_ul_window::is_in_window(uint16_t bsn) const -{ - uint16_t offset_v_q; - - /* current block relative to lowest unreceived block */ - offset_v_q = (bsn - m_v_q) & mod_sns(); - /* If out of window (may happen if blocks below V(Q) are received - * again. */ - return offset_v_q < ws(); -} - -inline bool gprs_rlc_ul_window::is_received(uint16_t bsn) const -{ - uint16_t offset_v_r; - - /* Offset to the end of the received window */ - offset_v_r = (m_v_r - 1 - bsn) & mod_sns(); - return is_in_window(bsn) && m_v_n.is_received(bsn) && offset_v_r < ws(); -} - -inline void gprs_rlc_ul_window::reset_state() -{ - m_v_r = 0; - m_v_q = 0; -} - -inline const void gprs_rlc_ul_window::set_v_r(int v_r) -{ - m_v_r = v_r; -} - -inline const void gprs_rlc_ul_window::set_v_q(int v_q) -{ - m_v_q = v_q; -} - -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 const uint16_t gprs_rlc_ul_window::ssn() const -{ - return m_v_r; -} - -inline void gprs_rlc_ul_window::raise_v_r_to(int moves) -{ - m_v_r = mod_sns(m_v_r + moves); -} - -inline void gprs_rlc_ul_window::raise_v_q(int incr) -{ - m_v_q = mod_sns(m_v_q + incr); -} - -inline void gprs_rlc_v_n::mark_received(int bsn) -{ - return mark(bsn, GPRS_RLC_UL_BSN_RECEIVED); -} - -inline void gprs_rlc_v_n::mark_missing(int bsn) -{ - return mark(bsn, GPRS_RLC_UL_BSN_MISSING); -} - -inline bool gprs_rlc_v_n::is_received(int bsn) const -{ - return is_state(bsn, GPRS_RLC_UL_BSN_RECEIVED); -} - -inline bool gprs_rlc_v_n::is_state(int bsn, gprs_rlc_ul_bsn_state type) const -{ - return m_v_n[bsn & mod_sns_half()] == type; -} - -inline void gprs_rlc_v_n::mark(int bsn, gprs_rlc_ul_bsn_state type) -{ - m_v_n[bsn & mod_sns_half()] = type; -} - -inline gprs_rlc_ul_bsn_state gprs_rlc_v_n::state(int bsn) const -{ - return m_v_n[bsn & mod_sns_half()]; -} - inline void gprs_rlc::init() { memset(m_blocks, 0, sizeof(m_blocks)); diff --git a/src/rlc_window.cpp b/src/rlc_window.cpp new file mode 100644 index 0000000..4fa1a5c --- /dev/null +++ b/src/rlc_window.cpp @@ -0,0 +1,41 @@ +/* RLC Window (common for both UL/DL TBF), 3GPP TS 44.060 + * + * Copyright (C) 2013 by Holger Hans Peter Freyther + * Copyright (C) 2023 sysmocom - s.f.m.c. GmbH <info(a)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. + */ + +#include "rlc_window.h" + +extern "C" { +#include <osmocom/core/utils.h> +#include <osmocom/core/bitvec.h> +#include <osmocom/core/logging.h> +} + +void gprs_rlc_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_window::set_ws(uint16_t ws) +{ + LOGP(DRLCMAC, LOGL_INFO, "ws(%d)\n", + ws); + OSMO_ASSERT(ws >= RLC_GPRS_SNS/2); + OSMO_ASSERT(ws <= RLC_MAX_SNS/2); + m_ws = ws; +} \ No newline at end of file diff --git a/src/rlc_window.h b/src/rlc_window.h new file mode 100644 index 0000000..c34cc7b --- /dev/null +++ b/src/rlc_window.h @@ -0,0 +1,69 @@ +/* RLC Window (common for both UL/DL TBF), 3GPP TS 44.060 + * + * Copyright (C) 2012 Ivan Klyuchnikov + * Copyright (C) 2012 Andreas Eversberg <jolly(a)eversberg.eu> + * Copyright (C) 2023 sysmocom - s.f.m.c. GmbH <info(a)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. + */ +#pragma once + +#include <stdint.h> + +#define RLC_GPRS_WS 64 /* max window size */ +#define RLC_EGPRS_MIN_WS 64 /* min window size */ +#define RLC_EGPRS_MAX_WS 1024 /* min window size */ +#define RLC_EGPRS_MAX_BSN_DELTA 512 +#define RLC_MAX_WS RLC_EGPRS_MAX_WS + +class gprs_rlc_window { +public: + gprs_rlc_window(); + + const uint16_t mod_sns(void) const; + const uint16_t mod_sns(uint16_t bsn) const; + const uint16_t sns(void) const; + const uint16_t ws(void) const; + + void set_sns(uint16_t sns); + void set_ws(uint16_t ws); + +protected: + uint16_t m_sns; + uint16_t m_ws; +}; + + +inline gprs_rlc_window::gprs_rlc_window(void) + : m_sns(RLC_GPRS_SNS) + , m_ws(RLC_GPRS_WS) +{ +} + +inline const uint16_t gprs_rlc_window::sns(void) const +{ + return m_sns; +} + +inline const uint16_t gprs_rlc_window::ws(void) const +{ + return m_ws; +} + +inline const uint16_t gprs_rlc_window::mod_sns(void) const +{ + return sns() - 1; +} + +inline const uint16_t gprs_rlc_window::mod_sns(uint16_t bsn) const +{ + return bsn & mod_sns(); +} diff --git a/src/rlc_window_dl.cpp b/src/rlc_window_dl.cpp new file mode 100644 index 0000000..deb1b27 --- /dev/null +++ b/src/rlc_window_dl.cpp @@ -0,0 +1,175 @@ +/* RLC Window (DL TBF), 3GPP TS 44.060 + * + * Copyright (C) 2013 by Holger Hans Peter Freyther + * Copyright (C) 2023 sysmocom - s.f.m.c. GmbH <info(a)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. + */ + +#include "rlc_window.h" + +extern "C" { +#include <osmocom/core/utils.h> +#include <osmocom/core/bitvec.h> +#include <osmocom/core/logging.h> +} + +void gprs_rlc_v_b::reset() +{ + for (size_t i = 0; i < ARRAY_SIZE(m_v_b); ++i) + mark_invalid(i); +} + +void gprs_rlc_dl_window::reset() +{ + m_v_s = 0; + m_v_a = 0; + m_v_b.reset(); +} + +int gprs_rlc_dl_window::resend_needed() const +{ + for (uint16_t bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) { + if (m_v_b.is_nacked(bsn) || m_v_b.is_resend(bsn)) + return bsn; + } + + return -1; +} + +int gprs_rlc_dl_window::mark_for_resend() +{ + int resend = 0; + + for (uint16_t bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) { + if (m_v_b.is_unacked(bsn)) { + /* mark to be re-send */ + m_v_b.mark_resend(bsn); + resend += 1; + } + } + + return resend; +} + +int gprs_rlc_dl_window::count_unacked() +{ + uint16_t unacked = 0; + uint16_t bsn; + + for (bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) { + if (!m_v_b.is_acked(bsn)) + unacked += 1; + } + + return unacked; +} + +void gprs_rlc_dl_window::update(struct gprs_rlcmac_bts *bts, const struct bitvec *rbb, + uint16_t first_bsn, uint16_t *lost, + uint16_t *received) +{ + unsigned dist = distance(); + unsigned num_blocks = rbb->cur_bit > dist + ? dist : rbb->cur_bit; + unsigned bsn; + + /* first_bsn is in range V(A)..V(S) */ + + for (unsigned int bitpos = 0; bitpos < num_blocks; bitpos++) { + bool is_ack; + bsn = mod_sns(first_bsn + bitpos); + if (bsn == mod_sns(v_a() - 1)) + break; + + is_ack = bitvec_get_bit_pos(rbb, bitpos) == 1; + + if (is_ack) { + LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn); + if (!m_v_b.is_acked(bsn)) + *received += 1; + m_v_b.mark_acked(bsn); + } else { + LOGP(DRLCMACDL, LOGL_DEBUG, "- got NACK for BSN=%d\n", bsn); + m_v_b.mark_nacked(bsn); + bts_do_rate_ctr_inc(bts, CTR_RLC_NACKED); + *lost += 1; + } + } +} + +void gprs_rlc_dl_window::update(struct gprs_rlcmac_bts *bts, char *show_rbb, uint16_t ssn, + uint16_t *lost, uint16_t *received) +{ + /* SSN - 1 is in range V(A)..V(S)-1 */ + for (int bitpos = 0; bitpos < ws(); bitpos++) { + uint16_t bsn = mod_sns(bitnum_to_bsn(bitpos, ssn)); + + if (bsn == mod_sns(v_a() - 1)) + break; + + if (show_rbb[ws() - 1 - bitpos] == 'R') { + LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn); + if (!m_v_b.is_acked(bsn)) + *received += 1; + m_v_b.mark_acked(bsn); + } else { + LOGP(DRLCMACDL, LOGL_DEBUG, "- got NACK for BSN=%d\n", bsn); + m_v_b.mark_nacked(bsn); + bts_do_rate_ctr_inc(bts, CTR_RLC_NACKED); + *lost += 1; + } + } +} + +int gprs_rlc_dl_window::move_window() +{ + int i; + uint16_t bsn; + int moved = 0; + + for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = mod_sns(bsn + 1)) { + if (m_v_b.is_acked(bsn)) { + m_v_b.mark_invalid(bsn); + moved += 1; + } else + break; + } + + return moved; +} + +void gprs_rlc_dl_window::show_state(char *show_v_b) +{ + int i; + uint16_t bsn; + + for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = mod_sns(bsn + 1)) { + uint16_t index = bsn & mod_sns_half(); + switch(m_v_b.get_state(index)) { + case GPRS_RLC_DL_BSN_INVALID: + show_v_b[i] = 'I'; + break; + case GPRS_RLC_DL_BSN_ACKED: + show_v_b[i] = 'A'; + break; + case GPRS_RLC_DL_BSN_RESEND: + show_v_b[i] = 'X'; + break; + case GPRS_RLC_DL_BSN_NACKED: + show_v_b[i] = 'N'; + break; + default: + show_v_b[i] = '?'; + } + } + show_v_b[i] = '\0'; +} \ No newline at end of file diff --git a/src/rlc_window_dl.h b/src/rlc_window_dl.h new file mode 100644 index 0000000..e2da614 --- /dev/null +++ b/src/rlc_window_dl.h @@ -0,0 +1,205 @@ +/* RLC Window (DL TBF), 3GPP TS 44.060 + * + * Copyright (C) 2012 Ivan Klyuchnikov + * Copyright (C) 2012 Andreas Eversberg <jolly(a)eversberg.eu> + * Copyright (C) 2023 sysmocom - s.f.m.c. GmbH <info(a)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. + */ +#pragma once + +#include "rlc.h" +#include "rlc_window.h" + +enum gprs_rlc_dl_bsn_state { + GPRS_RLC_DL_BSN_INVALID, + GPRS_RLC_DL_BSN_NACKED, + GPRS_RLC_DL_BSN_ACKED, + GPRS_RLC_DL_BSN_UNACKED, + GPRS_RLC_DL_BSN_RESEND, + GPRS_RLC_DL_BSN_MAX, +}; + +/** + * TODO: for GPRS/EDGE maybe make sns a template parameter + * so we create specialized versions... + */ +struct gprs_rlc_v_b { + /* Check for an individual frame */ + bool is_unacked(int bsn) const; + bool is_nacked(int bsn) const; + bool is_acked(int bsn) const; + bool is_resend(int bsn) const; + bool is_invalid(int bsn) const; + gprs_rlc_dl_bsn_state get_state(int bsn) const; + + /* Mark a RLC frame for something */ + void mark_unacked(int bsn); + void mark_nacked(int bsn); + void mark_acked(int bsn); + void mark_resend(int bsn); + void mark_invalid(int bsn); + + void reset(void); + + +private: + bool is_state(int bsn, const gprs_rlc_dl_bsn_state state) const; + void mark(int bsn, const gprs_rlc_dl_bsn_state state); + + gprs_rlc_dl_bsn_state m_v_b[RLC_MAX_SNS/2]; /* acknowledge state array */ +}; + +inline bool gprs_rlc_v_b::is_state(int bsn, const gprs_rlc_dl_bsn_state type) const +{ + return m_v_b[bsn & mod_sns_half()] == type; +} + +inline void gprs_rlc_v_b::mark(int bsn, const gprs_rlc_dl_bsn_state type) +{ + m_v_b[bsn & mod_sns_half()] = type; +} + +inline bool gprs_rlc_v_b::is_nacked(int bsn) const +{ + return is_state(bsn, GPRS_RLC_DL_BSN_NACKED); +} + +inline bool gprs_rlc_v_b::is_acked(int bsn) const +{ + return is_state(bsn, GPRS_RLC_DL_BSN_ACKED); +} + +inline bool gprs_rlc_v_b::is_unacked(int bsn) const +{ + return is_state(bsn, GPRS_RLC_DL_BSN_UNACKED); +} + +inline bool gprs_rlc_v_b::is_resend(int bsn) const +{ + return is_state(bsn, GPRS_RLC_DL_BSN_RESEND); +} + +inline bool gprs_rlc_v_b::is_invalid(int bsn) const +{ + return is_state(bsn, GPRS_RLC_DL_BSN_INVALID); +} + +inline gprs_rlc_dl_bsn_state gprs_rlc_v_b::get_state(int bsn) const +{ + return m_v_b[bsn & mod_sns_half()]; +} + +inline void gprs_rlc_v_b::mark_resend(int bsn) +{ + return mark(bsn, GPRS_RLC_DL_BSN_RESEND); +} + +inline void gprs_rlc_v_b::mark_unacked(int bsn) +{ + return mark(bsn, GPRS_RLC_DL_BSN_UNACKED); +} + +inline void gprs_rlc_v_b::mark_acked(int bsn) +{ + return mark(bsn, GPRS_RLC_DL_BSN_ACKED); +} + +inline void gprs_rlc_v_b::mark_nacked(int bsn) +{ + return mark(bsn, GPRS_RLC_DL_BSN_NACKED); +} + +inline void gprs_rlc_v_b::mark_invalid(int bsn) +{ + return mark(bsn, GPRS_RLC_DL_BSN_INVALID); +} + +struct gprs_rlc_dl_window : public gprs_rlc_window { + void reset(void); + + bool window_stalled(void) const; + bool window_empty(void) const; + + void increment_send(void); + void raise(int moves); + + const uint16_t v_s(void) const; + const uint16_t v_s_mod(int offset) const; + const uint16_t v_a(void) const; + const uint16_t distance(void) const; + + /* Methods to manage reception */ + int resend_needed(void) const; + int mark_for_resend(void); + void update(struct gprs_rlcmac_bts *bts, char *show_rbb, uint16_t ssn, + uint16_t *lost, uint16_t *received); + void update(struct gprs_rlcmac_bts *bts, const struct bitvec *rbb, + uint16_t first_bsn, uint16_t *lost, + uint16_t *received); + int move_window(void); + void show_state(char *show_v_b); + int count_unacked(void); + + uint16_t m_v_s; /* send state */ + uint16_t m_v_a; /* ack state */ + + gprs_rlc_v_b m_v_b; + + gprs_rlc_dl_window(void); +}; + +inline gprs_rlc_dl_window::gprs_rlc_dl_window(void) + : m_v_s(0) + , m_v_a(0) +{ + reset(); +} + +inline const uint16_t gprs_rlc_dl_window::v_s(void) const +{ + return m_v_s; +} + +inline const uint16_t gprs_rlc_dl_window::v_s_mod(int offset) const +{ + return mod_sns(m_v_s + offset); +} + +inline const uint16_t gprs_rlc_dl_window::v_a(void) const +{ + return m_v_a; +} + +inline bool gprs_rlc_dl_window::window_stalled(void) const +{ + return (mod_sns(m_v_s - m_v_a)) == ws(); +} + +inline bool gprs_rlc_dl_window::window_empty(void) const +{ + return m_v_s == m_v_a; +} + +inline void gprs_rlc_dl_window::increment_send(void) +{ + 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 uint16_t gprs_rlc_dl_window::distance(void) const +{ + return (m_v_s - m_v_a) & mod_sns(); +} diff --git a/src/rlc_window_ul.cpp b/src/rlc_window_ul.cpp new file mode 100644 index 0000000..cabb033 --- /dev/null +++ b/src/rlc_window_ul.cpp @@ -0,0 +1,118 @@ +/* RLC Window (UL TBF), 3GPP TS 44.060 + * + * Copyright (C) 2013 by Holger Hans Peter Freyther + * Copyright (C) 2023 sysmocom - s.f.m.c. GmbH <info(a)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. + */ + +#include "rlc_window.h" + +extern "C" { +#include <osmocom/core/utils.h> +#include <osmocom/core/bitvec.h> +#include <osmocom/core/logging.h> +} + +void gprs_rlc_v_n::reset() +{ + for (size_t i = 0; i < ARRAY_SIZE(m_v_n); ++i) + m_v_n[i] = GPRS_RLC_UL_BSN_INVALID; +} + +/* Raise V(R) to highest received sequence number not received. */ +void gprs_rlc_ul_window::raise_v_r(const uint16_t bsn) +{ + uint16_t offset_v_r; + offset_v_r = mod_sns(bsn + 1 - v_r()); + /* Positive offset, so raise. */ + if (offset_v_r < (sns() >> 1)) { + while (offset_v_r--) { + if (offset_v_r) /* all except the received block */ + m_v_n.mark_missing(v_r()); + raise_v_r_to(1); + } + LOGP(DRLCMACUL, LOGL_DEBUG, "- Raising V(R) to %d\n", v_r()); + } +} + +/* + * Raise V(Q) if possible. This is looped until there is a gap + * (non received block) or the window is empty. + */ +uint16_t gprs_rlc_ul_window::raise_v_q() +{ + uint16_t count = 0; + + while (v_q() != v_r()) { + if (!m_v_n.is_received(v_q())) + break; + LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising " + "V(Q) to %d\n", v_q(), mod_sns(v_q() + 1)); + raise_v_q(1); + count += 1; + } + + return count; +} + +void gprs_rlc_ul_window::receive_bsn(const uint16_t bsn) +{ + m_v_n.mark_received(bsn); + raise_v_r(bsn); +} + +bool gprs_rlc_ul_window::invalidate_bsn(const uint16_t bsn) +{ + bool was_valid = m_v_n.is_received(bsn); + m_v_n.mark_missing(bsn); + + return was_valid; +} + + +/* Update the receive block bitmap */ +uint16_t gprs_rlc_ul_window::update_egprs_rbb(uint8_t *rbb) +{ + uint16_t i; + uint16_t bsn; + uint16_t bitmask = 0x80; + int8_t pos = 0; + int8_t bit_pos = 0; + for (i = 0, bsn = (v_q()+1); ((bsn < (v_r())) && (i < ws())); i++, + bsn = this->mod_sns(bsn + 1)) { + if (m_v_n.is_received(bsn)) { + rbb[pos] = rbb[pos] | bitmask; + } else { + rbb[pos] = rbb[pos] & (~bitmask); + } + bitmask = bitmask >> 1; + bit_pos++; + bit_pos = bit_pos % 8; + if (bit_pos == 0) { + pos++; + bitmask = 0x80; + } + } + return i; +} + +/* Update the receive block bitmap */ +void gprs_rlc_ul_window::update_rbb(char *rbb) +{ + int i; + for (i=0; i < ws(); i++) { + if (m_v_n.is_received((ssn()-1-i) & mod_sns())) + rbb[ws()-1-i] = 'R'; + else + rbb[ws()-1-i] = 'I'; + } +} \ No newline at end of file diff --git a/src/rlc_window_ul.h b/src/rlc_window_ul.h new file mode 100644 index 0000000..aa85419 --- /dev/null +++ b/src/rlc_window_ul.h @@ -0,0 +1,175 @@ +/* RLC Window (UL TBF), 3GPP TS 44.060 + * + * Copyright (C) 2012 Ivan Klyuchnikov + * Copyright (C) 2012 Andreas Eversberg <jolly(a)eversberg.eu> + * Copyright (C) 2023 sysmocom - s.f.m.c. GmbH <info(a)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. + */ +#pragma once + +#include "rlc.h" +#include "rlc_window.h" + +/* The state of a BSN in the send/receive window */ +enum gprs_rlc_ul_bsn_state { + GPRS_RLC_UL_BSN_INVALID, + GPRS_RLC_UL_BSN_RECEIVED, + GPRS_RLC_UL_BSN_MISSING, + GPRS_RLC_UL_BSN_MAX, +}; + +struct gprs_rlc_v_n { + void reset(void); + + void mark_received(int bsn); + void mark_missing(int bsn); + + bool is_received(int bsn) const; + + gprs_rlc_ul_bsn_state state(int bsn) const; +private: + bool is_state(int bsn, const gprs_rlc_ul_bsn_state state) const; + void mark(int bsn, const gprs_rlc_ul_bsn_state state); + gprs_rlc_ul_bsn_state m_v_n[RLC_MAX_SNS/2]; /* receive state array */ +}; + + +inline void gprs_rlc_v_n::mark_received(int bsn) +{ + return mark(bsn, GPRS_RLC_UL_BSN_RECEIVED); +} + +inline void gprs_rlc_v_n::mark_missing(int bsn) +{ + return mark(bsn, GPRS_RLC_UL_BSN_MISSING); +} + +inline bool gprs_rlc_v_n::is_received(int bsn) const +{ + return is_state(bsn, GPRS_RLC_UL_BSN_RECEIVED); +} + +inline bool gprs_rlc_v_n::is_state(int bsn, gprs_rlc_ul_bsn_state type) const +{ + return m_v_n[bsn & mod_sns_half()] == type; +} + +inline void gprs_rlc_v_n::mark(int bsn, gprs_rlc_ul_bsn_state type) +{ + m_v_n[bsn & mod_sns_half()] = type; +} + +inline gprs_rlc_ul_bsn_state gprs_rlc_v_n::state(int bsn) const +{ + return m_v_n[bsn & mod_sns_half()]; +} + +struct gprs_rlc_ul_window : public gprs_rlc_window { + const uint16_t v_r(void) const; + const uint16_t v_q(void) const; + + const void set_v_r(int v_r); + const void set_v_q(int v_q); + void reset_state(void); + + const uint16_t ssn(void) const; + + bool is_in_window(uint16_t bsn) const; + bool is_received(uint16_t bsn) const; + + void update_rbb(char *rbb); + uint16_t update_egprs_rbb(uint8_t *rbb); + void raise_v_r_to(int moves); + void raise_v_r(const uint16_t bsn); + uint16_t raise_v_q(void); + + void raise_v_q(int incr); + + void receive_bsn(const uint16_t bsn); + bool invalidate_bsn(const uint16_t bsn); + + uint16_t m_v_r; /* receive state */ + uint16_t m_v_q; /* receive window state */ + + gprs_rlc_v_n m_v_n; + + gprs_rlc_ul_window(void); +}; + + +inline gprs_rlc_ul_window::gprs_rlc_ul_window(void) + : m_v_r(0) + , m_v_q(0) +{ + m_v_n.reset(); +} + +inline bool gprs_rlc_ul_window::is_in_window(uint16_t bsn) const +{ + uint16_t offset_v_q; + + /* current block relative to lowest unreceived block */ + offset_v_q = (bsn - m_v_q) & mod_sns(); + /* If out of window (may happen if blocks below V(Q) are received + * again. */ + return offset_v_q < ws(); +} + +inline bool gprs_rlc_ul_window::is_received(uint16_t bsn) const +{ + uint16_t offset_v_r; + + /* Offset to the end of the received window */ + offset_v_r = (m_v_r - 1 - bsn) & mod_sns(); + return is_in_window(bsn) && m_v_n.is_received(bsn) && offset_v_r < ws(); +} + +inline void gprs_rlc_ul_window::reset_state(void) +{ + m_v_r = 0; + m_v_q = 0; +} + +inline const void gprs_rlc_ul_window::set_v_r(int v_r) +{ + m_v_r = v_r; +} + +inline const void gprs_rlc_ul_window::set_v_q(int v_q) +{ + m_v_q = v_q; +} + +inline const uint16_t gprs_rlc_ul_window::v_r(void) const +{ + return m_v_r; +} + +inline const uint16_t gprs_rlc_ul_window::v_q(void) const +{ + return m_v_q; +} + +inline const uint16_t gprs_rlc_ul_window::ssn(void) const +{ + return m_v_r; +} + +inline void gprs_rlc_ul_window::raise_v_r_to(int moves) +{ + m_v_r = mod_sns(m_v_r + moves); +} + +inline void gprs_rlc_ul_window::raise_v_q(int incr) +{ + m_v_q = mod_sns(m_v_q + incr); +} diff --git a/src/tbf.h b/src/tbf.h index 124a2e6..97f5562 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -20,6 +20,7 @@ #include "llc.h" #include "rlc.h" +#include "rlc_window.h" #include "cxx_linuxlist.h" #include "pcu_utils.h" #include <gprs_debug.h> diff --git a/src/tbf_dl.h b/src/tbf_dl.h index 7223fa0..59a0356 100644 --- a/src/tbf_dl.h +++ b/src/tbf_dl.h @@ -18,6 +18,7 @@ #ifdef __cplusplus #include "tbf.h" +#include "rlc_window_dl.h" #include <stdint.h> diff --git a/src/tbf_ul.h b/src/tbf_ul.h index 14884ab..4ec0f6f 100644 --- a/src/tbf_ul.h +++ b/src/tbf_ul.h @@ -20,6 +20,7 @@ #include <stdbool.h> #include "tbf.h" +#include "rlc_window_ul.h" #ifdef __cplusplus extern "C" { -- To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/33939 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-pcu Gerrit-Branch: master Gerrit-Change-Id: If21b6f48ef190a718502389cbfde8cbdfc8d7f7a Gerrit-Change-Number: 33939 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: newchange
1 0
0 0
[M] Change in osmo-trx[master]: devices: add freq/gain override for uhd
by Hoernchen 26 Jul '23

26 Jul '23
Attention is currently required from: pespin. Hoernchen has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-trx/+/32764 ) Change subject: devices: add freq/gain override for uhd ...................................................................... Patch Set 11: (3 comments) Patchset: PS11: Why would I hide the fixed freqs setting that are initialized once as configured in a function that is dynamically called at some random time depending on incoming messages? The freq override is and should be completely independent of any interaction that might or might not be happening. File Transceiver52M/device/uhd/UHDDevice.cpp: https://gerrit.osmocom.org/c/osmo-trx/+/32764/comment/41d5be83_99f7f02c PS5, Line 635: if (cfg->overrides.dl_freq_override) { > why are you doing it here instead of the place where the freq/gain is supposed to be updated? Done https://gerrit.osmocom.org/c/osmo-trx/+/32764/comment/20068196_163d38e6 PS5, Line 1013: if (cfg->overrides.dl_freq_override || cfg->overrides.ul_freq_override) > I would expected the overwritten frequency to be set here? Done -- To view, visit https://gerrit.osmocom.org/c/osmo-trx/+/32764 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-trx Gerrit-Branch: master Gerrit-Change-Id: I3c1b9a067cafc6d696b9aa2da8ee0480ec1e094f Gerrit-Change-Number: 32764 Gerrit-PatchSet: 11 Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-CC: laforge <laforge(a)osmocom.org> Gerrit-CC: pespin <pespin(a)sysmocom.de> Gerrit-Attention: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Wed, 26 Jul 2023 13:56:42 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: comment
1 0
0 0
[L] Change in osmo-ttcn3-hacks[master]: MME_Tests: add testcase TC_RIM_RAN_INF
by pespin 26 Jul '23

26 Jul '23
Attention is currently required from: dexter. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33937 ) Change subject: MME_Tests: add testcase TC_RIM_RAN_INF ...................................................................... Patch Set 3: (1 comment) File mme/MME_Tests.ttcn: https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33937/comment/2f076544_0675… PS3, Line 822: * does not add this information element. */ > @pespin: Is this a bug? it shall not be added to the S1AP MME Direct Information Transfer, see 3GPP TS 36.413 section 8.14.2: "The RIM Routing Address IE shall not be present since the eNB is the final destination node." -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33937 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-ttcn3-hacks Gerrit-Branch: master Gerrit-Change-Id: I22d5aaab64df2824099977fb574afb86a4b7e91f Gerrit-Change-Number: 33937 Gerrit-PatchSet: 3 Gerrit-Owner: dexter <pmaier(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-CC: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Attention: dexter <pmaier(a)sysmocom.de> Gerrit-Comment-Date: Wed, 26 Jul 2023 13:14:28 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: dexter <pmaier(a)sysmocom.de> Gerrit-MessageType: comment
1 0
0 0
[S] Change in libosmocore[master]: ASCI: Add missing check for return value of gsm0808_enc_speech_codec_...
by laforge 26 Jul '23

26 Jul '23
laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/33828 ) Change subject: ASCI: Add missing check for return value of gsm0808_enc_speech_codec_list2() ...................................................................... ASCI: Add missing check for return value of gsm0808_enc_speech_codec_list2() Fixes: CID#318987 Change-Id: I771b8ee8dfe1588d0af1c4957489f723447a7054 --- M src/gsm/gsm0808.c 1 file changed, 18 insertions(+), 2 deletions(-) Approvals: laforge: Looks good to me, approved fixeria: Looks good to me, but someone else must approve Jenkins Builder: Verified diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index 6ba6ef2..529dbdf 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -1756,13 +1756,19 @@ msgb_tlv_put(msg, GSM0808_IE_CIRCUIT_POOL_LIST, params->cpl.list_len, params->cpl.pool); /* Codec List (BSS Supported) 3.2.2.103 */ - if (params->codec_list_present) - gsm0808_enc_speech_codec_list2(msg, &params->codec_list_bss_supported); + if (params->codec_list_present) { + if (gsm0808_enc_speech_codec_list2(msg, &params->codec_list_bss_supported) < 0) + goto exit_free; + } /* prepend header with final length */ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); return msg; + +exit_free: + msgb_free(msg); + return NULL; } /*! Create BSSMAP VGCS/VBS QUEUING INDICATION message, 3GPP TS 48.008 3.2.1.56. -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/33828 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: I771b8ee8dfe1588d0af1c4957489f723447a7054 Gerrit-Change-Number: 33828 Gerrit-PatchSet: 2 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-MessageType: merged
1 0
0 0
[M] Change in osmo-trx[master]: devices: add freq/gain override for uhd
by laforge 26 Jul '23

26 Jul '23
Attention is currently required from: Hoernchen, pespin. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-trx/+/32764 ) Change subject: devices: add freq/gain override for uhd ...................................................................... Patch Set 11: (1 comment) Patchset: PS11: it would be good to provide some feedback to the questions raised by pespin (see "2 unresolved"). -- To view, visit https://gerrit.osmocom.org/c/osmo-trx/+/32764 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-trx Gerrit-Branch: master Gerrit-Change-Id: I3c1b9a067cafc6d696b9aa2da8ee0480ec1e094f Gerrit-Change-Number: 32764 Gerrit-PatchSet: 11 Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-CC: laforge <laforge(a)osmocom.org> Gerrit-CC: pespin <pespin(a)sysmocom.de> Gerrit-Attention: Hoernchen <ewild(a)sysmocom.de> Gerrit-Attention: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Wed, 26 Jul 2023 12:51:30 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment
1 0
0 0
[XS] Change in osmo-bsc-nat[master]: do not merge: testing CI
by osmith 26 Jul '23

26 Jul '23
osmith has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc-nat/+/33938 ) Change subject: do not merge: testing CI ...................................................................... do not merge: testing CI Change-Id: Ic78700d85b24a7d4b777360902410ebe21449eda --- A test 1 file changed, 9 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-bsc-nat refs/changes/38/33938/1 diff --git a/test b/test new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test -- To view, visit https://gerrit.osmocom.org/c/osmo-bsc-nat/+/33938 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-bsc-nat Gerrit-Branch: master Gerrit-Change-Id: Ic78700d85b24a7d4b777360902410ebe21449eda Gerrit-Change-Number: 33938 Gerrit-PatchSet: 1 Gerrit-Owner: osmith <osmith(a)sysmocom.de> Gerrit-MessageType: newchange
1 0
0 0
[L] Change in osmo-ttcn3-hacks[master]: MME_Tests: add testcase TC_RIM_RAN_INF
by fixeria 26 Jul '23

26 Jul '23
Attention is currently required from: pespin, dexter. fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33937 ) Change subject: MME_Tests: add testcase TC_RIM_RAN_INF ...................................................................... Patch Set 3: (1 comment) File mme/MME_Tests.ttcn: https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33937/comment/ded7a419_bb2f… PS3, Line 108: global_enb_id_len := 8 no semicolon? (same below) -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33937 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-ttcn3-hacks Gerrit-Branch: master Gerrit-Change-Id: I22d5aaab64df2824099977fb574afb86a4b7e91f Gerrit-Change-Number: 33937 Gerrit-PatchSet: 3 Gerrit-Owner: dexter <pmaier(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-CC: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Attention: pespin <pespin(a)sysmocom.de> Gerrit-Attention: dexter <pmaier(a)sysmocom.de> Gerrit-Comment-Date: Wed, 26 Jul 2023 12:49:10 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment
1 0
0 0
[S] Change in osmo-msc[master]: csd_bs_list_to_bearer_cap(): add default branch for safety
by fixeria 26 Jul '23

26 Jul '23
fixeria has submitted this change. ( https://gerrit.osmocom.org/c/osmo-msc/+/33933 ) Change subject: csd_bs_list_to_bearer_cap(): add default branch for safety ...................................................................... csd_bs_list_to_bearer_cap(): add default branch for safety Otherwise we may fail to initialize cap->data.{user,interm}_rate. Change-Id: Ibfb71d1ece502585b55db0f28069a6aa0666b9df Related: OS#6110, OS#4394 --- M src/libmsc/csd_bs.c 1 file changed, 17 insertions(+), 0 deletions(-) Approvals: Jenkins Builder: Verified osmith: Looks good to me, but someone else must approve laforge: Looks good to me, approved diff --git a/src/libmsc/csd_bs.c b/src/libmsc/csd_bs.c index dcc6124..3a2c82a 100644 --- a/src/libmsc/csd_bs.c +++ b/src/libmsc/csd_bs.c @@ -467,6 +467,11 @@ cap->data.user_rate = GSM48_BCAP_UR_9600; cap->data.interm_rate = GSM48_BCAP_IR_16k; break; + default: + LOGP(DMSC, LOGL_ERROR, + "%s(): bs=%d (rate=%u) is not implemented\n", + __func__, bs, bs_map[bs].rate); + continue; } /* FIXME: handle more than one list entry */ -- To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/33933 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-msc Gerrit-Branch: master Gerrit-Change-Id: Ibfb71d1ece502585b55db0f28069a6aa0666b9df Gerrit-Change-Number: 33933 Gerrit-PatchSet: 1 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: osmith <osmith(a)sysmocom.de> Gerrit-CC: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 0
0 0
[M] Change in osmo-bts[master]: pcu_sock: forward downlink IMMEDAITE ASSIGNMENT with no IMSI to AGCH
by laforge 26 Jul '23

26 Jul '23
Attention is currently required from: fixeria, dexter. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-bts/+/33829 ) Change subject: pcu_sock: forward downlink IMMEDAITE ASSIGNMENT with no IMSI to AGCH ...................................................................... Patch Set 5: (1 comment) Patchset: PS5: I have to admit I'm not able to follow the rationale of the PCU interface changes of the last 2-or-so month. Hence I prefer if other people with more knowledge on it perform code review. -- To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/33829 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-bts Gerrit-Branch: master Gerrit-Change-Id: Iaa3e5cdcf86578821e149b3e23482a0bcee19f7b Gerrit-Change-Number: 33829 Gerrit-PatchSet: 5 Gerrit-Owner: dexter <pmaier(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-CC: laforge <laforge(a)osmocom.org> Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Attention: dexter <pmaier(a)sysmocom.de> Gerrit-Comment-Date: Wed, 26 Jul 2023 12:46:21 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment
1 0
0 0
[S] Change in osmo-ttcn3-hacks[master]: BSC_Tests: Fix test case TC_err_84_unknown
by laforge 26 Jul '23

26 Jul '23
laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33925 ) Change subject: BSC_Tests: Fix test case TC_err_84_unknown ...................................................................... BSC_Tests: Fix test case TC_err_84_unknown The test cases used UPLINK RELEASE message as test for an unspported message. This message is supported and does not trigger the expected RR STATUS message. The fix uses the unsupported DTM ASSIGNMENT FAILURE message. To have the DTM ASSIGNMENT FAILE, it is added to library/L3_Templates.ttcn. Change-Id: I35877574cf4459332229e3b941918bc0a23b939f --- M bsc/BSC_Tests.ttcn M library/L3_Templates.ttcn 2 files changed, 35 insertions(+), 2 deletions(-) Approvals: laforge: Looks good to me, approved Jenkins Builder: Verified diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn index a9cfa03..f2f7f5b 100644 --- a/bsc/BSC_Tests.ttcn +++ b/bsc/BSC_Tests.ttcn @@ -5656,10 +5656,9 @@ f_shutdown_helper(); } - /* 24.008 8.4 Unknown message must trigger RR STATUS */ private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr { - f_est_single_l3(ts_RRM_UL_REL('00'O)); + f_est_single_l3(ts_RRM_DTM_ASS_FAIL('00'O)); timer T := 3.0 alt { [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) { diff --git a/library/L3_Templates.ttcn b/library/L3_Templates.ttcn index edec440..345935c 100644 --- a/library/L3_Templates.ttcn +++ b/library/L3_Templates.ttcn @@ -1012,6 +1012,23 @@ } } +template (value) PDU_ML3_MS_NW ts_RRM_DTM_ASS_FAIL(OCT1 cause) := { + discriminator := '0110'B, + tiOrSkip := { + skipIndicator := '0000'B + }, + msgs := { + rrm := { + dTM_AssignmentFailure := { + messageType := '01001000'B, + rR_Cause := { + valuePart := cause + } + } + } + } +} + template PDU_ML3_MS_NW tr_RRM_RR_STATUS(template OCT1 cause := ?) := { discriminator := '0110'B, tiOrSkip := { -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33925 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-ttcn3-hacks Gerrit-Branch: master Gerrit-Change-Id: I35877574cf4459332229e3b941918bc0a23b939f Gerrit-Change-Number: 33925 Gerrit-PatchSet: 3 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-CC: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • ...
  • 306
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.