blob: bafe6a8846cfed5de981eb78e1c044ba9aae15b6 [file] [log] [blame]
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +02001/* rlc header descriptions
2 *
3 * Copyright (C) 2012 Ivan Klyuchnikov
4 * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20#pragma once
21
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010022#include "gprs_coding_scheme.h"
23
Jacob Erlbeck4aa78a82015-12-14 11:13:30 +010024#include <osmocom/core/endian.h>
25
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +020026#include <stdint.h>
27
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010028#define RLC_MAX_SNS 128 /* GPRS, must be power of 2 */
29#define RLC_MAX_WS 64 /* max window size */
30#define RLC_MAX_LEN 54 /* CS-4 including spare bits */
31
Holger Hans Peter Freyther35cc1c02014-07-02 14:48:44 +020032struct BTS;
Holger Hans Peter Freythercbb00eb2013-11-25 23:26:06 +010033struct gprs_rlc_v_n;
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010034
Daniel Willmannd54d9f52013-12-28 21:16:13 +010035/* The state of a BSN in the send/receive window */
36enum gprs_rlc_ul_bsn_state {
37 GPRS_RLC_UL_BSN_INVALID,
38 GPRS_RLC_UL_BSN_RECEIVED,
39 GPRS_RLC_UL_BSN_MISSING,
40 GPRS_RLC_UL_BSN_MAX,
41};
42
43enum gprs_rlc_dl_bsn_state {
44 GPRS_RLC_DL_BSN_INVALID,
45 GPRS_RLC_DL_BSN_NACKED,
46 GPRS_RLC_DL_BSN_ACKED,
47 GPRS_RLC_DL_BSN_UNACKED,
48 GPRS_RLC_DL_BSN_RESEND,
49 GPRS_RLC_DL_BSN_MAX,
50};
51
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +010052
53static inline uint16_t mod_sns_half()
54{
55 return (RLC_MAX_SNS / 2) - 1;
56}
57
Jacob Erlbeck4abc6862015-12-08 15:14:05 +010058struct gprs_rlc_ul_data_block_info {
59 unsigned int data_len; /* EGPRS: N2, GPRS: N2-2, N-2 */
60 unsigned int bsn;
61 unsigned int ti;
62 unsigned int e;
63 unsigned int cv;
64 unsigned int pi;
65 unsigned int spb;
66};
67
68struct gprs_rlc_ul_header_egprs {
69 GprsCodingScheme cs;
70 unsigned int r;
71 unsigned int si;
72 unsigned int tfi;
73 unsigned int cps;
74 unsigned int rsb;
75 unsigned int num_data_blocks;
76 unsigned int data_offs_bits[2];
77 struct gprs_rlc_ul_data_block_info block_info[2];
78};
79
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010080struct gprs_rlc_data {
81 uint8_t *prepare(size_t block_data_length);
Holger Hans Peter Freyther423dd222013-11-25 23:24:29 +010082 void put_data(const uint8_t *data, size_t len);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010083
84 /* block history */
85 uint8_t block[RLC_MAX_LEN];
86 /* block len of history */
87 uint8_t len;
Jacob Erlbeck1751c622015-06-04 12:12:32 +020088
89 uint8_t cs;
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010090};
91
92/*
93 * I hold the currently transferred blocks and will provide
94 * the routines to manipulate these arrays.
95 */
96struct gprs_rlc {
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +010097 gprs_rlc_data *block(int bsn);
98 gprs_rlc_data m_blocks[RLC_MAX_SNS/2];
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010099};
100
Daniel Willmann146514e2013-12-28 18:24:42 +0100101/**
102 * TODO: for GPRS/EDGE maybe make sns a template parameter
103 * so we create specialized versions...
104 */
105struct gprs_rlc_v_b {
106 /* Check for an individual frame */
107 bool is_unacked(int bsn) const;
108 bool is_nacked(int bsn) const;
109 bool is_acked(int bsn) const;
110 bool is_resend(int bsn) const;
111 bool is_invalid(int bsn) const;
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100112 gprs_rlc_dl_bsn_state get_state(int bsn) const;
Daniel Willmann146514e2013-12-28 18:24:42 +0100113
114 /* Mark a RLC frame for something */
115 void mark_unacked(int bsn);
116 void mark_nacked(int bsn);
117 void mark_acked(int bsn);
118 void mark_resend(int bsn);
119 void mark_invalid(int bsn);
120
121 void reset();
122
123
124private:
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100125 bool is_state(int bsn, const gprs_rlc_dl_bsn_state state) const;
126 void mark(int bsn, const gprs_rlc_dl_bsn_state state);
Daniel Willmann146514e2013-12-28 18:24:42 +0100127
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100128 gprs_rlc_dl_bsn_state m_v_b[RLC_MAX_SNS/2]; /* acknowledge state array */
Daniel Willmann146514e2013-12-28 18:24:42 +0100129};
130
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100131
132/**
133 * TODO: The UL/DL code could/should share a baseclass but
134 * we are using llist_for_each_entry for the TBF which
135 * requires everything which creates a requirement for a POD
136 * type and in < C++11 something that is using even if the
137 * most simple form of inheritance is not a POD anymore.
138 */
139struct gprs_rlc_dl_window {
Daniel Willmann7e994e32014-08-07 15:49:21 +0200140 void reset();
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100141 const uint16_t mod_sns() const;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100142 const uint16_t sns() const;
143 const uint16_t ws() const;
144
145 bool window_stalled() const;
146 bool window_empty() const;
147
148 void increment_send();
149 void raise(int moves);
150
151 const uint16_t v_s() const;
152 const uint16_t v_s_mod(int offset) const;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100153 const uint16_t v_a() const;
154 const int16_t distance() const;
155
Daniel Willmann146514e2013-12-28 18:24:42 +0100156 /* Methods to manage reception */
157 int resend_needed();
158 int mark_for_resend();
159 void update(BTS *bts, char *show_rbb, uint8_t ssn,
160 uint16_t *lost, uint16_t *received);
161 int move_window();
Daniel Willmann3ce011f2014-01-15 12:45:56 +0100162 void show_state(char *show_rbb);
Daniel Willmann146514e2013-12-28 18:24:42 +0100163 int count_unacked();
164
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100165 uint16_t m_v_s; /* send state */
166 uint16_t m_v_a; /* ack state */
Daniel Willmann146514e2013-12-28 18:24:42 +0100167
168 gprs_rlc_v_b m_v_b;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100169};
170
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100171struct gprs_rlc_v_n {
172 void reset();
173
174 void mark_received(int bsn);
175 void mark_missing(int bsn);
176
177 bool is_received(int bsn) const;
178
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100179 gprs_rlc_ul_bsn_state state(int bsn) const;
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100180private:
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100181 bool is_state(int bsn, const gprs_rlc_ul_bsn_state state) const;
182 void mark(int bsn, const gprs_rlc_ul_bsn_state state);
183 gprs_rlc_ul_bsn_state m_v_n[RLC_MAX_SNS/2]; /* receive state array */
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100184};
185
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100186struct gprs_rlc_ul_window {
187 const uint16_t mod_sns() const;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100188 const uint16_t sns() const;
189 const uint16_t ws() const;
190
191 const uint16_t v_r() const;
192 const uint16_t v_q() const;
193
Daniel Willmann8a31f9e2013-11-27 17:08:35 +0100194 const uint16_t ssn() const;
195
Holger Hans Peter Freyther6ab5b242013-11-24 22:43:03 +0100196 bool is_in_window(uint8_t bsn) const;
197
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100198 void update_rbb(char *rbb);
Daniel Willmannf4a1ec62013-12-28 13:57:31 +0100199 void raise_v_r_to(int moves);
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100200 void raise_v_r(const uint16_t bsn);
201 uint16_t raise_v_q();
Holger Hans Peter Freythercbb00eb2013-11-25 23:26:06 +0100202
Holger Hans Peter Freyther7f3e6622013-11-25 23:51:19 +0100203 void raise_v_q(int);
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100204
Daniel Willmann55844792013-12-28 14:41:00 +0100205 uint16_t receive_bsn(const uint16_t bsn);
206
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100207 uint16_t m_v_r; /* receive state */
208 uint16_t m_v_q; /* receive window state */
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100209
210 gprs_rlc_v_n m_v_n;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100211};
212
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200213extern "C" {
214/* TS 04.60 10.2.2 */
Jacob Erlbeck4aa78a82015-12-14 11:13:30 +0100215#if OSMO_IS_LITTLE_ENDIAN
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200216struct rlc_ul_header {
217 uint8_t r:1,
218 si:1,
219 cv:4,
220 pt:2;
221 uint8_t ti:1,
222 tfi:5,
223 pi:1,
224 spare:1;
225 uint8_t e:1,
226 bsn:7;
227} __attribute__ ((packed));
228
229struct rlc_dl_header {
230 uint8_t usf:3,
231 s_p:1,
232 rrbp:2,
233 pt:2;
234 uint8_t fbi:1,
235 tfi:5,
236 pr:2;
237 uint8_t e:1,
238 bsn:7;
239} __attribute__ ((packed));
240
241struct rlc_li_field {
242 uint8_t e:1,
243 m:1,
244 li:6;
245} __attribute__ ((packed));
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100246
247struct rlc_li_field_egprs {
248 uint8_t e:1,
249 li:7;
250} __attribute__ ((packed));
251
252struct gprs_rlc_ul_header_egprs_3 {
253 uint8_t r:1,
254 si:1,
255 cv:4,
256 tfi_a:2;
257 uint8_t tfi_b:3,
258 bsn1_a:5;
259 uint8_t bsn1_b:6,
260 cps_a:2;
261 uint8_t cps_b:2,
262 spb:2,
263 rsb:1,
264 pi:1,
265 spare:1,
266 dummy:1;
267} __attribute__ ((packed));
Jacob Erlbeck4aa78a82015-12-14 11:13:30 +0100268#else
269# error "Only little endian headers are supported yet. TODO: add missing structs"
270#endif
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200271}
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100272
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100273inline bool gprs_rlc_v_b::is_state(int bsn, const gprs_rlc_dl_bsn_state type) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100274{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100275 return m_v_b[bsn & mod_sns_half()] == type;
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100276}
277
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100278inline void gprs_rlc_v_b::mark(int bsn, const gprs_rlc_dl_bsn_state type)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100279{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100280 m_v_b[bsn & mod_sns_half()] = type;
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100281}
282
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100283inline bool gprs_rlc_v_b::is_nacked(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100284{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100285 return is_state(bsn, GPRS_RLC_DL_BSN_NACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100286}
287
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100288inline bool gprs_rlc_v_b::is_acked(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100289{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100290 return is_state(bsn, GPRS_RLC_DL_BSN_ACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100291}
292
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100293inline bool gprs_rlc_v_b::is_unacked(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100294{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100295 return is_state(bsn, GPRS_RLC_DL_BSN_UNACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100296}
297
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100298inline bool gprs_rlc_v_b::is_resend(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100299{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100300 return is_state(bsn, GPRS_RLC_DL_BSN_RESEND);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100301}
302
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100303inline bool gprs_rlc_v_b::is_invalid(int bsn) const
Holger Hans Peter Freyther95255672013-11-23 16:18:18 +0100304{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100305 return is_state(bsn, GPRS_RLC_DL_BSN_INVALID);
Holger Hans Peter Freyther95255672013-11-23 16:18:18 +0100306}
307
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100308inline gprs_rlc_dl_bsn_state gprs_rlc_v_b::get_state(int bsn) const
Daniel Willmann146514e2013-12-28 18:24:42 +0100309{
310 return m_v_b[bsn & mod_sns_half()];
311}
312
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100313inline void gprs_rlc_v_b::mark_resend(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100314{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100315 return mark(bsn, GPRS_RLC_DL_BSN_RESEND);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100316}
317
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100318inline void gprs_rlc_v_b::mark_unacked(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100319{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100320 return mark(bsn, GPRS_RLC_DL_BSN_UNACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100321}
322
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100323inline void gprs_rlc_v_b::mark_acked(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100324{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100325 return mark(bsn, GPRS_RLC_DL_BSN_ACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100326}
327
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100328inline void gprs_rlc_v_b::mark_nacked(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100329{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100330 return mark(bsn, GPRS_RLC_DL_BSN_NACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100331}
332
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100333inline void gprs_rlc_v_b::mark_invalid(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100334{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100335 return mark(bsn, GPRS_RLC_DL_BSN_INVALID);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100336}
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100337
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100338inline const uint16_t gprs_rlc_dl_window::sns() const
339{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100340 return RLC_MAX_SNS;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100341}
342
343inline const uint16_t gprs_rlc_dl_window::ws() const
344{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100345 return RLC_MAX_WS;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100346}
347
348inline const uint16_t gprs_rlc_dl_window::mod_sns() const
349{
350 return sns() - 1;
351}
352
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100353inline const uint16_t gprs_rlc_dl_window::v_s() const
354{
355 return m_v_s;
356}
357
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100358inline const uint16_t gprs_rlc_dl_window::v_s_mod(int offset) const
359{
360 return (m_v_s + offset) & mod_sns();
361}
362
363inline const uint16_t gprs_rlc_dl_window::v_a() const
364{
365 return m_v_a;
366}
367
368inline bool gprs_rlc_dl_window::window_stalled() const
369{
370 return ((m_v_s - m_v_a) & mod_sns()) == ws();
371}
372
373inline bool gprs_rlc_dl_window::window_empty() const
374{
375 return m_v_s == m_v_a;
376}
377
378inline void gprs_rlc_dl_window::increment_send()
379{
380 m_v_s = (m_v_s + 1) & mod_sns();
381}
382
383inline void gprs_rlc_dl_window::raise(int moves)
384{
385 m_v_a = (m_v_a + moves) & mod_sns();
386}
387
388inline const int16_t gprs_rlc_dl_window::distance() const
389{
390 return (m_v_s - m_v_a) & mod_sns();
391}
392
Holger Hans Peter Freyther6ab5b242013-11-24 22:43:03 +0100393inline bool gprs_rlc_ul_window::is_in_window(uint8_t bsn) const
394{
395 uint16_t offset_v_q;
396
397 /* current block relative to lowest unreceived block */
398 offset_v_q = (bsn - m_v_q) & mod_sns();
399 /* If out of window (may happen if blocks below V(Q) are received
400 * again. */
401 return offset_v_q < ws();
402}
403
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100404inline const uint16_t gprs_rlc_ul_window::sns() const
405{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100406 return RLC_MAX_SNS;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100407}
408
409inline const uint16_t gprs_rlc_ul_window::ws() const
410{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100411 return RLC_MAX_WS;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100412}
413
414inline const uint16_t gprs_rlc_ul_window::mod_sns() const
415{
416 return sns() - 1;
417}
418
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100419inline const uint16_t gprs_rlc_ul_window::v_r() const
420{
421 return m_v_r;
422}
423
424inline const uint16_t gprs_rlc_ul_window::v_q() const
425{
426 return m_v_q;
427}
428
Daniel Willmann8a31f9e2013-11-27 17:08:35 +0100429inline const uint16_t gprs_rlc_ul_window::ssn() const
430{
431 return m_v_r;
432}
433
Daniel Willmannf4a1ec62013-12-28 13:57:31 +0100434inline void gprs_rlc_ul_window::raise_v_r_to(int moves)
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100435{
436 m_v_r = (m_v_r + moves) & mod_sns();
437}
438
Holger Hans Peter Freyther7f3e6622013-11-25 23:51:19 +0100439inline void gprs_rlc_ul_window::raise_v_q(int incr)
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100440{
441 m_v_q = (m_v_q + incr) & mod_sns();
442}
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100443
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100444inline void gprs_rlc_v_n::mark_received(int bsn)
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100445{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100446 return mark(bsn, GPRS_RLC_UL_BSN_RECEIVED);
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100447}
448
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100449inline void gprs_rlc_v_n::mark_missing(int bsn)
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100450{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100451 return mark(bsn, GPRS_RLC_UL_BSN_MISSING);
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100452}
453
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100454inline bool gprs_rlc_v_n::is_received(int bsn) const
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100455{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100456 return is_state(bsn, GPRS_RLC_UL_BSN_RECEIVED);
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100457}
458
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100459inline bool gprs_rlc_v_n::is_state(int bsn, gprs_rlc_ul_bsn_state type) const
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100460{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100461 return m_v_n[bsn & mod_sns_half()] == type;
462}
463
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100464inline void gprs_rlc_v_n::mark(int bsn, gprs_rlc_ul_bsn_state type)
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100465{
466 m_v_n[bsn & mod_sns_half()] = type;
467}
468
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100469inline gprs_rlc_ul_bsn_state gprs_rlc_v_n::state(int bsn) const
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100470{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100471 return m_v_n[bsn & mod_sns_half()];
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100472}
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100473
474inline gprs_rlc_data *gprs_rlc::block(int bsn)
475{
476 return &m_blocks[bsn & mod_sns_half()];
477}