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
[M] Change in osmo-tetra[master]: Added calls to stub decryption functions for MAC resources
by laforge 27 Jul '23

27 Jul '23
Attention is currently required from: wbokslag. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-tetra/+/33953 ) Change subject: Added calls to stub decryption functions for MAC resources ...................................................................... Patch Set 3: Code-Review+1 (1 comment) File src/tetra_upper_mac.c: https://gerrit.osmocom.org/c/osmo-tetra/+/33953/comment/b09ed4e4_47cac60e PS3, Line 301: m so you want to move the tail but not change the length (as msgb_get does). That's highly unusual, as it leaves the msgb in a somehwat inconsistent state. -- To view, visit https://gerrit.osmocom.org/c/osmo-tetra/+/33953 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-tetra Gerrit-Branch: master Gerrit-Change-Id: I92d718789d6b7e84c1901d09165fce59cdf8c1ca Gerrit-Change-Number: 33953 Gerrit-PatchSet: 3 Gerrit-Owner: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Attention: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-Comment-Date: Thu, 27 Jul 2023 11:33:54 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[L] Change in osmo-tetra[master]: Added first steps towards tetra crypto support
by laforge 27 Jul '23

27 Jul '23
Attention is currently required from: wbokslag. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-tetra/+/33943 ) Change subject: Added first steps towards tetra crypto support ...................................................................... Patch Set 3: (9 comments) Patchset: PS3: I feel a bit sorry for the large number of comments. Don't treat them as strict change requests, more like "these are my thoughts, do with them what you think'. The only ones I think are blockers is the talloc vs. calloc use and the license/copyright header. File src/crypto/tetra_crypto.h: https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/e26312ab_fed450a8 PS3, Line 47: mcc it's been a long time since I read TETRA specs. However, in GSM there is a difference between MNC 02 and 002, and we made the early mistake to represent them as integers, where we cannot differentiate those two distinct values. We then had to invent work-arounds, etc. So if TETRA also has similar differences (you tell me!) in terms of number of digits / leading zeroes, it might be best to avoid int. https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/d9329000_417adb5d PS3, Line 54: int is_gssi_range; : int start; : int end; are there situations where those integers really can be negative? https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/46c19233_b00a3a79 PS3, Line 61: mnc is there a reeason to use int for mnc/mcc in 'struct network_info' but uint32_t here? https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/db06bc10_6ecaf02e PS3, Line 71: int num_keys; I guess all of these could be unsigned as they simply count the number of list elements? Using the more constrained unsigned avoids situations where it's unclear what the meaning of a negative number could mean in this context, and it also helps to avoid static analysis tools to "think" about the question of negative values where none are desired/useful. https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/318f3980_df2ccedc PS3, Line 93: const char *tetra_get_key_type_name(int key_type); didn't you define enums above for those types? Wondering why the argument type is int instead of the enum File src/crypto/tetra_crypto.c: https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/aa304436_7ca02f87 PS3, Line 14: struct tet I'd generally suggest to a void global variables for state that might exist multiple times (think of decrypting multiple different calls/subscribers/... simultaneously). This is why I'm using a context pointer (like 'struct tetra_mac_state *) that gets passed around to functions. So future software can have multiple of those around, rather than assuming there is only a singleton. https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/989c662a_b8a769cc PS3, Line 82: calloc we generally use talloc in the existing osmo-tetra code base, and it would make sense to not mix different memory allocators. This way it's clear one always uses one type of free() function, and not another. https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/f991f1b1_bf3f500d PS3, Line 96: k->mcc, k->mnc, k->key_type); we have something like OSMO_STRBUF_APPEND() in osmocom/core/utils.h to avoid the manual size-counting + pointer arithmetic in the snprintf calls here. Not critical, up to you. -- To view, visit https://gerrit.osmocom.org/c/osmo-tetra/+/33943 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-tetra Gerrit-Branch: master Gerrit-Change-Id: I63bc712630ae5dbaa049c129d456f7aef5bda863 Gerrit-Change-Number: 33943 Gerrit-PatchSet: 3 Gerrit-Owner: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-Reviewer: Jenkins Builder Gerrit-CC: laforge <laforge(a)osmocom.org> Gerrit-Attention: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-Comment-Date: Thu, 27 Jul 2023 11:31:45 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment
1 0
0 0
[L] Change in osmo-tetra[master]: Added first steps towards tetra crypto support
by laforge 27 Jul '23

