blob: f2acb98a3ff632e00d7bcbf359674606b4c80060 [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
Jacob Erlbeckb3100e12015-12-14 13:36:13 +010089 struct gprs_rlc_ul_data_block_info block_info;
Jacob Erlbeckce1beb42015-12-14 12:04:01 +010090 GprsCodingScheme cs;
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +010091};
92
93/*
94 * I hold the currently transferred blocks and will provide
95 * the routines to manipulate these arrays.
96 */
97struct gprs_rlc {
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +010098 gprs_rlc_data *block(int bsn);
99 gprs_rlc_data m_blocks[RLC_MAX_SNS/2];
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100100};
101
Daniel Willmann146514e2013-12-28 18:24:42 +0100102/**
103 * TODO: for GPRS/EDGE maybe make sns a template parameter
104 * so we create specialized versions...
105 */
106struct gprs_rlc_v_b {
107 /* Check for an individual frame */
108 bool is_unacked(int bsn) const;
109 bool is_nacked(int bsn) const;
110 bool is_acked(int bsn) const;
111 bool is_resend(int bsn) const;
112 bool is_invalid(int bsn) const;
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100113 gprs_rlc_dl_bsn_state get_state(int bsn) const;
Daniel Willmann146514e2013-12-28 18:24:42 +0100114
115 /* Mark a RLC frame for something */
116 void mark_unacked(int bsn);
117 void mark_nacked(int bsn);
118 void mark_acked(int bsn);
119 void mark_resend(int bsn);
120 void mark_invalid(int bsn);
121
122 void reset();
123
124
125private:
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100126 bool is_state(int bsn, const gprs_rlc_dl_bsn_state state) const;
127 void mark(int bsn, const gprs_rlc_dl_bsn_state state);
Daniel Willmann146514e2013-12-28 18:24:42 +0100128
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100129 gprs_rlc_dl_bsn_state m_v_b[RLC_MAX_SNS/2]; /* acknowledge state array */
Daniel Willmann146514e2013-12-28 18:24:42 +0100130};
131
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100132
133/**
134 * TODO: The UL/DL code could/should share a baseclass but
135 * we are using llist_for_each_entry for the TBF which
136 * requires everything which creates a requirement for a POD
137 * type and in < C++11 something that is using even if the
138 * most simple form of inheritance is not a POD anymore.
139 */
140struct gprs_rlc_dl_window {
Daniel Willmann7e994e32014-08-07 15:49:21 +0200141 void reset();
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100142 const uint16_t mod_sns() const;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100143 const uint16_t sns() const;
144 const uint16_t ws() const;
145
146 bool window_stalled() const;
147 bool window_empty() const;
148
149 void increment_send();
150 void raise(int moves);
151
152 const uint16_t v_s() const;
153 const uint16_t v_s_mod(int offset) const;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100154 const uint16_t v_a() const;
155 const int16_t distance() const;
156
Daniel Willmann146514e2013-12-28 18:24:42 +0100157 /* Methods to manage reception */
158 int resend_needed();
159 int mark_for_resend();
160 void update(BTS *bts, char *show_rbb, uint8_t ssn,
161 uint16_t *lost, uint16_t *received);
162 int move_window();
Daniel Willmann3ce011f2014-01-15 12:45:56 +0100163 void show_state(char *show_rbb);
Daniel Willmann146514e2013-12-28 18:24:42 +0100164 int count_unacked();
165
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100166 uint16_t m_v_s; /* send state */
167 uint16_t m_v_a; /* ack state */
Daniel Willmann146514e2013-12-28 18:24:42 +0100168
169 gprs_rlc_v_b m_v_b;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100170};
171
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100172struct gprs_rlc_v_n {
173 void reset();
174
175 void mark_received(int bsn);
176 void mark_missing(int bsn);
177
178 bool is_received(int bsn) const;
179
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100180 gprs_rlc_ul_bsn_state state(int bsn) const;
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100181private:
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100182 bool is_state(int bsn, const gprs_rlc_ul_bsn_state state) const;
183 void mark(int bsn, const gprs_rlc_ul_bsn_state state);
184 gprs_rlc_ul_bsn_state m_v_n[RLC_MAX_SNS/2]; /* receive state array */
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100185};
186
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100187struct gprs_rlc_ul_window {
188 const uint16_t mod_sns() const;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100189 const uint16_t sns() const;
190 const uint16_t ws() const;
191
192 const uint16_t v_r() const;
193 const uint16_t v_q() const;
194
Daniel Willmann8a31f9e2013-11-27 17:08:35 +0100195 const uint16_t ssn() const;
196
Holger Hans Peter Freyther6ab5b242013-11-24 22:43:03 +0100197 bool is_in_window(uint8_t bsn) const;
Jacob Erlbeck784a0bd2015-12-14 11:54:29 +0100198 bool is_received(uint8_t bsn) const;
Holger Hans Peter Freyther6ab5b242013-11-24 22:43:03 +0100199
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100200 void update_rbb(char *rbb);
Daniel Willmannf4a1ec62013-12-28 13:57:31 +0100201 void raise_v_r_to(int moves);
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100202 void raise_v_r(const uint16_t bsn);
203 uint16_t raise_v_q();
Holger Hans Peter Freythercbb00eb2013-11-25 23:26:06 +0100204
Holger Hans Peter Freyther7f3e6622013-11-25 23:51:19 +0100205 void raise_v_q(int);
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100206
Jacob Erlbeckd87e1d62015-12-14 11:43:04 +0100207 void receive_bsn(const uint16_t bsn);
Jacob Erlbeck784a0bd2015-12-14 11:54:29 +0100208 bool invalidate_bsn(const uint16_t bsn);
Daniel Willmann55844792013-12-28 14:41:00 +0100209
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100210 uint16_t m_v_r; /* receive state */
211 uint16_t m_v_q; /* receive window state */
Daniel Willmann7c3751b2013-12-28 13:59:24 +0100212
213 gprs_rlc_v_n m_v_n;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100214};
215
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200216extern "C" {
217/* TS 04.60 10.2.2 */
Jacob Erlbeck4aa78a82015-12-14 11:13:30 +0100218#if OSMO_IS_LITTLE_ENDIAN
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200219struct rlc_ul_header {
220 uint8_t r:1,
221 si:1,
222 cv:4,
223 pt:2;
224 uint8_t ti:1,
225 tfi:5,
226 pi:1,
227 spare:1;
228 uint8_t e:1,
229 bsn:7;
230} __attribute__ ((packed));
231
232struct rlc_dl_header {
233 uint8_t usf:3,
234 s_p:1,
235 rrbp:2,
236 pt:2;
237 uint8_t fbi:1,
238 tfi:5,
239 pr:2;
240 uint8_t e:1,
241 bsn:7;
242} __attribute__ ((packed));
243
244struct rlc_li_field {
245 uint8_t e:1,
246 m:1,
247 li:6;
248} __attribute__ ((packed));
Jacob Erlbeck4abc6862015-12-08 15:14:05 +0100249
250struct rlc_li_field_egprs {
251 uint8_t e:1,
252 li:7;
253} __attribute__ ((packed));
254
255struct gprs_rlc_ul_header_egprs_3 {
256 uint8_t r:1,
257 si:1,
258 cv:4,
259 tfi_a:2;
260 uint8_t tfi_b:3,
261 bsn1_a:5;
262 uint8_t bsn1_b:6,
263 cps_a:2;
264 uint8_t cps_b:2,
265 spb:2,
266 rsb:1,
267 pi:1,
268 spare:1,
269 dummy:1;
270} __attribute__ ((packed));
Jacob Erlbeck4aa78a82015-12-14 11:13:30 +0100271#else
272# error "Only little endian headers are supported yet. TODO: add missing structs"
273#endif
Holger Hans Peter Freytherd11290b2013-10-26 17:32:04 +0200274}
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100275
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100276inline 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 +0100277{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100278 return m_v_b[bsn & mod_sns_half()] == type;
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100279}
280
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100281inline void gprs_rlc_v_b::mark(int bsn, const gprs_rlc_dl_bsn_state type)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100282{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100283 m_v_b[bsn & mod_sns_half()] = type;
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100284}
285
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100286inline bool gprs_rlc_v_b::is_nacked(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100287{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100288 return is_state(bsn, GPRS_RLC_DL_BSN_NACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100289}
290
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100291inline bool gprs_rlc_v_b::is_acked(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100292{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100293 return is_state(bsn, GPRS_RLC_DL_BSN_ACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100294}
295
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100296inline bool gprs_rlc_v_b::is_unacked(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100297{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100298 return is_state(bsn, GPRS_RLC_DL_BSN_UNACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100299}
300
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100301inline bool gprs_rlc_v_b::is_resend(int bsn) const
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100302{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100303 return is_state(bsn, GPRS_RLC_DL_BSN_RESEND);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100304}
305
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100306inline bool gprs_rlc_v_b::is_invalid(int bsn) const
Holger Hans Peter Freyther95255672013-11-23 16:18:18 +0100307{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100308 return is_state(bsn, GPRS_RLC_DL_BSN_INVALID);
Holger Hans Peter Freyther95255672013-11-23 16:18:18 +0100309}
310
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100311inline gprs_rlc_dl_bsn_state gprs_rlc_v_b::get_state(int bsn) const
Daniel Willmann146514e2013-12-28 18:24:42 +0100312{
313 return m_v_b[bsn & mod_sns_half()];
314}
315
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100316inline void gprs_rlc_v_b::mark_resend(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100317{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100318 return mark(bsn, GPRS_RLC_DL_BSN_RESEND);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100319}
320
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100321inline void gprs_rlc_v_b::mark_unacked(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100322{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100323 return mark(bsn, GPRS_RLC_DL_BSN_UNACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100324}
325
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100326inline void gprs_rlc_v_b::mark_acked(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100327{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100328 return mark(bsn, GPRS_RLC_DL_BSN_ACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100329}
330
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100331inline void gprs_rlc_v_b::mark_nacked(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100332{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100333 return mark(bsn, GPRS_RLC_DL_BSN_NACKED);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100334}
335
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100336inline void gprs_rlc_v_b::mark_invalid(int bsn)
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100337{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100338 return mark(bsn, GPRS_RLC_DL_BSN_INVALID);
Holger Hans Peter Freyther6b5660c2013-11-23 16:10:48 +0100339}
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100340
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100341inline const uint16_t gprs_rlc_dl_window::sns() const
342{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100343 return RLC_MAX_SNS;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100344}
345
346inline const uint16_t gprs_rlc_dl_window::ws() const
347{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100348 return RLC_MAX_WS;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100349}
350
351inline const uint16_t gprs_rlc_dl_window::mod_sns() const
352{
353 return sns() - 1;
354}
355
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100356inline const uint16_t gprs_rlc_dl_window::v_s() const
357{
358 return m_v_s;
359}
360
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100361inline const uint16_t gprs_rlc_dl_window::v_s_mod(int offset) const
362{
363 return (m_v_s + offset) & mod_sns();
364}
365
366inline const uint16_t gprs_rlc_dl_window::v_a() const
367{
368 return m_v_a;
369}
370
371inline bool gprs_rlc_dl_window::window_stalled() const
372{
373 return ((m_v_s - m_v_a) & mod_sns()) == ws();
374}
375
376inline bool gprs_rlc_dl_window::window_empty() const
377{
378 return m_v_s == m_v_a;
379}
380
381inline void gprs_rlc_dl_window::increment_send()
382{
383 m_v_s = (m_v_s + 1) & mod_sns();
384}
385
386inline void gprs_rlc_dl_window::raise(int moves)
387{
388 m_v_a = (m_v_a + moves) & mod_sns();
389}
390
391inline const int16_t gprs_rlc_dl_window::distance() const
392{
393 return (m_v_s - m_v_a) & mod_sns();
394}
395
Holger Hans Peter Freyther6ab5b242013-11-24 22:43:03 +0100396inline bool gprs_rlc_ul_window::is_in_window(uint8_t bsn) const
397{
398 uint16_t offset_v_q;
399
400 /* current block relative to lowest unreceived block */
401 offset_v_q = (bsn - m_v_q) & mod_sns();
402 /* If out of window (may happen if blocks below V(Q) are received
403 * again. */
404 return offset_v_q < ws();
405}
406
Jacob Erlbeck784a0bd2015-12-14 11:54:29 +0100407inline bool gprs_rlc_ul_window::is_received(uint8_t bsn) const
408{
409 uint16_t offset_v_r;
410
411 /* Offset to the end of the received window */
412 offset_v_r = (m_v_r - 1 - bsn) & mod_sns();
413 return is_in_window(bsn) && m_v_n.is_received(bsn) && offset_v_r < ws();
414}
415
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100416inline const uint16_t gprs_rlc_ul_window::sns() const
417{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100418 return RLC_MAX_SNS;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100419}
420
421inline const uint16_t gprs_rlc_ul_window::ws() const
422{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100423 return RLC_MAX_WS;
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100424}
425
426inline const uint16_t gprs_rlc_ul_window::mod_sns() const
427{
428 return sns() - 1;
429}
430
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100431inline const uint16_t gprs_rlc_ul_window::v_r() const
432{
433 return m_v_r;
434}
435
436inline const uint16_t gprs_rlc_ul_window::v_q() const
437{
438 return m_v_q;
439}
440
Daniel Willmann8a31f9e2013-11-27 17:08:35 +0100441inline const uint16_t gprs_rlc_ul_window::ssn() const
442{
443 return m_v_r;
444}
445
Daniel Willmannf4a1ec62013-12-28 13:57:31 +0100446inline void gprs_rlc_ul_window::raise_v_r_to(int moves)
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100447{
448 m_v_r = (m_v_r + moves) & mod_sns();
449}
450
Holger Hans Peter Freyther7f3e6622013-11-25 23:51:19 +0100451inline void gprs_rlc_ul_window::raise_v_q(int incr)
Holger Hans Peter Freytherf1593b72013-11-24 20:36:36 +0100452{
453 m_v_q = (m_v_q + incr) & mod_sns();
454}
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100455
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100456inline void gprs_rlc_v_n::mark_received(int bsn)
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100457{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100458 return mark(bsn, GPRS_RLC_UL_BSN_RECEIVED);
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100459}
460
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100461inline void gprs_rlc_v_n::mark_missing(int bsn)
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100462{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100463 return mark(bsn, GPRS_RLC_UL_BSN_MISSING);
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100464}
465
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100466inline bool gprs_rlc_v_n::is_received(int bsn) const
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100467{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100468 return is_state(bsn, GPRS_RLC_UL_BSN_RECEIVED);
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100469}
470
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100471inline 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 +0100472{
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100473 return m_v_n[bsn & mod_sns_half()] == type;
474}
475
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100476inline void gprs_rlc_v_n::mark(int bsn, gprs_rlc_ul_bsn_state type)
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100477{
478 m_v_n[bsn & mod_sns_half()] = type;
479}
480
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100481inline gprs_rlc_ul_bsn_state gprs_rlc_v_n::state(int bsn) const
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100482{
Daniel Willmannd54d9f52013-12-28 21:16:13 +0100483 return m_v_n[bsn & mod_sns_half()];
Holger Hans Peter Freyther270f7fc2013-11-24 20:55:02 +0100484}
Holger Hans Peter Freyther3cbf9e02013-11-26 21:43:58 +0100485
486inline gprs_rlc_data *gprs_rlc::block(int bsn)
487{
488 return &m_blocks[bsn & mod_sns_half()];
489}