27 Jul '23
Attention is currently required from: wbokslag. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-tetra/+/33943 ) Change subject: Added first steps towards tetra crypto support ...................................................................... Patch Set 3: (1 comment) Patchset: PS3: I know not all of the existing files adhere to that rule, but particularly as large portions of code are contributed by new authors, I think a comment section with copyright / author information and the license text and/or a SPDX line would be useful to have in all newly introduced files. -- To view, visit https://gerrit.osmocom.org/c/osmo-tetra/+/33943 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-tetra Gerrit-Branch: master Gerrit-Change-Id: I63bc712630ae5dbaa049c129d456f7aef5bda863 Gerrit-Change-Number: 33943 Gerrit-PatchSet: 3 Gerrit-Owner: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-Reviewer: Jenkins Builder Gerrit-CC: laforge <laforge(a)osmocom.org> Gerrit-Attention: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-Comment-Date: Thu, 27 Jul 2023 11:19:42 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment
1 0
0 0
[M] Change in osmo-pcu[master]: gprs_rlc_ul_window: Mark received BSNs falling out of the V(N)/RBB wh...
by pespin 27 Jul '23

27 Jul '23
pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-pcu/+/33924 ) Change subject: gprs_rlc_ul_window: Mark received BSNs falling out of the V(N)/RBB when V(R) is raised ...................................................................... gprs_rlc_ul_window: Mark received BSNs falling out of the V(N)/RBB when V(R) is raised This is a port of libosmo-gprs.git commit 49535bec37caddcea5718ed4e526c477c71f1b3a applied to osmo-pcu. Problem this patch is fixing: The current RLCMAC code is never invalidating the BSNs which have been received after they are not needed. This is somehow workaround by the following check when eg BSN wraps around 127->0 and the BSN=0 is received: """" rcv_data_block_acknowledged() m_window.m_v_n.is_received(rdbi->bsn) /* Offset to the end of the received window */ offset_v_r = (m_v_r - 1 - bsn) & mod_sns(); return m_v_n.is_received(bsn) && offset_v_r < ws(); """ The first m_v_n_is_received() would return true because the BSN has never been invalidated, which is wrong, but fortunately the extra check "offset_v_r < ws()" returns > ws() since: v_r=0, bsn=0: "(0 - 1 - 0) & 127" ----> 0xffff & 0x007f ---> 0x007f > 64 So thanks to the above the BSN is considered not received, but looking at the V(N) array would say the opposite. Hence, this commit aims at fixing the V(N) array to contain proper values (marked "invalid") for BSNs becoming out of the window when it rolls forward. Explanation of the solution: The V(N) array contains the status of the previous WS (64 in GPRS) data blocks. This array is used to construct the RRB signaled to the peer during PKT UL ACK/NACK messages together with the SSN (start sequence number), which in our case is mainly V(R), aka one block higher than the highest received block in the rx window. Hence, whenever PKT UL ACK/NACK is transmitted, it contains an RRB ranging [V(R)-1,...V(R)-WS)] mod SNS (SNS=128 in GPRS). The receive window is basically [V(Q) <= BSN < V(R)] mod SNS, as is of size 64. The V(R) is increased whenever a highest new block arrives which is in the receive window (guaranteeing it will be increased to at most V(Q)+64. Since we are only announcing state of blocks from V(R)..V(R)-WS, and blocks received which are before that BSN are dropped since don't fall inside the rx window, we can securely mark as invalid those blocks falling behind V(R)-WS whenever we increase V(R). Related: OS#6102 Change-Id: I5ef4dcb0c5eac07a892114897f9e4f565b1dcc2c --- M src/rlc_window_ul.cpp M src/rlc_window_ul.h M src/tbf_ul.cpp 3 files changed, 69 insertions(+), 3 deletions(-) Approvals: Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve osmith: Looks good to me, but someone else must approve pespin: Looks good to me, approved diff --git a/src/rlc_window_ul.cpp b/src/rlc_window_ul.cpp index 568e126..32810d1 100644 --- a/src/rlc_window_ul.cpp +++ b/src/rlc_window_ul.cpp @@ -37,8 +37,14 @@ /* 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()); + const uint16_t _v_r = v_r(); + const uint16_t bsn_no_longer_in_ws = mod_sns(_v_r - ws()); + LOGP(DRLCMACUL, LOGL_DEBUG, "- Mark BSN %u as INVALID\n", bsn_no_longer_in_ws); + m_v_n.mark_invalid(bsn_no_longer_in_ws); + if (offset_v_r) {/* all except the received block */ + LOGP(DRLCMACUL, LOGL_DEBUG, "- Mark BSN %u as MISSING\n", _v_r); + m_v_n.mark_missing(_v_r); + } raise_v_r_to(1); } LOGP(DRLCMACUL, LOGL_DEBUG, "- Raising V(R) to %d\n", v_r()); diff --git a/src/rlc_window_ul.h b/src/rlc_window_ul.h index a2e60c0..8a48af9 100644 --- a/src/rlc_window_ul.h +++ b/src/rlc_window_ul.h @@ -32,6 +32,7 @@ void mark_received(int bsn); void mark_missing(int bsn); + void mark_invalid(int bsn); bool is_received(int bsn) const; @@ -53,6 +54,11 @@ return mark(bsn, GPRS_RLC_UL_BSN_MISSING); } +inline void gprs_rlc_v_n::mark_invalid(int bsn) +{ + return mark(bsn, GPRS_RLC_UL_BSN_INVALID); +} + inline bool gprs_rlc_v_n::is_received(int bsn) const { return is_state(bsn, GPRS_RLC_UL_BSN_RECEIVED); diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp index 5ae0d49..3746130 100644 --- a/src/tbf_ul.cpp +++ b/src/tbf_ul.cpp @@ -303,7 +303,7 @@ rdbi->bsn, m_window.v_q(), m_window.mod_sns(m_window.v_q() + ws - 1)); continue; - } else if (m_window.is_received(rdbi->bsn)) { + } else if (m_window.m_v_n.is_received(rdbi->bsn)) { LOGPTBFUL(this, LOGL_DEBUG, "BSN %d already received\n", rdbi->bsn); continue; -- To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/33924 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-pcu Gerrit-Branch: master Gerrit-Change-Id: I5ef4dcb0c5eac07a892114897f9e4f565b1dcc2c Gerrit-Change-Number: 33924 Gerrit-PatchSet: 2 Gerrit-Owner: pespin <pespin(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-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 0
0 0
[XL] Change in osmo-pcu[master]: Split rlc_{dl_,ul_,}window out of rlc.{h,cpp}
by pespin 27 Jul '23

27 Jul '23
pespin has submitted this change. ( 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/decoding.h 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 14 files changed, 820 insertions(+), 660 deletions(-) Approvals: Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve osmith: Looks good to me, but someone else must approve pespin: Looks good to me, approved 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/decoding.h b/src/decoding.h index b0a5aed..c89b5b1 100644 --- a/src/decoding.h +++ b/src/decoding.h @@ -32,6 +32,8 @@ #ifdef __cplusplus +#include "rlc_window_dl.h" + class Decoding { public: /* represents (parts) LLC PDUs within one RLC Data block */ diff --git a/src/rlc.cpp b/src/rlc.cpp index a082597..2166e4d 100644 --- a/src/rlc.cpp +++ b/src/rlc.cpp @@ -41,275 +41,6 @@ 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 d4a7a5e..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,241 +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() -{ - reset_state(); -} - -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; - m_v_n.reset(); -} - -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..c056170 --- /dev/null +++ b/src/rlc_window.cpp @@ -0,0 +1,42 @@ +/* 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 "gprs_debug.h" +#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..1b0227f --- /dev/null +++ b/src/rlc_window.h @@ -0,0 +1,71 @@ +/* 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> + +#include "rlc.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..41f9887 --- /dev/null +++ b/src/rlc_window_dl.cpp @@ -0,0 +1,182 @@ +/* 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 "gprs_debug.h" +#include "bts.h" +#include "rlc_window_dl.h" + +extern "C" { +#include <osmocom/core/utils.h> +#include <osmocom/core/bitvec.h> +#include <osmocom/core/logging.h> +} + +static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn) +{ + return (ssn - 1 - bitnum); +} + +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..568e126 --- /dev/null +++ b/src/rlc_window_ul.cpp @@ -0,0 +1,119 @@ +/* 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 "gprs_debug.h" +#include "rlc_window_ul.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..a2e60c0 --- /dev/null +++ b/src/rlc_window_ul.h @@ -0,0 +1,174 @@ +/* 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) +{ + reset_state(); +} + +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; + m_v_n.reset(); +} + +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: 2 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: osmith <osmith(a)sysmocom.de> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 0
0 0
[M] Change in osmo-pcu[master]: gprs_rlc_ul_window: Mark received BSNs falling out of the V(N)/RBB wh...
by pespin 27 Jul '23

27 Jul '23
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-pcu/+/33924 ) Change subject: gprs_rlc_ul_window: Mark received BSNs falling out of the V(N)/RBB when V(R) is raised ...................................................................... Patch Set 2: Code-Review+2 -- To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/33924 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-pcu Gerrit-Branch: master Gerrit-Change-Id: I5ef4dcb0c5eac07a892114897f9e4f565b1dcc2c Gerrit-Change-Number: 33924 Gerrit-PatchSet: 2 Gerrit-Owner: pespin <pespin(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-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Thu, 27 Jul 2023 11:17:52 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[XL] Change in osmo-pcu[master]: Split rlc_{dl_,ul_,}window out of rlc.{h,cpp}
by pespin 27 Jul '23

27 Jul '23
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-pcu/+/33939 ) Change subject: Split rlc_{dl_,ul_,}window out of rlc.{h,cpp} ...................................................................... Patch Set 2: Code-Review+2 -- 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: 2 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: osmith <osmith(a)sysmocom.de> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Thu, 27 Jul 2023 11:17:46 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[M] Change in osmo-ttcn3-hacks[master]: pcu: Introduce test TC_ul_tbf_bsn_wraparound_gprs
by pespin 27 Jul '23

27 Jul '23
pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33923 ) Change subject: pcu: Introduce test TC_ul_tbf_bsn_wraparound_gprs ...................................................................... pcu: Introduce test TC_ul_tbf_bsn_wraparound_gprs Related: OS#6102 Change-Id: I253e3607b75dd1a850c53f284fadf753dd49c247 --- M pcu/PCU_Tests.ttcn M pcu/expected-results.xml 2 files changed, 165 insertions(+), 0 deletions(-) Approvals: laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved osmith: Looks good to me, but someone else must approve Jenkins Builder: Verified diff --git a/pcu/PCU_Tests.ttcn b/pcu/PCU_Tests.ttcn index 2598e7b..c360e97 100644 --- a/pcu/PCU_Tests.ttcn +++ b/pcu/PCU_Tests.ttcn @@ -3596,6 +3596,159 @@ f_TC_ul_tbf_reestablish_with_pkt_dl_ack_nack(true); } +/* Test UL data blocks BSN 0..127 and then continue again at BSN 0... up to 300 + * BSNs in total to test several wrap arounds. */ +testcase TC_ul_tbf_bsn_wraparound_gprs() runs on RAW_PCU_Test_CT +{ + var PCUIF_info_ind info_ind; + var RlcmacDlBlock dl_block; + var octetstring payload; + var template (value) RlcmacUlBlock ul_data; + var template (value) LlcBlockHdr blk_hdr; + var template (value) LlcBlocks blocks; + var uint32_t sched_fn; + var uint32_t dl_fn; + var template (value) TsTrxBtsNum nr; + var BTS_PDTCH_Block data_msg; + var template RlcmacDlBlock acknack_tmpl; + var GprsMS ms; + var integer blocks_sent := 0; + var integer blocks_received := 0; + const integer target_bsn_set := 300; + + /* Initialize NS/BSSGP side */ + f_init_bssgp(); + /* Initialize GPRS MS side */ + f_init_gprs_ms(); + ms := g_ms[0]; /* We only use first MS in this test */ + + /* Initialize the PCU interface abstraction */ + info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS)); + f_init_raw(testcasename(), info_ind); + + /* Establish BSSGP connection to the PCU */ + f_bssgp_establish(); + f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli); + + /* Establish an Uplink TBF */ + f_ms_establish_ul_tbf(ms); + + /* Wait until PCU starts requesting for UL block on this TBF: */ + dl_fn := f_ms_wait_usf(ms); + sched_fn := f_next_pdch_block(dl_fn); + + /* Send one UL block (with TLLI since we are in One-Phase Access + contention resolution) and make sure it is ACKED fine. */ + payload := f_rnd_octstring(16); /* 16 bytes fills the llc block (because TLLI takes 4 bytes) */ + blk_hdr := t_RLCMAC_LLCBLOCK_HDR(length_ind := lengthof(payload), + more := false, e := true); + blocks := { t_RLCMAC_LLCBLOCK(payload, blk_hdr) }; + /* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */ + ul_data := t_RLCMAC_UL_DATA_TLLI(cs := ms.ul_tbf.tx_cs_mcs, + tfi := ms.ul_tbf.tfi, + cv := 15, + bsn := ms.ul_tbf.bsn, + blocks := blocks, + tlli := ms.tlli); + f_ultbf_inc_bsn(ms.ul_tbf); + f_ms_tx_ul_block(ms, ul_data, f_next_pdch_block(sched_fn)); + blocks_sent := blocks_sent + 1; + + /* UL block should be received in SGSN */ + BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id)); + + acknack_tmpl := tr_RLCMAC_UL_ACK_NACK_GPRS(ms.ul_tbf.tfi, + tr_UlAckNackGprs(ms.tlli, + tr_AckNackDescription(final_ack := '0'B))) + f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn, acknack_tmpl); + + ul_data := t_RLCMAC_UL_DATA(cs := ms.ul_tbf.tx_cs_mcs, + tfi := ms.ul_tbf.tfi, + cv := 15, + bsn := ms.ul_tbf.bsn, + blocks := blocks); + + nr := f_ms_tx_TsTrxBtsNum(ms); + BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr, + sapi := PCU_IF_SAPI_PDTCH, fn := 0, + arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)), + block_nr := nr.blk_nr)); + alt { + [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr, + tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH), + tr_RLCMAC_UL_ACK_NACK_GPRS)) -> value data_msg { + + if (f_dl_block_rrbp_valid(data_msg.dl_block)) { + var uint32_t ack_fn := f_dl_block_ack_fn(data_msg.dl_block, data_msg.raw.fn) + log("ACKING FN ", data_msg.raw.fn, " on FN ", ack_fn); + f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), ack_fn); + } + ul_data.data.mac_hdr.bsn := ms.ul_tbf.bsn; + f_ms_tx_ul_block(ms, ul_data, 0); + f_ultbf_inc_bsn(ms.ul_tbf); + blocks_sent := blocks_sent + 1; + + if (blocks_sent == target_bsn_set) { + break; + } + + nr := f_ms_tx_TsTrxBtsNum(ms); + BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr, + sapi := PCU_IF_SAPI_PDTCH, fn := 0, + arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)), + block_nr := nr.blk_nr)); + repeat; + } + [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr, + tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH), + tr_RLCMAC_DL_DUMMY_CTRL)) -> value data_msg { + + ul_data.data.mac_hdr.bsn := ms.ul_tbf.bsn; + f_ms_tx_ul_block(ms, ul_data, 0); + f_ultbf_inc_bsn(ms.ul_tbf); + blocks_sent := blocks_sent + 1; + + if (blocks_sent == target_bsn_set) { + break; + } + + nr := f_ms_tx_TsTrxBtsNum(ms); + BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr, + sapi := PCU_IF_SAPI_PDTCH, fn := 0, + arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)), + block_nr := nr.blk_nr)); + repeat; + } + [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr, + tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH), + omit)) -> value data_msg { + nr := f_ms_tx_TsTrxBtsNum(ms); + BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr, + sapi := PCU_IF_SAPI_PDTCH, fn := 0, + arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)), + block_nr := nr.blk_nr)); + repeat; + } + [] BTS.receive { + setverdict(fail, "Unexpected BTS message"); + f_shutdown(__BFILE__, __LINE__); + } + [] BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id)) { + blocks_received := blocks_received + 1; + repeat; + } + } + + /* Validate most part of them were accepted and forwarded: */ + if (blocks_received < target_bsn_set * 95 / 100) { + setverdict(fail, "Forwarded ", blocks_received, " out of ", target_bsn_set, " transmitted"); + f_shutdown(__BFILE__, __LINE__); + } + log("Forwarded ", blocks_received, " out of ", target_bsn_set, " transmitted"); + + f_shutdown(__BFILE__, __LINE__, final := true); +} + /* Test CS paging over the BTS<->PCU socket. * When a (class B or C, not A) MS has an active TBF (or is on the PDCH), the MS can not react on CS paging over CCCH. * Paging should be send on the PACCH. @@ -7258,6 +7411,7 @@ execute( TC_ul_flow_multiple_llc_blocks() ); execute( TC_dl_no_ack_retrans_imm_ass() ); execute( TC_dl_llc_sapi_priority() ); + execute( TC_ul_tbf_bsn_wraparound_gprs()); execute( TC_paging_cs_from_bts() ); execute( TC_paging_cs_from_sgsn_sign_ptmsi() ); execute( TC_paging_cs_from_sgsn_sign() ); diff --git a/pcu/expected-results.xml b/pcu/expected-results.xml index cdc4aec..eccff6f 100644 --- a/pcu/expected-results.xml +++ b/pcu/expected-results.xml @@ -55,6 +55,7 @@ <testcase classname='PCU_Tests' name='TC_ul_flow_multiple_llc_blocks' time='MASKED'/> <testcase classname='PCU_Tests' name='TC_dl_no_ack_retrans_imm_ass' time='MASKED'/> <testcase classname='PCU_Tests' name='TC_dl_llc_sapi_priority' time='MASKED'/> + <testcase classname='PCU_Tests' name='TC_ul_tbf_bsn_wraparound_gprs' time='MASKED'/> <testcase classname='PCU_Tests' name='TC_paging_cs_from_bts' time='MASKED'/> <testcase classname='PCU_Tests' name='TC_paging_cs_from_sgsn_sign_ptmsi' time='MASKED'/> <testcase classname='PCU_Tests' name='TC_paging_cs_from_sgsn_sign' time='MASKED'/> -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33923 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: I253e3607b75dd1a850c53f284fadf753dd49c247 Gerrit-Change-Number: 33923 Gerrit-PatchSet: 3 Gerrit-Owner: pespin <pespin(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-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 0
0 0
[M] Change in osmo-ttcn3-hacks[master]: pcu: Introduce test TC_ul_tbf_bsn_wraparound_gprs
by pespin 27 Jul '23

27 Jul '23
Attention is currently required from: fixeria. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33923 ) Change subject: pcu: Introduce test TC_ul_tbf_bsn_wraparound_gprs ...................................................................... Patch Set 2: Code-Review+2 -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/33923 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: I253e3607b75dd1a850c53f284fadf753dd49c247 Gerrit-Change-Number: 33923 Gerrit-PatchSet: 2 Gerrit-Owner: pespin <pespin(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-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Comment-Date: Thu, 27 Jul 2023 11:17:34 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[L] Change in osmo-trx[master]: ms/va: add test tool and data
by pespin 27 Jul '23

27 Jul '23
Attention is currently required from: Hoernchen, laforge. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-trx/+/33945 ) Change subject: ms/va: add test tool and data ...................................................................... Patch Set 8: (1 comment) Commit Message: https://gerrit.osmocom.org/c/osmo-trx/+/33945/comment/3b3a75b9_21b6e57c PS8, Line 10: demodulate bursts and prints the bits (differen), only useful for differen? what do you mean? -- To view, visit https://gerrit.osmocom.org/c/osmo-trx/+/33945 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-trx Gerrit-Branch: master Gerrit-Change-Id: Ie38ed4996134e84ad0481872a743299bb442b3db Gerrit-Change-Number: 33945 Gerrit-PatchSet: 8 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: laforge <laforge(a)osmocom.org> Gerrit-Comment-Date: Thu, 27 Jul 2023 11:13:10 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • ...
  • 306
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.